1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
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. */
25 /* On 4.3 these lose if they come after xterm.h. */
26 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
27 /* Putting these at the beginning seems to be standard for other .c files. */
40 #include "blockinput.h"
42 /* Need syssignal.h for various externs and definitions that may be required
43 by some configurations for calls to signal later in this source file. */
44 #include "syssignal.h"
46 /* This may include sys/types.h, and that somehow loses
47 if this is not done before the other system files. */
49 #include <X11/cursorfont.h>
52 /* Load sys/types.h if not already loaded.
53 In some systems loading it twice is suicidal. */
55 #include <sys/types.h>
60 #include <sys/ioctl.h>
61 #endif /* ! defined (BSD_SYSTEM) */
66 #ifndef INCLUDED_FCNTL
73 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
74 /* #include <sys/param.h> */
80 #include "dispextern.h"
81 #include "termhooks.h"
93 #include "intervals.h"
97 #include <X11/Shell.h>
100 #include <sys/types.h>
101 #ifdef HAVE_SYS_TIME_H
102 #include <sys/time.h>
110 extern void free_frame_menubar ();
111 extern FRAME_PTR
x_menubar_window_to_frame ();
113 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
115 extern void _XEditResCheckMessages ();
116 #endif /* not NO_EDITRES */
118 /* Include toolkit specific headers for the scroll bar widget. */
120 #ifdef USE_TOOLKIT_SCROLL_BARS
121 #if defined USE_MOTIF
122 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
123 #include <Xm/ScrollBar.h>
124 #include <Xm/ScrollBarP.h>
125 #elif defined HAVE_XAW3D
126 #include <X11/Xaw3d/Simple.h>
127 #include <X11/Xaw3d/ThreeD.h>
128 #include <X11/Xaw3d/Scrollbar.h>
129 #define ARROW_SCROLLBAR
130 #include <X11/Xaw3d/ScrollbarP.h>
131 #endif /* HAVE_XAW3D */
132 #endif /* USE_TOOLKIT_SCROLL_BARS */
134 #endif /* USE_X_TOOLKIT */
136 #ifndef USE_X_TOOLKIT
137 #define x_any_window_to_frame x_window_to_frame
138 #define x_top_window_to_frame x_window_to_frame
143 #ifndef XtNinitialState
144 #define XtNinitialState "initialState"
148 #ifdef HAVE_SETLOCALE
149 /* So we can do setlocale. */
154 /* memmove will be defined as a macro in Xfuncs.h unless
155 <string.h> is included beforehand. The declaration for memmove in
156 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
161 #define min(a,b) ((a) < (b) ? (a) : (b))
164 #define max(a,b) ((a) > (b) ? (a) : (b))
167 #define abs(x) ((x) < 0 ? -(x) : (x))
169 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
172 /* Bitmaps for truncated lines. */
177 LEFT_TRUNCATION_BITMAP
,
178 RIGHT_TRUNCATION_BITMAP
,
179 OVERLAY_ARROW_BITMAP
,
180 CONTINUED_LINE_BITMAP
,
181 CONTINUATION_LINE_BITMAP
,
185 /* Bitmap drawn to indicate lines not displaying text if
186 `indicate-empty-lines' is non-nil. */
190 static unsigned char zv_bits
[] = {
191 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
193 /* An arrow like this: `<-'. */
196 #define left_height 8
197 static unsigned char left_bits
[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
200 /* Marker for continued lines. */
202 #define continued_width 8
203 #define continued_height 8
204 static unsigned char continued_bits
[] = {
205 0x30, 0x30, 0x30, 0x30, 0xb4, 0xfc, 0x78, 0x30};
207 #define continuation_width 8
208 #define continuation_height 8
209 static unsigned char continuation_bits
[] = {
210 0x0c, 0x1e, 0x3f, 0x2d, 0x0c, 0x0c, 0x0c, 0x0c};
212 /* Right truncation arrow bitmap `->'. */
214 #define right_width 8
215 #define right_height 8
216 static unsigned char right_bits
[] = {
217 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
219 /* Overlay arrow bitmap; a filled `<>'. */
224 static unsigned char ov_bits
[] = {
225 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
230 static unsigned char ov_bits
[] = {
231 0x18, 0x04, 0x08, 0x1c, 0x3e, 0x3a, 0x32, 0x1c};
235 static unsigned char ov_bits
[] = {
236 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18};
239 extern Lisp_Object Qhelp_echo
;
242 /* Non-zero means Emacs uses toolkit scroll bars. */
244 int x_toolkit_scroll_bars_p
;
246 /* If a string, XTread_socket generates an event to display that string.
247 (The display is done in read_char.) */
249 static Lisp_Object help_echo
;
251 /* Temporary variable for XTread_socket. */
253 static Lisp_Object previous_help_echo
;
255 /* Non-zero means that a HELP_EVENT has been generated since Emacs
258 static int any_help_event_p
;
260 /* Non-zero means draw block and hollow cursor as wide as the glyph
261 under it. For example, if a block cursor is over a tab, it will be
262 drawn as wide as that tab on the display. */
264 int x_stretch_cursor_p
;
266 /* This is a chain of structures for all the X displays currently in
269 struct x_display_info
*x_display_list
;
271 /* This is a list of cons cells, each of the form (NAME
272 . FONT-LIST-CACHE), one for each element of x_display_list and in
273 the same order. NAME is the name of the frame. FONT-LIST-CACHE
274 records previous values returned by x-list-fonts. */
276 Lisp_Object x_display_name_list
;
278 /* Frame being updated by update_frame. This is declared in term.c.
279 This is set by update_begin and looked at by all the XT functions.
280 It is zero while not inside an update. In that case, the XT
281 functions assume that `selected_frame' is the frame to apply to. */
283 extern struct frame
*updating_frame
;
285 extern int waiting_for_input
;
287 /* This is a frame waiting to be auto-raised, within XTread_socket. */
289 struct frame
*pending_autoraise_frame
;
292 /* The application context for Xt use. */
293 XtAppContext Xt_app_con
;
294 static String Xt_default_resources
[] = {0};
295 #endif /* USE_X_TOOLKIT */
297 /* Nominal cursor position -- where to draw output.
298 HPOS and VPOS are window relative glyph matrix coordinates.
299 X and Y are window relative pixel coordinates. */
301 struct cursor_pos output_cursor
;
306 Formerly, we used PointerMotionHintMask (in standard_event_mask)
307 so that we would have to call XQueryPointer after each MotionNotify
308 event to ask for another such event. However, this made mouse tracking
309 slow, and there was a bug that made it eventually stop.
311 Simply asking for MotionNotify all the time seems to work better.
313 In order to avoid asking for motion events and then throwing most
314 of them away or busy-polling the server for mouse positions, we ask
315 the server for pointer motion hints. This means that we get only
316 one event per group of mouse movements. "Groups" are delimited by
317 other kinds of events (focus changes and button clicks, for
318 example), or by XQueryPointer calls; when one of these happens, we
319 get another MotionNotify event the next time the mouse moves. This
320 is at least as efficient as getting motion events when mouse
321 tracking is on, and I suspect only negligibly worse when tracking
324 /* Where the mouse was last time we reported a mouse event. */
326 FRAME_PTR last_mouse_frame
;
327 static XRectangle last_mouse_glyph
;
328 static Lisp_Object last_mouse_press_frame
;
330 /* The scroll bar in which the last X motion event occurred.
332 If the last X motion event occurred in a scroll bar, we set this so
333 XTmouse_position can know whether to report a scroll bar motion or
336 If the last X motion event didn't occur in a scroll bar, we set
337 this to Qnil, to tell XTmouse_position to return an ordinary motion
340 static Lisp_Object last_mouse_scroll_bar
;
342 /* This is a hack. We would really prefer that XTmouse_position would
343 return the time associated with the position it returns, but there
344 doesn't seem to be any way to wrest the time-stamp from the server
345 along with the position query. So, we just keep track of the time
346 of the last movement we received, and return that in hopes that
347 it's somewhat accurate. */
349 static Time last_mouse_movement_time
;
351 /* Incremented by XTread_socket whenever it really tries to read
355 static int volatile input_signal_count
;
357 static int input_signal_count
;
360 /* Used locally within XTread_socket. */
362 static int x_noop_count
;
364 /* Initial values of argv and argc. */
366 extern char **initial_argv
;
367 extern int initial_argc
;
369 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
371 /* Tells if a window manager is present or not. */
373 extern Lisp_Object Vx_no_window_manager
;
375 extern Lisp_Object Qface
, Qmouse_face
;
379 /* A mask of extra modifier bits to put into every keyboard char. */
381 extern int extra_keyboard_modifiers
;
383 static Lisp_Object Qvendor_specific_keysyms
;
385 extern XrmDatabase
x_load_resources ();
386 extern Lisp_Object
x_icon_type ();
389 /* Enumeration for overriding/changing the face to use for drawing
390 glyphs in x_draw_glyphs. */
392 enum draw_glyphs_face
402 static void x_update_window_end
P_ ((struct window
*, int));
403 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
404 void x_delete_display
P_ ((struct x_display_info
*));
405 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
407 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
409 static void set_output_cursor
P_ ((struct cursor_pos
*));
410 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
411 int *, int *, int *));
412 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
413 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
414 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
415 static void note_toolbar_highlight
P_ ((struct frame
*f
, int, int));
416 static void x_handle_toolbar_click
P_ ((struct frame
*, XButtonEvent
*));
417 static void show_mouse_face
P_ ((struct x_display_info
*,
418 enum draw_glyphs_face
));
419 static int x_io_error_quitter
P_ ((Display
*));
420 int x_catch_errors
P_ ((Display
*));
421 void x_uncatch_errors
P_ ((Display
*, int));
422 void x_lower_frame
P_ ((struct frame
*));
423 void x_scroll_bar_clear
P_ ((struct frame
*));
424 int x_had_errors_p
P_ ((Display
*));
425 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
426 void x_raise_frame
P_ ((struct frame
*));
427 void x_set_window_size
P_ ((struct frame
*, int, int, int));
428 void x_wm_set_window_state
P_ ((struct frame
*, int));
429 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
430 void x_initialize
P_ ((void));
431 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
432 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
433 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
435 enum draw_glyphs_face
));
436 static void x_update_end
P_ ((struct frame
*));
437 static void XTframe_up_to_date
P_ ((struct frame
*));
438 static void XTreassert_line_highlight
P_ ((int, int));
439 static void x_change_line_highlight
P_ ((int, int, int, int));
440 static void XTset_terminal_modes
P_ ((void));
441 static void XTreset_terminal_modes
P_ ((void));
442 static void XTcursor_to
P_ ((int, int, int, int));
443 static void x_write_glyphs
P_ ((struct glyph
*, int));
444 static void x_clear_end_of_line
P_ ((int));
445 static void x_clear_frame
P_ ((void));
446 static void x_clear_cursor
P_ ((struct window
*));
447 static void frame_highlight
P_ ((struct frame
*));
448 static void frame_unhighlight
P_ ((struct frame
*));
449 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
450 static void XTframe_rehighlight
P_ ((struct frame
*));
451 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
452 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
453 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*));
454 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
456 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
457 static void expose_window_tree
P_ ((struct window
*, XRectangle
*));
458 static void expose_window
P_ ((struct window
*, XRectangle
*));
459 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
460 XRectangle
*, enum glyph_row_area
));
461 static void expose_line
P_ ((struct window
*, struct glyph_row
*,
463 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
464 static void x_update_window_cursor
P_ ((struct window
*, int));
465 static void x_erase_phys_cursor
P_ ((struct window
*));
466 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
467 static void x_draw_bitmap
P_ ((struct window
*, struct glyph_row
*,
470 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
472 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
473 static void x_draw_row_bitmaps
P_ ((struct window
*, struct glyph_row
*));
474 static void note_overwritten_text_cursor
P_ ((struct window
*, int, int));
475 static void x_flush
P_ ((struct frame
*f
));
478 /* Flush display of frame F, or of all frames if F is null. */
487 Lisp_Object rest
, frame
;
488 FOR_EACH_FRAME (rest
, frame
)
489 x_flush (XFRAME (frame
));
491 else if (FRAME_X_P (f
))
492 XFlush (FRAME_X_DISPLAY (f
));
497 /* Remove calls to XFlush by defining XFlush to an empty replacement.
498 Calls to XFlush should be unnecessary because the X output buffer
499 is flushed automatically as needed by calls to XPending,
500 XNextEvent, or XWindowEvent according to the XFlush man page.
501 XTread_socket calls XPending. Removing XFlush improves
504 #define XFlush(DISPLAY) (void) 0
507 /***********************************************************************
509 ***********************************************************************/
513 /* This is a function useful for recording debugging information about
514 the sequence of occurrences in this file. */
522 struct record event_record
[100];
524 int event_record_index
;
526 record_event (locus
, type
)
530 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
531 event_record_index
= 0;
533 event_record
[event_record_index
].locus
= locus
;
534 event_record
[event_record_index
].type
= type
;
535 event_record_index
++;
542 /* Return the struct x_display_info corresponding to DPY. */
544 struct x_display_info
*
545 x_display_info_for_display (dpy
)
548 struct x_display_info
*dpyinfo
;
550 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
551 if (dpyinfo
->display
== dpy
)
559 /***********************************************************************
560 Starting and ending an update
561 ***********************************************************************/
563 /* Start an update of frame F. This function is installed as a hook
564 for update_begin, i.e. it is called when update_begin is called.
565 This function is called prior to calls to x_update_window_begin for
566 each window being updated. Currently, there is nothing to do here
567 because all interesting stuff is done on a window basis. */
577 /* Start update of window W. Set the global variable updated_window
578 to the window being updated and set output_cursor to the cursor
582 x_update_window_begin (w
)
585 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
586 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
589 set_output_cursor (&w
->cursor
);
593 if (f
== display_info
->mouse_face_mouse_frame
)
595 /* Don't do highlighting for mouse motion during the update. */
596 display_info
->mouse_face_defer
= 1;
598 /* If F needs to be redrawn, simply forget about any prior mouse
600 if (FRAME_GARBAGED_P (f
))
601 display_info
->mouse_face_window
= Qnil
;
603 /* Can we tell that this update does not affect the window
604 where the mouse highlight is? If so, no need to turn off.
605 Likewise, don't do anything if the frame is garbaged;
606 in that case, the frame's current matrix that we would use
607 is all wrong, and we will redisplay that line anyway. */
608 if (!NILP (display_info
->mouse_face_window
)
609 && w
== XWINDOW (display_info
->mouse_face_window
))
613 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
614 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
617 if (i
< w
->desired_matrix
->nrows
)
618 clear_mouse_face (display_info
);
626 /* Draw a vertical window border to the right of window W if W doesn't
627 have vertical scroll bars. */
630 x_draw_vertical_border (w
)
633 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
635 /* Redraw borders between horizontally adjacent windows. Don't
636 do it for frames with vertical scroll bars because either the
637 right scroll bar of a window, or the left scroll bar of its
638 neighbor will suffice as a border. */
639 if (!WINDOW_RIGHTMOST_P (w
)
640 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
644 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
645 x1
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
648 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
649 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
654 /* End update of window W (which is equal to updated_window). Draw
655 vertical borders between horizontally adjacent windows, and display
656 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
657 pseudo-window in case we don't have X toolkit support. Such
658 windows don't have a cursor, so don't display it here. */
661 x_update_window_end (w
, cursor_on_p
)
665 if (!w
->pseudo_window_p
)
669 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
671 output_cursor
.x
, output_cursor
.y
);
672 x_draw_vertical_border (w
);
676 updated_window
= NULL
;
680 /* End update of frame F. This function is installed as a hook in
687 /* Mouse highlight may be displayed again. */
688 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
691 XFlush (FRAME_X_DISPLAY (f
));
696 /* This function is called from various places in xdisp.c whenever a
697 complete update has been performed. The global variable
698 updated_window is not available here. */
701 XTframe_up_to_date (f
)
706 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
707 if (dpyinfo
->mouse_face_deferred_gc
708 || f
== dpyinfo
->mouse_face_mouse_frame
)
711 if (dpyinfo
->mouse_face_mouse_frame
)
712 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
713 dpyinfo
->mouse_face_mouse_x
,
714 dpyinfo
->mouse_face_mouse_y
);
715 dpyinfo
->mouse_face_deferred_gc
= 0;
722 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
723 arrow bitmaps, or clear the areas where they would be displayed
724 before DESIRED_ROW is made current. The window being updated is
725 found in updated_window. This function It is called from
726 update_window_line only if it is known that there are differences
727 between bitmaps to be drawn between current row and DESIRED_ROW. */
730 x_after_update_window_line (desired_row
)
731 struct glyph_row
*desired_row
;
733 struct window
*w
= updated_window
;
737 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
740 x_draw_row_bitmaps (w
, desired_row
);
742 /* When a window has disappeared, make sure that no rest of
743 full-width rows stays visible in the internal border. */
744 if (windows_or_buffers_changed
)
746 struct frame
*f
= XFRAME (w
->frame
);
747 int width
= FRAME_INTERNAL_BORDER_WIDTH (f
);
748 int height
= desired_row
->visible_height
;
749 int x
= window_box_right (w
, -1) + FRAME_X_FLAGS_AREA_WIDTH (f
);
750 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
752 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
753 x
, y
, width
, height
, False
);
761 /* Draw the bitmap WHICH in one of the areas to the left or right of
762 window W. ROW is the glyph row for which to display the bitmap; it
763 determines the vertical position at which the bitmap has to be
767 x_draw_bitmap (w
, row
, which
)
769 struct glyph_row
*row
;
770 enum bitmap_type which
;
772 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
773 Display
*display
= FRAME_X_DISPLAY (f
);
774 Window window
= FRAME_X_WINDOW (f
);
778 GC gc
= f
->output_data
.x
->normal_gc
;
780 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
782 /* Must clip because of partially visible lines. */
783 x_clip_to_row (w
, row
, gc
, 1);
787 case LEFT_TRUNCATION_BITMAP
:
791 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
793 - (FRAME_X_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
796 case OVERLAY_ARROW_BITMAP
:
800 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
802 - (FRAME_X_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
805 case RIGHT_TRUNCATION_BITMAP
:
809 x
= window_box_right (w
, -1);
810 x
+= (FRAME_X_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
813 case CONTINUED_LINE_BITMAP
:
816 bits
= continued_bits
;
817 x
= window_box_right (w
, -1);
818 x
+= (FRAME_X_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
821 case CONTINUATION_LINE_BITMAP
:
822 wd
= continuation_width
;
823 h
= continuation_height
;
824 bits
= continuation_bits
;
825 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
827 - (FRAME_X_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
834 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
836 - (FRAME_X_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
843 /* Convert to frame coordinates. Set dy to the offset in the row to
844 start drawing the bitmap. */
845 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
846 dy
= (row
->height
- h
) / 2;
848 /* Draw the bitmap. I believe these small pixmaps can be cached
850 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
851 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
853 face
->background
, depth
);
854 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
855 XFreePixmap (display
, pixmap
);
856 XSetClipMask (display
, gc
, None
);
860 /* Draw flags bitmaps for glyph row ROW on window W. Call this
861 function with input blocked. */
864 x_draw_row_bitmaps (w
, row
)
866 struct glyph_row
*row
;
868 struct frame
*f
= XFRAME (w
->frame
);
869 enum bitmap_type bitmap
;
871 int top_line_height
= -1;
873 xassert (interrupt_input_blocked
);
875 /* If row is completely invisible, because of vscrolling, we
876 don't have to draw anything. */
877 if (row
->visible_height
<= 0)
880 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
881 PREPARE_FACE_FOR_DISPLAY (f
, face
);
883 /* Decide which bitmap to draw at the left side. */
884 if (row
->overlay_arrow_p
)
885 bitmap
= OVERLAY_ARROW_BITMAP
;
886 else if (row
->truncated_on_left_p
)
887 bitmap
= LEFT_TRUNCATION_BITMAP
;
888 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
889 bitmap
= CONTINUATION_LINE_BITMAP
;
890 else if (row
->indicate_empty_line_p
)
891 bitmap
= ZV_LINE_BITMAP
;
895 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
897 if (bitmap
== NO_BITMAP
898 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_FLAGS_AREA_WIDTH (f
)
899 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
901 /* If W has a vertical border to its left, don't draw over it. */
902 int border
= ((XFASTINT (w
->left
) > 0
903 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
905 int left
= window_box_left (w
, -1);
907 if (top_line_height
< 0)
908 top_line_height
= WINDOW_DISPLAY_TOP_LINE_HEIGHT (w
);
909 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
910 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
913 - FRAME_X_FLAGS_AREA_WIDTH (f
)
915 WINDOW_TO_FRAME_PIXEL_Y (w
, max (top_line_height
,
917 FRAME_X_FLAGS_AREA_WIDTH (f
) - border
,
918 row
->visible_height
);
919 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
922 /* Draw the left bitmap. */
923 if (bitmap
!= NO_BITMAP
)
924 x_draw_bitmap (w
, row
, bitmap
);
926 /* Decide which bitmap to draw at the right side. */
927 if (row
->truncated_on_right_p
)
928 bitmap
= RIGHT_TRUNCATION_BITMAP
;
929 else if (row
->continued_p
)
930 bitmap
= CONTINUED_LINE_BITMAP
;
934 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
936 if (bitmap
== NO_BITMAP
937 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_FLAGS_AREA_WIDTH (f
)
938 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
940 int right
= window_box_right (w
, -1);
942 if (top_line_height
< 0)
943 top_line_height
= WINDOW_DISPLAY_TOP_LINE_HEIGHT (w
);
944 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
945 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
948 WINDOW_TO_FRAME_PIXEL_Y (w
, max (top_line_height
,
950 FRAME_X_FLAGS_AREA_WIDTH (f
),
951 row
->visible_height
);
952 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
955 /* Draw the right bitmap. */
956 if (bitmap
!= NO_BITMAP
)
957 x_draw_bitmap (w
, row
, bitmap
);
961 /***********************************************************************
963 ***********************************************************************/
965 /* External interface to control of standout mode. Not used for X
966 frames. Aborts when called. */
969 XTreassert_line_highlight (new, vpos
)
976 /* Call this when about to modify line at position VPOS and change
977 whether it is highlighted. Not used for X frames. Aborts when
981 x_change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
982 int new_highlight
, vpos
, y
, first_unused_hpos
;
988 /* This is called when starting Emacs and when restarting after
989 suspend. When starting Emacs, no X window is mapped. And nothing
990 must be done to Emacs's own window if it is suspended (though that
994 XTset_terminal_modes ()
998 /* This is called when exiting or suspending Emacs. Exiting will make
999 the X-windows go away, and suspending requires no action. */
1002 XTreset_terminal_modes ()
1008 /***********************************************************************
1010 ***********************************************************************/
1012 /* Set the global variable output_cursor to CURSOR. All cursor
1013 positions are relative to updated_window. */
1016 set_output_cursor (cursor
)
1017 struct cursor_pos
*cursor
;
1019 output_cursor
.hpos
= cursor
->hpos
;
1020 output_cursor
.vpos
= cursor
->vpos
;
1021 output_cursor
.x
= cursor
->x
;
1022 output_cursor
.y
= cursor
->y
;
1026 /* Set a nominal cursor position.
1028 HPOS and VPOS are column/row positions in a window glyph matrix. X
1029 and Y are window text area relative pixel positions.
1031 If this is done during an update, updated_window will contain the
1032 window that is being updated and the position is the future output
1033 cursor position for that window. If updated_window is null, use
1034 selected_window and display the cursor at the given position. */
1037 XTcursor_to (vpos
, hpos
, y
, x
)
1038 int vpos
, hpos
, y
, x
;
1042 /* If updated_window is not set, work on selected_window. */
1046 w
= XWINDOW (selected_window
);
1048 /* Set the output cursor. */
1049 output_cursor
.hpos
= hpos
;
1050 output_cursor
.vpos
= vpos
;
1051 output_cursor
.x
= x
;
1052 output_cursor
.y
= y
;
1054 /* If not called as part of an update, really display the cursor.
1055 This will also set the cursor position of W. */
1056 if (updated_window
== NULL
)
1059 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1060 XFlush (FRAME_X_DISPLAY (selected_frame
));
1067 /***********************************************************************
1069 ***********************************************************************/
1071 /* Function prototypes of this page. */
1073 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1076 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1077 int, XChar2b
*, int));
1078 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1079 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1080 static void x_append_glyph
P_ ((struct it
*));
1081 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1083 static void x_produce_glyphs
P_ ((struct it
*));
1084 static void x_produce_special_glyphs
P_ ((struct it
*, enum display_element_type
));
1085 static void x_produce_image_glyph
P_ ((struct it
*it
));
1088 /* Return a pointer to per-char metric information in FONT of a
1089 character pointed by B which is a pointer to an XChar2b. */
1091 #define PER_CHAR_METRIC(font, b) \
1093 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1094 + (((font)->min_byte1 || (font)->max_byte1) \
1095 ? (((b)->byte1 - (font)->min_byte1) \
1096 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1098 : &((font)->max_bounds))
1101 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1102 If CHAR2B is not contained in FONT, the font's default character
1103 metric is returned. */
1105 static INLINE XCharStruct
*
1106 x_per_char_metric (font
, char2b
)
1110 /* The result metric information. */
1111 XCharStruct
*pcm
= NULL
;
1113 xassert (font
&& char2b
);
1115 if (font
->per_char
!= NULL
)
1117 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1119 /* min_char_or_byte2 specifies the linear character index
1120 corresponding to the first element of the per_char array,
1121 max_char_or_byte2 is the index of the last character. A
1122 character with non-zero CHAR2B->byte1 is not in the font.
1123 A character with byte2 less than min_char_or_byte2 or
1124 greater max_char_or_byte2 is not in the font. */
1125 if (char2b
->byte1
== 0
1126 && char2b
->byte2
>= font
->min_char_or_byte2
1127 && char2b
->byte2
<= font
->max_char_or_byte2
)
1128 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1132 /* If either min_byte1 or max_byte1 are nonzero, both
1133 min_char_or_byte2 and max_char_or_byte2 are less than
1134 256, and the 2-byte character index values corresponding
1135 to the per_char array element N (counting from 0) are:
1137 byte1 = N/D + min_byte1
1138 byte2 = N\D + min_char_or_byte2
1142 D = max_char_or_byte2 - min_char_or_byte2 + 1
1143 / = integer division
1144 \ = integer modulus */
1145 if (char2b
->byte1
>= font
->min_byte1
1146 && char2b
->byte1
<= font
->max_byte1
1147 && char2b
->byte2
>= font
->min_char_or_byte2
1148 && char2b
->byte2
<= font
->max_char_or_byte2
)
1150 pcm
= (font
->per_char
1151 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1152 * (char2b
->byte1
- font
->min_byte1
))
1153 + (char2b
->byte2
- font
->min_char_or_byte2
));
1159 /* If the per_char pointer is null, all glyphs between the first
1160 and last character indexes inclusive have the same
1161 information, as given by both min_bounds and max_bounds. */
1162 if (char2b
->byte2
>= font
->min_char_or_byte2
1163 && char2b
->byte2
<= font
->max_char_or_byte2
)
1164 pcm
= &font
->max_bounds
;
1168 if (pcm
== NULL
|| pcm
->width
== 0)
1170 /* Character not contained in the font. FONT->default_char
1171 gives the character that will be printed. FONT->default_char
1172 is a 16-bit character code with byte1 in the most significant
1173 byte and byte2 in the least significant byte. */
1174 XChar2b default_char
;
1175 default_char
.byte1
= (font
->default_char
>> BITS_PER_CHAR
) & 0xff;
1176 default_char
.byte2
= font
->default_char
& 0xff;
1178 /* Avoid an endless recursion if FONT->default_char itself
1179 hasn't per char metrics. handa@etl.go.jp reports that some
1180 fonts have this problem. */
1181 if (default_char
.byte1
!= char2b
->byte1
1182 || default_char
.byte2
!= char2b
->byte2
)
1183 pcm
= x_per_char_metric (font
, &default_char
);
1185 pcm
= &font
->max_bounds
;
1192 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1193 the two-byte form of C. Encoding is returned in *CHAR2B. */
1196 x_encode_char (c
, char2b
, font_info
)
1199 struct font_info
*font_info
;
1201 int charset
= CHAR_CHARSET (c
);
1202 XFontStruct
*font
= font_info
->font
;
1204 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1205 This may be either a program in a special encoder language or a
1207 if (font_info
->font_encoder
)
1209 /* It's a program. */
1210 struct ccl_program
*ccl
= font_info
->font_encoder
;
1212 if (CHARSET_DIMENSION (charset
) == 1)
1214 ccl
->reg
[0] = charset
;
1215 ccl
->reg
[1] = char2b
->byte2
;
1219 ccl
->reg
[0] = charset
;
1220 ccl
->reg
[1] = char2b
->byte1
;
1221 ccl
->reg
[2] = char2b
->byte2
;
1224 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1226 /* We assume that MSBs are appropriately set/reset by CCL
1228 if (font
->max_byte1
== 0) /* 1-byte font */
1229 char2b
->byte2
= ccl
->reg
[1];
1231 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1233 else if (font_info
->encoding
[charset
])
1235 /* Fixed encoding scheme. See fontset.h for the meaning of the
1236 encoding numbers. */
1237 int enc
= font_info
->encoding
[charset
];
1239 if ((enc
== 1 || enc
== 2)
1240 && CHARSET_DIMENSION (charset
) == 2)
1241 char2b
->byte1
|= 0x80;
1243 if (enc
== 1 || enc
== 3)
1244 char2b
->byte2
|= 0x80;
1249 /* Get face and two-byte form of character C in face FACE_ID on frame
1250 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1251 means we want to display multibyte text. Value is a pointer to a
1252 realized face that is ready for display. */
1254 static INLINE
struct face
*
1255 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1261 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1265 /* Unibyte case. We don't have to encode, but we have to make
1266 sure to use a face suitable for unibyte. */
1270 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, -1))
1272 face_id
= FACE_FOR_CHARSET (f
, face_id
, -1);
1273 face
= FACE_FROM_ID (f
, face_id
);
1276 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1278 /* Case of ASCII in a face known to fit ASCII. */
1284 int c1
, c2
, charset
;
1286 /* Split characters into bytes. If c2 is -1 afterwards, C is
1287 really a one-byte character so that byte1 is zero. */
1288 SPLIT_CHAR (c
, charset
, c1
, c2
);
1290 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1292 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1294 /* Get the face for displaying C. If `face' is not suitable for
1295 charset, get the one that fits. (This can happen for the
1296 translations of composite characters where the glyph
1297 specifies a face for ASCII, but translations have a different
1299 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, charset
))
1301 face_id
= FACE_FOR_CHARSET (f
, face_id
, charset
);
1302 face
= FACE_FROM_ID (f
, face_id
);
1305 /* Maybe encode the character in *CHAR2B. */
1306 if (charset
!= CHARSET_ASCII
)
1308 struct font_info
*font_info
1309 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1312 x_encode_char (c
, char2b
, font_info
);
1313 if (charset
== charset_latin_iso8859_1
)
1315 xassert (((XFontStruct
*) font_info
->font
)->max_char_or_byte2
1317 char2b
->byte2
|= 0x80;
1323 /* Make sure X resources of the face are allocated. */
1324 xassert (face
!= NULL
);
1325 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1331 /* Get face and two-byte form of character glyph GLYPH on frame F.
1332 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1333 a pointer to a realized face that is ready for display. */
1335 static INLINE
struct face
*
1336 x_get_glyph_face_and_encoding (f
, glyph
, char2b
)
1338 struct glyph
*glyph
;
1343 xassert (glyph
->type
== CHAR_GLYPH
);
1344 face
= FACE_FROM_ID (f
, glyph
->u
.ch
.face_id
);
1346 if (!glyph
->multibyte_p
)
1348 /* Unibyte case. We don't have to encode, but we have to make
1349 sure to use a face suitable for unibyte. */
1351 char2b
->byte2
= glyph
->u
.ch
.code
;
1353 else if (glyph
->u
.ch
.code
< 128
1354 && glyph
->u
.ch
.face_id
< BASIC_FACE_ID_SENTINEL
)
1356 /* Case of ASCII in a face known to fit ASCII. */
1358 char2b
->byte2
= glyph
->u
.ch
.code
;
1362 int c1
, c2
, charset
;
1364 /* Split characters into bytes. If c2 is -1 afterwards, C is
1365 really a one-byte character so that byte1 is zero. */
1366 SPLIT_CHAR (glyph
->u
.ch
.code
, charset
, c1
, c2
);
1368 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1370 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1372 /* Maybe encode the character in *CHAR2B. */
1373 if (charset
!= CHARSET_ASCII
)
1375 struct font_info
*font_info
1376 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1379 x_encode_char (glyph
->u
.ch
.code
, char2b
, font_info
);
1380 if (charset
== charset_latin_iso8859_1
)
1381 char2b
->byte2
|= 0x80;
1386 /* Make sure X resources of the face are allocated. */
1387 xassert (face
!= NULL
);
1388 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1393 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1394 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1400 struct glyph
*glyph
;
1401 enum glyph_row_area area
= it
->area
;
1403 xassert (it
->glyph_row
);
1404 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1406 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1407 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1409 /* Play it safe. If sub-structures of the glyph are not all the
1410 same size, it otherwise be that some bits stay set. This
1411 would prevent a comparison with GLYPH_EQUAL_P. */
1414 glyph
->type
= CHAR_GLYPH
;
1415 glyph
->pixel_width
= it
->pixel_width
;
1416 glyph
->u
.ch
.code
= it
->char_to_display
;
1417 glyph
->u
.ch
.face_id
= it
->face_id
;
1418 glyph
->charpos
= CHARPOS (it
->position
);
1419 glyph
->object
= it
->object
;
1420 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1421 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1422 glyph
->voffset
= it
->voffset
;
1423 glyph
->multibyte_p
= it
->multibyte_p
;
1424 ++it
->glyph_row
->used
[area
];
1429 /* Change IT->ascent and IT->height according to the setting of
1433 take_vertical_position_into_account (it
)
1438 if (it
->voffset
< 0)
1439 /* Increase the ascent so that we can display the text higher
1441 it
->ascent
+= abs (it
->voffset
);
1443 /* Increase the descent so that we can display the text lower
1445 it
->descent
+= it
->voffset
;
1450 /* Produce glyphs/get display metrics for the image IT is loaded with.
1451 See the description of struct display_iterator in dispextern.h for
1452 an overview of struct display_iterator. */
1455 x_produce_image_glyph (it
)
1461 xassert (it
->what
== IT_IMAGE
);
1463 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1464 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1467 /* Make sure X resources of the face and image are loaded. */
1468 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1469 prepare_image_for_display (it
->f
, img
);
1471 it
->ascent
= IMAGE_ASCENT (img
);
1472 it
->descent
= img
->height
+ 2 * img
->margin
- it
->ascent
;
1473 it
->pixel_width
= img
->width
+ 2 * img
->margin
;
1477 if (face
->box
!= FACE_NO_BOX
)
1479 it
->ascent
+= face
->box_line_width
;
1480 it
->descent
+= face
->box_line_width
;
1482 if (it
->start_of_box_run_p
)
1483 it
->pixel_width
+= face
->box_line_width
;
1484 if (it
->end_of_box_run_p
)
1485 it
->pixel_width
+= face
->box_line_width
;
1488 take_vertical_position_into_account (it
);
1492 struct glyph
*glyph
;
1493 enum glyph_row_area area
= it
->area
;
1495 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1496 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1498 glyph
->type
= IMAGE_GLYPH
;
1499 glyph
->u
.img
.id
= img
->id
;
1500 glyph
->u
.img
.face_id
= it
->face_id
;
1501 glyph
->pixel_width
= it
->pixel_width
;
1502 glyph
->charpos
= CHARPOS (it
->position
);
1503 glyph
->object
= it
->object
;
1504 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1505 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1506 glyph
->voffset
= it
->voffset
;
1507 glyph
->multibyte_p
= it
->multibyte_p
;
1508 ++it
->glyph_row
->used
[area
];
1514 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1515 of the glyph, WIDTH and HEIGHT are the width and height of the
1516 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1517 ascent of the glyph (0 <= ASCENT <= 1). */
1520 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1526 struct glyph
*glyph
;
1527 enum glyph_row_area area
= it
->area
;
1529 xassert (ascent
>= 0 && ascent
<= 1);
1531 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1532 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1534 glyph
->type
= STRETCH_GLYPH
;
1535 glyph
->u
.stretch
.ascent
= height
* ascent
;
1536 glyph
->u
.stretch
.height
= height
;
1537 glyph
->u
.stretch
.face_id
= it
->face_id
;
1538 glyph
->pixel_width
= width
;
1539 glyph
->charpos
= CHARPOS (it
->position
);
1540 glyph
->object
= object
;
1541 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1542 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1543 glyph
->voffset
= it
->voffset
;
1544 glyph
->multibyte_p
= it
->multibyte_p
;
1545 ++it
->glyph_row
->used
[area
];
1550 /* Produce a stretch glyph for iterator IT. IT->object is the value
1551 of the glyph property displayed. The value must be a list
1552 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1555 1. `:width WIDTH' specifies that the space should be WIDTH *
1556 canonical char width wide. WIDTH may be an integer or floating
1559 2. `:relative-width FACTOR' specifies that the width of the stretch
1560 should be computed from the width of the first character having the
1561 `glyph' property, and should be FACTOR times that width.
1563 3. `:align-to HPOS' specifies that the space should be wide enough
1564 to reach HPOS, a value in canonical character units.
1566 Exactly one of the above pairs must be present.
1568 4. `:height HEIGHT' specifies that the height of the stretch produced
1569 should be HEIGHT, measured in canonical character units.
1571 5. `:relative-height FACTOR' specifies that the height of the the
1572 stretch should be FACTOR times the height of the characters having
1575 Either none or exactly one of 4 or 5 must be present.
1577 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1578 of the stretch should be used for the ascent of the stretch.
1579 ASCENT must be in the range 0 <= ASCENT <= 100. */
1582 ((INTEGERP (X) || FLOATP (X)) \
1588 x_produce_stretch_glyph (it
)
1591 /* (space :width WIDTH :height HEIGHT. */
1592 extern Lisp_Object QCwidth
, QCheight
, QCascent
, Qspace
;
1593 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1594 extern Lisp_Object QCalign_to
;
1595 Lisp_Object prop
, plist
;
1596 double width
= 0, height
= 0, ascent
= 0;
1597 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1598 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1600 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1602 /* List should start with `space'. */
1603 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1604 plist
= XCDR (it
->object
);
1606 /* Compute the width of the stretch. */
1607 if (prop
= Fplist_get (plist
, QCwidth
),
1609 /* Absolute width `:width WIDTH' specified and valid. */
1610 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1611 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1614 /* Relative width `:relative-width FACTOR' specified and valid.
1615 Compute the width of the characters having the `glyph'
1618 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1621 if (it
->multibyte_p
)
1623 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1624 - IT_BYTEPOS (*it
));
1625 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1628 it2
.c
= *p
, it2
.len
= 1;
1630 it2
.glyph_row
= NULL
;
1631 it2
.what
= IT_CHARACTER
;
1632 x_produce_glyphs (&it2
);
1633 width
= NUMVAL (prop
) * it2
.pixel_width
;
1635 else if (prop
= Fplist_get (plist
, QCalign_to
),
1637 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1639 /* Nothing specified -> width defaults to canonical char width. */
1640 width
= CANON_X_UNIT (it
->f
);
1642 /* Compute height. */
1643 if (prop
= Fplist_get (plist
, QCheight
),
1645 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1646 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1648 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1650 height
= FONT_HEIGHT (font
);
1652 /* Compute percentage of height used for ascent. If
1653 `:ascent ASCENT' is present and valid, use that. Otherwise,
1654 derive the ascent from the font in use. */
1655 if (prop
= Fplist_get (plist
, QCascent
),
1656 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1657 ascent
= NUMVAL (prop
) / 100.0;
1659 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1668 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1669 if (!STRINGP (object
))
1670 object
= it
->w
->buffer
;
1671 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1674 it
->pixel_width
= width
;
1675 it
->ascent
= height
* ascent
;
1676 it
->descent
= height
- it
->ascent
;
1679 if (face
->box
!= FACE_NO_BOX
)
1681 it
->ascent
+= face
->box_line_width
;
1682 it
->descent
+= face
->box_line_width
;
1684 if (it
->start_of_box_run_p
)
1685 it
->pixel_width
+= face
->box_line_width
;
1686 if (it
->end_of_box_run_p
)
1687 it
->pixel_width
+= face
->box_line_width
;
1690 take_vertical_position_into_account (it
);
1694 /* Produce glyphs/get display metrics for the display element IT is
1695 loaded with. See the description of struct display_iterator in
1696 dispextern.h for an overview of struct display_iterator. */
1699 x_produce_glyphs (it
)
1702 if (it
->what
== IT_CHARACTER
)
1709 int font_not_found_p
;
1712 /* Maybe translate single-byte characters to multibyte. */
1713 it
->char_to_display
= it
->c
;
1714 if (unibyte_display_via_language_environment
1715 && SINGLE_BYTE_CHAR_P (it
->c
)
1718 && !NILP (Vnonascii_translation_table
))))
1720 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1721 it
->charset
= CHAR_CHARSET (it
->char_to_display
);
1724 /* Get face and font to use. Encode IT->char_to_display. */
1725 face
= x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1726 it
->face_id
, &char2b
,
1730 /* When no suitable font found, use the default font. */
1731 font_not_found_p
= font
== NULL
;
1732 if (font_not_found_p
)
1733 font
= FRAME_FONT (it
->f
);
1735 if (it
->char_to_display
>= ' '
1736 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1738 /* Either unibyte or ASCII. */
1742 it
->ascent
= font
->ascent
;
1743 it
->descent
= font
->descent
;
1745 pcm
= x_per_char_metric (font
, &char2b
);
1746 it
->pixel_width
= pcm
->width
;
1748 /* If this is a space inside a region of text with
1749 `space-width' property, change its width. */
1750 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1752 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1754 /* If face has a box, add the box thickness to the character
1755 height. If character has a box line to the left and/or
1756 right, add the box line width to the character's width. */
1757 if (face
->box
!= FACE_NO_BOX
)
1759 int thick
= face
->box_line_width
;
1761 it
->ascent
+= thick
;
1762 it
->descent
+= thick
;
1764 if (it
->start_of_box_run_p
)
1765 it
->pixel_width
+= thick
;
1766 if (it
->end_of_box_run_p
)
1767 it
->pixel_width
+= thick
;
1770 /* If face has an overline, add the height of the overline
1771 (1 pixel) and a 1 pixel margin to the character height. */
1772 if (face
->overline_p
)
1775 take_vertical_position_into_account (it
);
1777 /* If we have to actually produce glyphs, do it. */
1782 /* Translate a space with a `space-width' property
1783 into a stretch glyph. */
1784 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1785 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1786 it
->ascent
+ it
->descent
, ascent
);
1789 x_append_glyph (it
);
1791 /* If characters with lbearing or rbearing are displayed
1792 in this line, record that fact in a flag of the
1793 glyph row. This is used to optimize X output code. */
1794 if (pcm
->lbearing
< 0
1795 || pcm
->rbearing
> pcm
->width
)
1796 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1799 else if (it
->char_to_display
== '\n')
1801 /* A newline has no width but we need the height of the line. */
1802 it
->pixel_width
= 0;
1804 it
->ascent
= font
->ascent
;
1805 it
->descent
= font
->descent
;
1807 if (face
->box
!= FACE_NO_BOX
)
1809 int thick
= face
->box_line_width
;
1810 it
->ascent
+= thick
;
1811 it
->descent
+= thick
;
1814 else if (it
->char_to_display
== '\t')
1816 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1817 int x
= (it
->current_x
1819 + it
->continuation_lines_width
);
1820 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1822 it
->pixel_width
= next_tab_x
- x
;
1824 it
->ascent
= font
->ascent
;
1825 it
->descent
= font
->descent
;
1829 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1830 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1831 it
->ascent
+ it
->descent
, ascent
);
1836 /* A multi-byte character. Assume that the display width of the
1837 character is the width of the character multiplied by the
1838 width of the font. There has to be better support for
1839 variable sizes in cmpchar_info to do anything better than
1842 Note: composite characters are represented as one glyph in
1843 the glyph matrix. There are no padding glyphs. */
1844 if (it
->charset
== CHARSET_COMPOSITION
)
1846 struct cmpchar_info
*cmpcharp
;
1849 idx
= COMPOSITE_CHAR_ID (it
->char_to_display
);
1850 cmpcharp
= cmpchar_table
[idx
];
1851 it
->pixel_width
= font
->max_bounds
.width
* cmpcharp
->width
;
1853 /* There are no padding glyphs, so there is only one glyph
1854 to produce for the composite char. Important is that
1855 pixel_width, ascent and descent are the values of what is
1856 drawn by draw_glyphs. */
1859 /* These settings may not be correct. We must have more
1860 information in cmpcharp to do the correct setting. */
1861 it
->ascent
= font
->ascent
;
1862 it
->descent
= font
->descent
;
1866 /* If we found a font, this font should give us the right
1867 metrics. If we didn't find a font, use the frame's
1868 default font and calculate the width of the character
1869 from the charset width; this is what old redisplay code
1871 pcm
= x_per_char_metric (font
, &char2b
);
1872 it
->pixel_width
= pcm
->width
;
1873 if (font_not_found_p
)
1874 it
->pixel_width
*= CHARSET_WIDTH (it
->charset
);
1876 it
->ascent
= font
->ascent
;
1877 it
->descent
= font
->descent
;
1879 && (pcm
->lbearing
< 0
1880 || pcm
->rbearing
> pcm
->width
))
1881 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1884 if (face
->box
!= FACE_NO_BOX
)
1886 int thick
= face
->box_line_width
;
1887 it
->ascent
+= thick
;
1888 it
->descent
+= thick
;
1890 if (it
->start_of_box_run_p
)
1891 it
->pixel_width
+= thick
;
1892 if (it
->end_of_box_run_p
)
1893 it
->pixel_width
+= thick
;
1896 /* If face has an overline, add the height of the overline
1897 (1 pixel) and a 1 pixel margin to the character height. */
1898 if (face
->overline_p
)
1901 take_vertical_position_into_account (it
);
1904 x_append_glyph (it
);
1907 else if (it
->what
== IT_IMAGE
)
1908 x_produce_image_glyph (it
);
1909 else if (it
->what
== IT_STRETCH
)
1910 x_produce_stretch_glyph (it
);
1912 /* Accumulate dimensions. */
1913 xassert (it
->ascent
>= 0 && it
->descent
> 0);
1914 if (it
->area
== TEXT_AREA
)
1915 it
->current_x
+= it
->pixel_width
;
1916 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
1917 it
->max_descent
= max (it
->max_descent
, it
->descent
);
1921 /* Estimate the pixel height of the mode or top line on frame F.
1922 FACE_ID specifies what line's height to estimate. */
1925 x_estimate_mode_line_height (f
, face_id
)
1927 enum face_id face_id
;
1931 /* This function is called so early when Emacs starts that the face
1932 cache and mode line face are not yet initialized. */
1933 if (FRAME_FACE_CACHE (f
))
1935 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1937 height
= FONT_HEIGHT (face
->font
) + 2 * face
->box_line_width
;
1944 /***********************************************************************
1946 ***********************************************************************/
1948 /* A sequence of glyphs to be drawn in the same face.
1950 This data structure is not really completely X specific, so it
1951 could possibly, at least partially, be useful for other systems. It
1952 is currently not part of the external redisplay interface because
1953 it's not clear what other systems will need. */
1957 /* X-origin of the string. */
1960 /* Y-origin and y-position of the base line of this string. */
1963 /* The width of the string, not including a face extension. */
1966 /* The width of the string, including a face extension. */
1967 int background_width
;
1969 /* The height of this string. This is the height of the line this
1970 string is drawn in, and can be different from the height of the
1971 font the string is drawn in. */
1974 /* Number of pixels this string overwrites in front of its x-origin.
1975 This number is zero if the string has an lbearing >= 0; it is
1976 -lbearing, if the string has an lbearing < 0. */
1979 /* Number of pixels this string overwrites past its right-most
1980 nominal x-position, i.e. x + width. Zero if the string's
1981 rbearing is <= its nominal width, rbearing - width otherwise. */
1984 /* The frame on which the glyph string is drawn. */
1987 /* The window on which the glyph string is drawn. */
1990 /* X display and window for convenience. */
1994 /* The glyph row for which this string was built. It determines the
1995 y-origin and height of the string. */
1996 struct glyph_row
*row
;
1998 /* The area within row. */
1999 enum glyph_row_area area
;
2001 /* Characters to be drawn, and number of characters. */
2005 /* Character set of this glyph string. */
2008 /* A face-override for drawing cursors, mouse face and similar. */
2009 enum draw_glyphs_face hl
;
2011 /* Face in which this string is to be drawn. */
2014 /* Font in which this string is to be drawn. */
2017 /* Font info for this string. */
2018 struct font_info
*font_info
;
2020 /* Non-null means this string describes (part of) a composite
2021 character. All characters from char2b are drawn at the same
2022 x-origin in that case. */
2023 struct cmpchar_info
*cmpcharp
;
2025 /* Index of this glyph string's first character in the glyph
2026 definition of cmpcharp. If this is zero, this glyph string
2027 describes the first character of a composite character. */
2030 /* 1 means this glyph strings face has to be drawn to the right end
2031 of the window's drawing area. */
2032 unsigned extends_to_end_of_line_p
: 1;
2034 /* 1 means the background of this string has been drawn. */
2035 unsigned background_filled_p
: 1;
2037 /* 1 means glyph string must be drawn with 16-bit functions. */
2038 unsigned two_byte_p
: 1;
2040 /* 1 means that the original font determined for drawing this glyph
2041 string could not be loaded. The member `font' has been set to
2042 the frame's default font in this case. */
2043 unsigned font_not_found_p
: 1;
2045 /* 1 means that the face in which this glyph string is drawn has a
2047 unsigned stippled_p
: 1;
2049 /* The GC to use for drawing this glyph string. */
2052 /* A pointer to the first glyph in the string. This glyph
2053 corresponds to char2b[0]. Needed to draw rectangles if
2054 font_not_found_p is 1. */
2055 struct glyph
*first_glyph
;
2057 /* Image, if any. */
2060 struct glyph_string
*next
, *prev
;
2067 x_dump_glyph_string (s
)
2068 struct glyph_string
*s
;
2070 fprintf (stderr
, "glyph string\n");
2071 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2072 s
->x
, s
->y
, s
->width
, s
->height
);
2073 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2074 fprintf (stderr
, " hl = %d\n", s
->hl
);
2075 fprintf (stderr
, " left overhang = %d, right = %d\n",
2076 s
->left_overhang
, s
->right_overhang
);
2077 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2078 fprintf (stderr
, " extends to end of line = %d\n",
2079 s
->extends_to_end_of_line_p
);
2080 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2081 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2084 #endif /* GLYPH_DEBUG */
2088 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2089 struct glyph_string
**,
2090 struct glyph_string
*,
2091 struct glyph_string
*));
2092 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2093 struct glyph_string
**,
2094 struct glyph_string
*,
2095 struct glyph_string
*));
2096 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2097 struct glyph_string
**,
2098 struct glyph_string
*));
2099 static int x_left_overwritten
P_ ((struct glyph_string
*));
2100 static int x_left_overwriting
P_ ((struct glyph_string
*));
2101 static int x_right_overwritten
P_ ((struct glyph_string
*));
2102 static int x_right_overwriting
P_ ((struct glyph_string
*));
2103 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int));
2104 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2105 XChar2b
*, struct window
*,
2107 enum glyph_row_area
, int,
2108 enum draw_glyphs_face
));
2109 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2110 enum glyph_row_area
, int, int,
2111 enum draw_glyphs_face
, int *, int *));
2112 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2113 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2114 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2116 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2117 static void x_draw_glyph_string_underline
P_ ((struct glyph_string
*));
2118 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2119 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2120 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2121 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2122 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2123 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2124 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2126 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2127 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2128 unsigned long *, float, int));
2129 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2130 float, int, unsigned long));
2131 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2132 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2133 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2134 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2135 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2136 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2137 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2139 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2140 int, int, int, int, XRectangle
*));
2141 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2142 int, int, int, XRectangle
*));
2146 /* Append the list of glyph strings with head H and tail T to the list
2147 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2150 x_append_glyph_string_lists (head
, tail
, h
, t
)
2151 struct glyph_string
**head
, **tail
;
2152 struct glyph_string
*h
, *t
;
2166 /* Prepend the list of glyph strings with head H and tail T to the
2167 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2171 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2172 struct glyph_string
**head
, **tail
;
2173 struct glyph_string
*h
, *t
;
2187 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2188 Set *HEAD and *TAIL to the resulting list. */
2191 x_append_glyph_string (head
, tail
, s
)
2192 struct glyph_string
**head
, **tail
;
2193 struct glyph_string
*s
;
2195 s
->next
= s
->prev
= NULL
;
2196 x_append_glyph_string_lists (head
, tail
, s
, s
);
2200 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2205 struct glyph_string
*s
;
2207 if (s
->font
== FRAME_FONT (s
->f
)
2208 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2209 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2211 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2214 /* Cursor on non-default face: must merge. */
2218 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2219 xgcv
.foreground
= s
->face
->background
;
2221 /* If the glyph would be invisible, try a different foreground. */
2222 if (xgcv
.foreground
== xgcv
.background
)
2223 xgcv
.foreground
= s
->face
->foreground
;
2224 if (xgcv
.foreground
== xgcv
.background
)
2225 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2226 if (xgcv
.foreground
== xgcv
.background
)
2227 xgcv
.foreground
= s
->face
->foreground
;
2229 /* Make sure the cursor is distinct from text in this face. */
2230 if (xgcv
.background
== s
->face
->background
2231 && xgcv
.foreground
== s
->face
->foreground
)
2233 xgcv
.background
= s
->face
->foreground
;
2234 xgcv
.foreground
= s
->face
->background
;
2237 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2238 xgcv
.font
= s
->font
->fid
;
2239 xgcv
.graphics_exposures
= False
;
2240 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2242 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2243 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2246 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2247 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2249 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2254 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2257 x_set_mouse_face_gc (s
)
2258 struct glyph_string
*s
;
2262 /* What face has to be used for the mouse face? */
2263 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2264 face_id
= FACE_FOR_CHARSET (s
->f
, face_id
, s
->charset
);
2265 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2266 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2268 /* If font in this face is same as S->font, use it. */
2269 if (s
->font
== s
->face
->font
)
2270 s
->gc
= s
->face
->gc
;
2273 /* Otherwise construct scratch_cursor_gc with values from FACE
2278 xgcv
.background
= s
->face
->background
;
2279 xgcv
.foreground
= s
->face
->foreground
;
2280 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2281 xgcv
.font
= s
->font
->fid
;
2282 xgcv
.graphics_exposures
= False
;
2283 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2285 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2286 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2289 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2290 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2292 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2295 xassert (s
->gc
!= 0);
2299 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2300 Faces to use in the mode line have already been computed when the
2301 matrix was built, so there isn't much to do, here. */
2304 x_set_mode_line_face_gc (s
)
2305 struct glyph_string
*s
;
2307 s
->gc
= s
->face
->gc
;
2308 xassert (s
->gc
!= 0);
2312 /* Set S->gc of glyph string S for drawing that glyph string. Set
2313 S->stippled_p to a non-zero value if the face of S has a stipple
2317 x_set_glyph_string_gc (s
)
2318 struct glyph_string
*s
;
2320 if (s
->hl
== DRAW_NORMAL_TEXT
)
2322 s
->gc
= s
->face
->gc
;
2323 s
->stippled_p
= s
->face
->stipple
!= 0;
2325 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2327 x_set_mode_line_face_gc (s
);
2328 s
->stippled_p
= s
->face
->stipple
!= 0;
2330 else if (s
->hl
== DRAW_CURSOR
)
2332 x_set_cursor_gc (s
);
2335 else if (s
->hl
== DRAW_MOUSE_FACE
)
2337 x_set_mouse_face_gc (s
);
2338 s
->stippled_p
= s
->face
->stipple
!= 0;
2340 else if (s
->hl
== DRAW_IMAGE_RAISED
2341 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2343 s
->gc
= s
->face
->gc
;
2344 s
->stippled_p
= s
->face
->stipple
!= 0;
2348 s
->gc
= s
->face
->gc
;
2349 s
->stippled_p
= s
->face
->stipple
!= 0;
2352 /* GC must have been set. */
2353 xassert (s
->gc
!= 0);
2357 /* Return in *R the clipping rectangle for glyph string S. */
2360 x_get_glyph_string_clip_rect (s
, r
)
2361 struct glyph_string
*s
;
2364 if (s
->row
->full_width_p
)
2366 /* Draw full-width. X coordinates are relative to S->w->left. */
2367 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * CANON_X_UNIT (s
->f
);
2368 r
->width
= XFASTINT (s
->w
->width
) * CANON_X_UNIT (s
->f
);
2370 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2372 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
2374 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2378 /* Unless displaying a mode or menu bar line, which are always
2379 fully visible, clip to the visible part of the row. */
2380 if (s
->w
->pseudo_window_p
)
2381 r
->height
= s
->row
->visible_height
;
2383 r
->height
= s
->height
;
2387 /* This is a text line that may be partially visible. */
2388 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2389 r
->width
= window_box_width (s
->w
, s
->area
);
2390 r
->height
= s
->row
->visible_height
;
2393 /* Don't use S->y for clipping because it doesn't take partially
2394 visible lines into account. For example, it can be negative for
2395 partially visible lines at the top of a window. */
2396 if (!s
->row
->full_width_p
2397 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2398 r
->y
= WINDOW_DISPLAY_TOP_LINE_HEIGHT (s
->w
);
2400 r
->y
= max (0, s
->row
->y
);
2401 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2403 /* If drawing a toolbar window, draw it over the internal border
2404 at the top of the window. */
2405 if (s
->w
== XWINDOW (s
->f
->toolbar_window
))
2406 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2410 /* Set clipping for output of glyph string S. S may be part of a mode
2411 line or menu if we don't have X toolkit support. */
2414 x_set_glyph_string_clipping (s
)
2415 struct glyph_string
*s
;
2418 x_get_glyph_string_clip_rect (s
, &r
);
2419 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2423 /* Compute left and right overhang of glyph string S. If S is a glyph
2424 string for a composite character, assume overhangs don't exist. */
2427 x_compute_glyph_string_overhangs (s
)
2428 struct glyph_string
*s
;
2430 if (s
->cmpcharp
== NULL
2431 && s
->first_glyph
->type
== CHAR_GLYPH
)
2434 int direction
, font_ascent
, font_descent
;
2435 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2436 &font_ascent
, &font_descent
, &cs
);
2437 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2438 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2443 /* Compute overhangs and x-positions for glyph string S and its
2444 predecessors, or successors. X is the starting x-position for S.
2445 BACKWARD_P non-zero means process predecessors. */
2448 x_compute_overhangs_and_x (s
, x
, backward_p
)
2449 struct glyph_string
*s
;
2457 x_compute_glyph_string_overhangs (s
);
2467 x_compute_glyph_string_overhangs (s
);
2476 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2477 frame F. Overhangs of glyphs other than type CHAR_GLYPH or of
2478 character glyphs for composite characters are assumed to be zero. */
2481 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2482 struct glyph
*glyph
;
2490 if (glyph
->type
== CHAR_GLYPH
2491 && (c
= glyph
->u
.ch
.code
,
2492 CHAR_CHARSET (c
) != CHARSET_COMPOSITION
))
2496 struct font_info
*font_info
;
2499 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
);
2501 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2504 XCharStruct
*pcm
= x_per_char_metric (font
, &char2b
);
2506 if (pcm
->rbearing
> pcm
->width
)
2507 *right
= pcm
->rbearing
- pcm
->width
;
2508 if (pcm
->lbearing
< 0)
2509 *left
= -pcm
->lbearing
;
2515 /* Return the index of the first glyph preceding glyph string S that
2516 is overwritten by S because of S's left overhang. Value is -1
2517 if no glyphs are overwritten. */
2520 x_left_overwritten (s
)
2521 struct glyph_string
*s
;
2525 if (s
->left_overhang
)
2528 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2529 int first
= s
->first_glyph
- glyphs
;
2531 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2532 x
-= glyphs
[i
].pixel_width
;
2543 /* Return the index of the first glyph preceding glyph string S that
2544 is overwriting S because of its right overhang. Value is -1 if no
2545 glyph in front of S overwrites S. */
2548 x_left_overwriting (s
)
2549 struct glyph_string
*s
;
2552 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2553 int first
= s
->first_glyph
- glyphs
;
2557 for (i
= first
- 1; i
>= 0; --i
)
2560 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2563 x
-= glyphs
[i
].pixel_width
;
2570 /* Return the index of the last glyph following glyph string S that is
2571 not overwritten by S because of S's right overhang. Value is -1 if
2572 no such glyph is found. */
2575 x_right_overwritten (s
)
2576 struct glyph_string
*s
;
2580 if (s
->right_overhang
)
2583 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2584 int first
= (s
->first_glyph
- glyphs
) + (s
->cmpcharp
? 1 : s
->nchars
);
2585 int end
= s
->row
->used
[s
->area
];
2587 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
2588 x
+= glyphs
[i
].pixel_width
;
2597 /* Return the index of the last glyph following glyph string S that
2598 overwrites S because of its left overhang. Value is negative
2599 if no such glyph is found. */
2602 x_right_overwriting (s
)
2603 struct glyph_string
*s
;
2606 int end
= s
->row
->used
[s
->area
];
2607 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2608 int first
= (s
->first_glyph
- glyphs
) + (s
->cmpcharp
? 1 : s
->nchars
);
2612 for (i
= first
; i
< end
; ++i
)
2615 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2618 x
+= glyphs
[i
].pixel_width
;
2625 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2628 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2629 struct glyph_string
*s
;
2633 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
2634 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2635 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2636 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2640 /* Draw the background of glyph_string S. If S->background_filled_p
2641 is non-zero don't draw it. FORCE_P non-zero means draw the
2642 background even if it wouldn't be drawn normally. This is used
2643 when a string preceding S draws into the background of S. */
2646 x_draw_glyph_string_background (s
, force_p
)
2647 struct glyph_string
*s
;
2650 /* Nothing to do if background has already been drawn or if it
2651 shouldn't be drawn in the first place. */
2652 if (!s
->background_filled_p
)
2656 && !s
->font_not_found_p
2657 && !s
->extends_to_end_of_line_p
)
2659 /* Don't draw background for glyphs of a composite
2660 characters, except for the first one. */
2661 s
->background_filled_p
= 1;
2663 else if (s
->stippled_p
)
2665 /* Fill background with a stipple pattern. */
2666 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2667 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2668 s
->y
+ s
->face
->box_line_width
,
2669 s
->background_width
,
2670 s
->height
- 2 * s
->face
->box_line_width
);
2671 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2672 s
->background_filled_p
= 1;
2674 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * s
->face
->box_line_width
2675 || s
->font_not_found_p
2676 || s
->extends_to_end_of_line_p
2680 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ s
->face
->box_line_width
,
2681 s
->background_width
,
2682 s
->height
- 2 * s
->face
->box_line_width
);
2683 s
->background_filled_p
= 1;
2689 /* Draw the foreground of glyph string S. */
2692 x_draw_glyph_string_foreground (s
)
2693 struct glyph_string
*s
;
2697 /* If first glyph of S has a left box line, start drawing the text
2698 of S to the right of that box line. */
2699 if (s
->face
->box
!= FACE_NO_BOX
2700 && s
->first_glyph
->left_box_line_p
)
2701 x
= s
->x
+ s
->face
->box_line_width
;
2705 if (s
->cmpcharp
== NULL
)
2707 /* Not a composite character. Draw characters of S as
2708 rectangles if S's font could not be loaded. */
2709 if (s
->font_not_found_p
)
2711 for (i
= 0; i
< s
->nchars
; ++i
)
2713 struct glyph
*g
= s
->first_glyph
+ i
;
2714 XDrawRectangle (s
->display
, s
->window
,
2715 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2717 x
+= g
->pixel_width
;
2722 char *char1b
= (char *) s
->char2b
;
2724 /* If we can use 8-bit functions, condense S->char2b. */
2726 for (i
= 0; i
< s
->nchars
; ++i
)
2727 char1b
[i
] = s
->char2b
[i
].byte2
;
2729 /* Draw text with XDrawString if background has already been
2730 filled. Otherwise, use XDrawImageString. (Note that
2731 XDrawImageString is usually faster than XDrawString.)
2732 Always use XDrawImageString when drawing the cursor so
2733 that there is no chance that characters under a box
2734 cursor are invisible. */
2735 if (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
)
2737 /* Draw characters with 16-bit or 8-bit functions. */
2739 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
, s
->ybase
,
2740 s
->char2b
, s
->nchars
);
2742 XDrawString (s
->display
, s
->window
, s
->gc
, x
, s
->ybase
,
2748 XDrawImageString16 (s
->display
, s
->window
, s
->gc
,
2749 x
, s
->ybase
, s
->char2b
, s
->nchars
);
2751 XDrawImageString (s
->display
, s
->window
, s
->gc
,
2752 x
, s
->ybase
, char1b
, s
->nchars
);
2758 /* S is a glyph string for a composite character. S->gidx is the
2759 index of the first character drawn in the vector
2760 S->cmpcharp->glyph. S->gidx == 0 means we are drawing the
2761 very first component character of a composite char. */
2763 /* Draw a single rectangle for the composite character if S's
2764 font could not be loaded. */
2765 if (s
->font_not_found_p
&& s
->gidx
== 0)
2766 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2767 s
->width
- 1, s
->height
- 1);
2771 int relative_compose
, default_ascent
, i
;
2772 int highest
= 0, lowest
= 0;
2774 /* The value of font_info my be null if we couldn't find it
2775 in x_get_char_face_and_encoding. */
2776 if (s
->cmpcharp
->cmp_rule
== NULL
&& s
->font_info
)
2778 relative_compose
= s
->font_info
->relative_compose
;
2779 default_ascent
= s
->font_info
->default_ascent
;
2782 relative_compose
= default_ascent
= 0;
2784 if ((s
->cmpcharp
->cmp_rule
|| relative_compose
)
2787 /* This is the first character. Initialize variables.
2788 Highest is the highest position of glyphs ever
2789 written, lowest the lowest position. */
2791 int first_ch
= s
->first_glyph
->u
.ch
.code
;
2794 && CHAR_TABLE_P (Vuse_default_ascent
)
2795 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
2797 highest
= default_ascent
;
2802 pcm
= PER_CHAR_METRIC (s
->font
, s
->char2b
);
2803 highest
= pcm
->ascent
+ 1;
2804 lowest
= - pcm
->descent
;
2807 if (s
->cmpcharp
->cmp_rule
)
2808 x_offset
= (s
->cmpcharp
->col_offset
[0]
2809 * FONT_WIDTH (s
->f
->output_data
.x
->font
));
2811 /* Draw the first character at the normal position. */
2812 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2814 s
->ybase
, s
->char2b
, 1);
2821 for (; i
< s
->nchars
; i
++, ++s
->gidx
)
2823 int x_offset
= 0, y_offset
= 0;
2825 if (relative_compose
)
2827 pcm
= PER_CHAR_METRIC (s
->font
, s
->char2b
+ i
);
2828 if (NILP (Vignore_relative_composition
)
2829 || NILP (Faref (Vignore_relative_composition
,
2830 make_number (s
->cmpcharp
->glyph
[s
->gidx
]))))
2832 if (- pcm
->descent
>= relative_compose
)
2834 /* Draw above the current glyphs. */
2835 y_offset
= highest
+ pcm
->descent
;
2836 highest
+= pcm
->ascent
+ pcm
->descent
;
2838 else if (pcm
->ascent
<= 0)
2840 /* Draw beneath the current glyphs. */
2841 y_offset
= lowest
- pcm
->ascent
;
2842 lowest
-= pcm
->ascent
+ pcm
->descent
;
2847 /* Draw the glyph at normal position. If
2848 it sticks out of HIGHEST or LOWEST,
2849 update them appropriately. */
2850 if (pcm
->ascent
> highest
)
2851 highest
= pcm
->ascent
;
2852 else if (- pcm
->descent
< lowest
)
2853 lowest
= - pcm
->descent
;
2856 else if (s
->cmpcharp
->cmp_rule
)
2858 int gref
= (s
->cmpcharp
->cmp_rule
[s
->gidx
] - 0xA0) / 9;
2859 int nref
= (s
->cmpcharp
->cmp_rule
[s
->gidx
] - 0xA0) % 9;
2862 /* Re-encode GREF and NREF so that they specify
2863 only Y-axis information:
2864 0:top, 1:base, 2:bottom, 3:center */
2865 gref
= gref
/ 3 + (gref
== 4) * 2;
2866 nref
= nref
/ 3 + (nref
== 4) * 2;
2868 pcm
= PER_CHAR_METRIC (s
->font
, s
->char2b
+ i
);
2869 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
2870 : gref
== 2 ? lowest
2871 : (highest
+ lowest
) / 2)
2872 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
2873 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
2874 : (pcm
->ascent
+ pcm
->descent
) / 2));
2875 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
2878 if (bottom
< lowest
)
2880 y_offset
= bottom
+ pcm
->descent
;
2881 x_offset
= (s
->cmpcharp
->col_offset
[s
->gidx
]
2882 * FONT_WIDTH (FRAME_FONT (s
->f
)));
2885 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2886 x
+ x_offset
, s
->ybase
- y_offset
,
2894 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2895 CMAP. If an exact match can't be allocated, try the nearest color
2896 available. Value is non-zero if successful. Set *COLOR to the
2900 x_alloc_nearest_color (display
, screen
, cmap
, color
)
2906 int rc
= XAllocColor (display
, cmap
, color
);
2909 /* If we got to this point, the colormap is full, so we're going
2910 to try to get the next closest color. The algorithm used is
2911 a least-squares matching, which is what X uses for closest
2912 color matching with StaticColor visuals. */
2914 unsigned long nearest_delta
= ~0;
2915 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2916 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2918 for (i
= 0; i
< ncells
; ++i
)
2920 XQueryColors (display
, cmap
, cells
, ncells
);
2922 for (nearest
= i
= 0; i
< ncells
; ++i
)
2924 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2925 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2926 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2927 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2929 if (delta
< nearest_delta
)
2932 nearest_delta
= delta
;
2936 color
->red
= cells
[nearest
].red
;
2937 color
->green
= cells
[nearest
].green
;
2938 color
->blue
= cells
[nearest
].blue
;
2939 rc
= XAllocColor (display
, cmap
, color
);
2946 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2947 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2948 If this produces the same color as PIXEL, try a color where all RGB
2949 values have DELTA added. Return the allocated color in *PIXEL.
2950 DISPLAY is the X display, CMAP is the colormap to operate on.
2951 Value is non-zero if successful. */
2954 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
2958 unsigned long *pixel
;
2965 /* Get RGB color values. */
2966 color
.pixel
= *pixel
;
2967 XQueryColor (display
, cmap
, &color
);
2969 /* Change RGB values by specified FACTOR. Avoid overflow! */
2970 xassert (factor
>= 0);
2971 new.red
= min (0xffff, factor
* color
.red
);
2972 new.green
= min (0xffff, factor
* color
.green
);
2973 new.blue
= min (0xffff, factor
* color
.blue
);
2975 /* Try to allocate the color. */
2976 success_p
= x_alloc_nearest_color (display
, FRAME_X_SCREEN (f
), cmap
, &new);
2979 if (new.pixel
== *pixel
)
2981 /* If we end up with the same color as before, try adding
2982 delta to the RGB values. */
2983 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
2985 /* If display has an immutable color map, freeing colors is
2986 not necessary and some servers don't allow it. So don't
2988 if (class != StaticColor
2989 && class != StaticGray
2990 && class != TrueColor
)
2991 XFreeColors (display
, cmap
, &new.pixel
, 1, 0);
2993 new.red
= min (0xffff, delta
+ color
.red
);
2994 new.green
= min (0xffff, delta
+ color
.green
);
2995 new.blue
= min (0xffff, delta
+ color
.blue
);
2996 success_p
= x_alloc_nearest_color (display
, FRAME_X_SCREEN (f
),
3008 /* Set up the foreground color for drawing relief lines of glyph
3009 string S. RELIEF is a pointer to a struct relief containing the GC
3010 with which lines will be drawn. Use a color that is FACTOR or
3011 DELTA lighter or darker than the relief's background which is found
3012 in S->f->output_data.x->relief_background. If such a color cannot
3013 be allocated, use DEFAULT_PIXEL, instead. */
3016 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3018 struct relief
*relief
;
3021 unsigned long default_pixel
;
3024 struct x_output
*di
= f
->output_data
.x
;
3025 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3026 unsigned long pixel
;
3027 unsigned long background
= di
->relief_background
;
3028 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3030 xgcv
.graphics_exposures
= False
;
3031 xgcv
.line_width
= 1;
3033 /* Free previously allocated color. The color cell will be reused
3034 when it has been freed as many times as it was allocated, so this
3035 doesn't affect faces using the same colors. */
3037 && relief
->allocated_p
)
3039 /* If display has an immutable color map, freeing colors is not
3040 necessary and some servers don't allow it. So don't do it. */
3041 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
3042 if (class != StaticColor
3043 && class != StaticGray
3044 && class != TrueColor
)
3045 XFreeColors (FRAME_X_DISPLAY (f
), cmap
, &relief
->pixel
, 1, 0);
3046 relief
->allocated_p
= 0;
3049 /* Allocate new color. */
3050 xgcv
.foreground
= default_pixel
;
3052 if (x_alloc_lighter_color (f
, FRAME_X_DISPLAY (f
), cmap
, &pixel
,
3055 relief
->allocated_p
= 1;
3056 xgcv
.foreground
= relief
->pixel
= pixel
;
3059 if (relief
->gc
== 0)
3061 xgcv
.stipple
= FRAME_X_DISPLAY_INFO (f
)->gray
;
3063 relief
->gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3067 XChangeGC (FRAME_X_DISPLAY (f
), relief
->gc
, mask
, &xgcv
);
3071 /* Set up colors for the relief lines around glyph string S. */
3074 x_setup_relief_colors (s
)
3075 struct glyph_string
*s
;
3077 struct x_output
*di
= s
->f
->output_data
.x
;
3078 unsigned long color
;
3080 if (s
->face
->use_box_color_for_shadows_p
)
3081 color
= s
->face
->box_color
;
3086 /* Get the background color of the face. */
3087 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3088 color
= xgcv
.background
;
3091 if (di
->white_relief
.gc
== 0
3092 || color
!= di
->relief_background
)
3094 di
->relief_background
= color
;
3095 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3096 WHITE_PIX_DEFAULT (s
->f
));
3097 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3098 BLACK_PIX_DEFAULT (s
->f
));
3103 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3104 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3105 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3106 relief. LEFT_P non-zero means draw a relief on the left side of
3107 the rectangle. RIGHT_P non-zero means draw a relief on the right
3108 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3112 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3113 raised_p
, left_p
, right_p
, clip_rect
)
3115 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3116 XRectangle
*clip_rect
;
3122 gc
= f
->output_data
.x
->white_relief
.gc
;
3124 gc
= f
->output_data
.x
->black_relief
.gc
;
3125 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3128 for (i
= 0; i
< width
; ++i
)
3129 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3130 left_x
+ i
* left_p
, top_y
+ i
,
3131 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3135 for (i
= 0; i
< width
; ++i
)
3136 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3137 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3139 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3141 gc
= f
->output_data
.x
->black_relief
.gc
;
3143 gc
= f
->output_data
.x
->white_relief
.gc
;
3144 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3147 for (i
= 0; i
< width
; ++i
)
3148 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3149 left_x
+ i
* left_p
, bottom_y
- i
,
3150 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3154 for (i
= 0; i
< width
; ++i
)
3155 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3156 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3158 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3162 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3163 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3164 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3165 left side of the rectangle. RIGHT_P non-zero means draw a line
3166 on the right side of the rectangle. CLIP_RECT is the clipping
3167 rectangle to use when drawing. */
3170 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3171 left_p
, right_p
, clip_rect
)
3172 struct glyph_string
*s
;
3173 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3174 XRectangle
*clip_rect
;
3178 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3179 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3180 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3183 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3184 left_x
, top_y
, right_x
- left_x
, width
);
3188 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3189 left_x
, top_y
, width
, bottom_y
- top_y
);
3192 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3193 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
3197 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3198 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
3200 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3201 XSetClipMask (s
->display
, s
->gc
, None
);
3205 /* Draw a box around glyph string S. */
3208 x_draw_glyph_string_box (s
)
3209 struct glyph_string
*s
;
3211 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3212 int left_p
, right_p
;
3213 struct glyph
*last_glyph
;
3214 XRectangle clip_rect
;
3216 last_x
= window_box_right (s
->w
, s
->area
);
3217 if (s
->row
->full_width_p
3218 && !s
->w
->pseudo_window_p
)
3220 last_x
+= FRAME_X_FLAGS_AREA_WIDTH (s
->f
);
3221 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3222 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3225 /* The glyph that may have a right box line. */
3226 last_glyph
= (s
->cmpcharp
|| s
->img
3228 : s
->first_glyph
+ s
->nchars
- 1);
3230 width
= s
->face
->box_line_width
;
3231 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3233 right_x
= ((s
->row
->full_width_p
3235 : min (last_x
, s
->x
+ s
->width
) - 1));
3237 bottom_y
= top_y
+ s
->height
- 1;
3239 left_p
= (s
->first_glyph
->left_box_line_p
3240 || (s
->hl
== DRAW_MOUSE_FACE
3242 || s
->prev
->hl
!= s
->hl
)));
3243 right_p
= (last_glyph
->right_box_line_p
3244 || (s
->hl
== DRAW_MOUSE_FACE
3246 || s
->next
->hl
!= s
->hl
)));
3248 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3250 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3251 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3252 left_p
, right_p
, &clip_rect
);
3255 x_setup_relief_colors (s
);
3256 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3257 width
, raised_p
, left_p
, right_p
, &clip_rect
);
3262 /* Draw foreground of image glyph string S. */
3265 x_draw_image_foreground (s
)
3266 struct glyph_string
*s
;
3269 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3271 /* If first glyph of S has a left box line, start drawing it to the
3272 right of that line. */
3273 if (s
->face
->box
!= FACE_NO_BOX
3274 && s
->first_glyph
->left_box_line_p
)
3275 x
= s
->x
+ s
->face
->box_line_width
;
3279 /* If there is a margin around the image, adjust x- and y-position
3283 x
+= s
->img
->margin
;
3284 y
+= s
->img
->margin
;
3291 /* We can't set both a clip mask and use XSetClipRectangles
3292 because the latter also sets a clip mask. We also can't
3293 trust on the shape extension to be available
3294 (XShapeCombineRegion). So, compute the rectangle to draw
3296 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3299 XRectangle clip_rect
, image_rect
, r
;
3301 xgcv
.clip_mask
= s
->img
->mask
;
3302 xgcv
.clip_x_origin
= x
;
3303 xgcv
.clip_y_origin
= y
;
3304 xgcv
.function
= GXcopy
;
3305 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3307 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3310 image_rect
.width
= s
->img
->width
;
3311 image_rect
.height
= s
->img
->height
;
3312 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3313 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3314 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3318 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3319 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3321 /* When the image has a mask, we can expect that at
3322 least part of a mouse highlight or a block cursor will
3323 be visible. If the image doesn't have a mask, make
3324 a block cursor visible by drawing a rectangle around
3325 the image. I believe it's looking better if we do
3326 nothing here for mouse-face. */
3327 if (s
->hl
== DRAW_CURSOR
)
3328 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3329 s
->img
->width
- 1, s
->img
->height
- 1);
3333 /* Draw a rectangle if image could not be loaded. */
3334 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3335 s
->img
->width
- 1, s
->img
->height
- 1);
3339 /* Draw a relief around the image glyph string S. */
3342 x_draw_image_relief (s
)
3343 struct glyph_string
*s
;
3345 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3348 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3350 /* If first glyph of S has a left box line, start drawing it to the
3351 right of that line. */
3352 if (s
->face
->box
!= FACE_NO_BOX
3353 && s
->first_glyph
->left_box_line_p
)
3354 x
= s
->x
+ s
->face
->box_line_width
;
3358 /* If there is a margin around the image, adjust x- and y-position
3362 x
+= s
->img
->margin
;
3363 y
+= s
->img
->margin
;
3366 if (s
->hl
== DRAW_IMAGE_SUNKEN
3367 || s
->hl
== DRAW_IMAGE_RAISED
)
3369 thick
= toolbar_button_relief
> 0 ? toolbar_button_relief
: 3;
3370 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3374 thick
= abs (s
->img
->relief
);
3375 raised_p
= s
->img
->relief
> 0;
3380 x1
= x
+ s
->img
->width
+ thick
- 1;
3381 y1
= y
+ s
->img
->height
+ thick
- 1;
3383 x_setup_relief_colors (s
);
3384 x_get_glyph_string_clip_rect (s
, &r
);
3385 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
3389 /* Draw the foreground of image glyph string S to PIXMAP. */
3392 x_draw_image_foreground_1 (s
, pixmap
)
3393 struct glyph_string
*s
;
3397 int y
= s
->ybase
- s
->y
- IMAGE_ASCENT (s
->img
);
3399 /* If first glyph of S has a left box line, start drawing it to the
3400 right of that line. */
3401 if (s
->face
->box
!= FACE_NO_BOX
3402 && s
->first_glyph
->left_box_line_p
)
3403 x
= s
->face
->box_line_width
;
3407 /* If there is a margin around the image, adjust x- and y-position
3411 x
+= s
->img
->margin
;
3412 y
+= s
->img
->margin
;
3419 /* We can't set both a clip mask and use XSetClipRectangles
3420 because the latter also sets a clip mask. We also can't
3421 trust on the shape extension to be available
3422 (XShapeCombineRegion). So, compute the rectangle to draw
3424 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3428 xgcv
.clip_mask
= s
->img
->mask
;
3429 xgcv
.clip_x_origin
= x
;
3430 xgcv
.clip_y_origin
= y
;
3431 xgcv
.function
= GXcopy
;
3432 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3434 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3435 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3436 XSetClipMask (s
->display
, s
->gc
, None
);
3440 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3441 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3443 /* When the image has a mask, we can expect that at
3444 least part of a mouse highlight or a block cursor will
3445 be visible. If the image doesn't have a mask, make
3446 a block cursor visible by drawing a rectangle around
3447 the image. I believe it's looking better if we do
3448 nothing here for mouse-face. */
3449 if (s
->hl
== DRAW_CURSOR
)
3450 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3451 s
->img
->width
- 1, s
->img
->height
- 1);
3455 /* Draw a rectangle if image could not be loaded. */
3456 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3457 s
->img
->width
- 1, s
->img
->height
- 1);
3461 /* Draw part of the background of glyph string S. X, Y, W, and H
3462 give the rectangle to draw. */
3465 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3466 struct glyph_string
*s
;
3471 /* Fill background with a stipple pattern. */
3472 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3473 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3474 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3477 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3481 /* Draw image glyph string S.
3484 s->x +-------------------------
3487 | +-------------------------
3490 | | +-------------------
3496 x_draw_image_glyph_string (s
)
3497 struct glyph_string
*s
;
3500 int box_line_width
= s
->face
->box_line_width
;
3501 int margin
= s
->img
->margin
;
3503 Pixmap pixmap
= None
;
3505 height
= s
->height
- 2 * box_line_width
;
3507 /* Fill background with face under the image. Do it only if row is
3508 taller than image or if image has a clip mask to reduce
3510 s
->stippled_p
= s
->face
->stipple
!= 0;
3511 if (height
> s
->img
->height
3514 || s
->img
->pixmap
== 0
3515 || s
->width
!= s
->background_width
)
3517 if (box_line_width
&& s
->first_glyph
->left_box_line_p
)
3518 x
= s
->x
+ box_line_width
;
3522 y
= s
->y
+ box_line_width
;
3526 /* Create a pixmap as large as the glyph string Fill it with
3527 the background color. Copy the image to it, using its
3528 mask. Copy the temporary pixmap to the display. */
3529 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
3530 int depth
= DefaultDepthOfScreen (screen
);
3532 /* Create a pixmap as large as the glyph string. */
3533 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3534 s
->background_width
,
3537 /* Don't clip in the following because we're working on the
3539 XSetClipMask (s
->display
, s
->gc
, None
);
3541 /* Fill the pixmap with the background color/stipple. */
3544 /* Fill background with a stipple pattern. */
3545 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3546 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3547 0, 0, s
->background_width
, s
->height
);
3548 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3553 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3555 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3556 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3557 0, 0, s
->background_width
, s
->height
);
3558 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3562 /* Implementation idea: Is it possible to construct a mask?
3563 We could look at the color at the margins of the image, and
3564 say that this color is probably the background color of the
3566 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3568 s
->background_filled_p
= 1;
3571 /* Draw the foreground. */
3574 x_draw_image_foreground_1 (s
, pixmap
);
3575 x_set_glyph_string_clipping (s
);
3576 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
3577 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3578 XFreePixmap (s
->display
, pixmap
);
3581 x_draw_image_foreground (s
);
3583 /* If we must draw a relief around the image, do it. */
3585 || s
->hl
== DRAW_IMAGE_RAISED
3586 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3587 x_draw_image_relief (s
);
3591 /* Draw stretch glyph string S. */
3594 x_draw_stretch_glyph_string (s
)
3595 struct glyph_string
*s
;
3597 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3598 s
->stippled_p
= s
->face
->stipple
!= 0;
3600 if (s
->hl
== DRAW_CURSOR
3601 && !x_stretch_cursor_p
)
3603 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3604 as wide as the stretch glyph. */
3605 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
3608 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3610 /* Clear rest using the GC of the original non-cursor face. */
3611 if (width
< s
->background_width
)
3613 GC gc
= s
->face
->gc
;
3614 int x
= s
->x
+ width
, y
= s
->y
;
3615 int w
= s
->background_width
- width
, h
= s
->height
;
3618 x_get_glyph_string_clip_rect (s
, &r
);
3619 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
3621 if (s
->face
->stipple
)
3623 /* Fill background with a stipple pattern. */
3624 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3625 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3626 XSetFillStyle (s
->display
, gc
, FillSolid
);
3631 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3632 XSetForeground (s
->display
, gc
, xgcv
.background
);
3633 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3634 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3639 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3642 s
->background_filled_p
= 1;
3646 /* Draw glyph string S. */
3649 x_draw_glyph_string (s
)
3650 struct glyph_string
*s
;
3652 /* If S draws into the background of its successor, draw the
3653 background of the successor first so that S can draw into it.
3654 This makes S->next use XDrawString instead of XDrawImageString. */
3655 if (s
->next
&& s
->right_overhang
)
3657 xassert (s
->next
->img
== NULL
);
3658 x_set_glyph_string_gc (s
->next
);
3659 x_set_glyph_string_clipping (s
->next
);
3660 x_draw_glyph_string_background (s
->next
, 1);
3663 /* Set up S->gc, set clipping and draw S. */
3664 x_set_glyph_string_gc (s
);
3665 x_set_glyph_string_clipping (s
);
3667 switch (s
->first_glyph
->type
)
3670 x_draw_image_glyph_string (s
);
3674 x_draw_stretch_glyph_string (s
);
3678 x_draw_glyph_string_background (s
, 0);
3679 x_draw_glyph_string_foreground (s
);
3686 /* Draw underline. */
3687 if (s
->face
->underline_p
)
3689 unsigned long dy
, h
;
3691 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3693 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &dy
))
3696 if (s
->face
->underline_defaulted_p
)
3697 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3702 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3703 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3704 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3706 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3710 /* Draw overline. */
3711 if (s
->face
->overline_p
)
3713 unsigned long dy
= 0, h
= 1;
3715 if (s
->face
->overline_color_defaulted_p
)
3716 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3721 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3722 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3723 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3725 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3729 /* Draw strike-through. */
3730 if (s
->face
->strike_through_p
)
3732 unsigned long h
= 1;
3733 unsigned long dy
= (s
->height
- h
) / 2;
3735 if (s
->face
->strike_through_color_defaulted_p
)
3736 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3741 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3742 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3743 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3745 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3750 if (s
->face
->box
!= FACE_NO_BOX
)
3751 x_draw_glyph_string_box (s
);
3753 /* Reset clipping. */
3754 XSetClipMask (s
->display
, s
->gc
, None
);
3758 /* A work-list entry used during the construction of glyph_string
3759 structures for a composite character. */
3763 /* Pointer to composite char info defining has the composite
3764 character is drawn. */
3765 struct cmpchar_info
*cmpcharp
;
3767 /* Start index in compcharp->glyph[]. */
3770 /* Next in stack. */
3775 static void x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
3776 int, struct work
**,
3780 /* Load glyph string S with information from the top of *STACK for a
3781 composite character. FACE_ID is the id of the face in which S is
3782 drawn. *NEW is a pointer to a struct work not on the stack, that
3783 can be used if this function needs to push a new structure on the
3784 stack. If it uses it, *NEW is set to null. */
3787 x_fill_composite_glyph_string (s
, face_id
, stack
, new)
3788 struct glyph_string
*s
;
3790 struct work
**stack
, **new;
3795 xassert (s
&& *new && *stack
);
3797 /* Pop the work stack. */
3799 *stack
= work
->next
;
3801 /* For all glyphs of cmpcharp->glyph, starting at the offset
3802 work->offset, until we reach the end of the definition or
3803 encounter another composite char, get the font and face to use,
3805 for (i
= work
->gidx
; i
< work
->cmpcharp
->glyph_len
; ++i
)
3807 c
= FAST_GLYPH_CHAR (work
->cmpcharp
->glyph
[i
]);
3808 if (CHAR_CHARSET (c
) == CHARSET_COMPOSITION
)
3810 s
->face
= x_get_char_face_and_encoding (s
->f
, c
, face_id
,
3811 s
->char2b
+ s
->nchars
, 1);
3812 s
->font
= s
->face
->font
;
3813 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
3817 /* If we find another composite char in the glyph definition of
3818 work->cmpcharp, put back the rest of the glyphs on the work
3819 stack, and make a new entry for the composite char. */
3820 if (i
< work
->cmpcharp
->glyph_len
)
3822 /* Push back an unprocessed rest of this glyph spec. */
3823 if (i
< work
->cmpcharp
->glyph_len
- 1)
3826 work
->next
= *stack
;
3832 /* Make an entry for the composite char on the work stack. */
3833 work
->cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (c
)];
3835 work
->next
= *stack
;
3839 /* The width of this glyph string equals the width of the first
3840 glyph. All characters are drawn at the same x-position. */
3841 s
->width
= s
->first_glyph
->pixel_width
;
3843 /* If the specified font could not be loaded, use the frame's
3844 default font, but record the fact that we couldn't load it in
3845 the glyph string so that we can draw rectangles for the
3846 characters of the glyph string. */
3847 if (s
->font
== NULL
)
3849 s
->font_not_found_p
= 1;
3850 s
->font
= FRAME_FONT (s
->f
);
3853 /* Adjust base line for subscript/superscript text. */
3854 s
->ybase
+= s
->first_glyph
->voffset
;
3856 xassert (s
->face
&& s
->face
->gc
);
3858 /* This glyph string must always be drawn with 16-bit functions. */
3863 /* Load glyph string S with a sequence of non-composite characters.
3864 FACE_ID is the face id of the string. START is the index of the
3865 first glyph to consider, END is the index of the last + 1. Value
3866 is the index of the first glyph not in S. */
3869 x_fill_glyph_string (s
, face_id
, start
, end
)
3870 struct glyph_string
*s
;
3874 struct glyph
*glyph
, *last
;
3877 xassert (s
->charset
!= CHARSET_COMPOSITION
);
3878 xassert (s
->f
== XFRAME (s
->w
->frame
));
3879 xassert (s
->nchars
== 0);
3880 xassert (start
>= 0 && end
> start
);
3882 glyph
= s
->row
->glyphs
[s
->area
] + start
;
3883 last
= s
->row
->glyphs
[s
->area
] + end
;
3884 voffset
= glyph
->voffset
;
3887 && glyph
->type
== CHAR_GLYPH
3888 && glyph
->voffset
== voffset
3889 /* Same face id implies same charset, nowadays. */
3890 && glyph
->u
.ch
.face_id
== face_id
)
3892 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
3893 s
->char2b
+ s
->nchars
);
3894 if (s
->char2b
[s
->nchars
].byte2
!= 0)
3898 xassert (s
->nchars
<= end
- start
);
3899 s
->width
+= glyph
->pixel_width
;
3903 s
->font
= s
->face
->font
;
3904 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
3906 /* If the specified font could not be loaded, use the frame's font,
3907 but record the fact that we couldn't load it in
3908 S->font_not_found_p so that we can draw rectangles for the
3909 characters of the glyph string. */
3910 if (s
->font
== NULL
)
3912 s
->font_not_found_p
= 1;
3913 s
->font
= FRAME_FONT (s
->f
);
3916 /* Adjust base line for subscript/superscript text. */
3917 s
->ybase
+= voffset
;
3919 xassert (s
->face
&& s
->face
->gc
);
3920 return glyph
- s
->row
->glyphs
[s
->area
];
3924 /* Fill glyph string S from image glyph S->first_glyph. */
3927 x_fill_image_glyph_string (s
)
3928 struct glyph_string
*s
;
3930 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
3931 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.id
);
3933 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.face_id
);
3934 s
->font
= s
->face
->font
;
3935 s
->width
= s
->first_glyph
->pixel_width
;
3937 /* Adjust base line for subscript/superscript text. */
3938 s
->ybase
+= s
->first_glyph
->voffset
;
3942 /* Fill glyph string S from stretch glyph S->first_glyph. */
3945 x_fill_stretch_glyph_string (s
)
3946 struct glyph_string
*s
;
3948 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3949 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.stretch
.face_id
);
3950 s
->font
= s
->face
->font
;
3951 s
->width
= s
->first_glyph
->pixel_width
;
3953 /* Adjust base line for subscript/superscript text. */
3954 s
->ybase
+= s
->first_glyph
->voffset
;
3958 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
3959 of XChar2b structures for S; it can't be allocated in
3960 x_init_glyph_string because it must be allocated via `alloca'. W
3961 is the window on which S is drawn. ROW and AREA are the glyph row
3962 and area within the row from which S is constructed. START is the
3963 index of the first glyph structure covered by S. HL is a
3964 face-override for drawing S. */
3967 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
3968 struct glyph_string
*s
;
3971 struct glyph_row
*row
;
3972 enum glyph_row_area area
;
3974 enum draw_glyphs_face hl
;
3976 bzero (s
, sizeof *s
);
3978 s
->f
= XFRAME (w
->frame
);
3979 s
->display
= FRAME_X_DISPLAY (s
->f
);
3980 s
->window
= FRAME_X_WINDOW (s
->f
);
3985 s
->first_glyph
= row
->glyphs
[area
] + start
;
3986 s
->height
= row
->height
;
3987 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
3989 /* Display the internal border below the toolbar window. */
3990 if (s
->w
== XWINDOW (s
->f
->toolbar_window
))
3991 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
3993 s
->ybase
= s
->y
+ row
->ascent
;
3997 /* Set background width of glyph string S. START is the index of the
3998 first glyph following S. LAST_X is the right-most x-position + 1
3999 in the drawing area. */
4002 x_set_glyph_string_background_width (s
, start
, last_x
)
4003 struct glyph_string
*s
;
4007 /* If the face of this glyph string has to be drawn to the end of
4008 the drawing area, set S->extends_to_end_of_line_p. */
4009 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4011 if (start
== s
->row
->used
[s
->area
]
4012 && s
->hl
== DRAW_NORMAL_TEXT
4013 && ((s
->area
== TEXT_AREA
&& s
->row
->fill_line_p
)
4014 || s
->face
->background
!= default_face
->background
4015 || s
->face
->stipple
!= default_face
->stipple
))
4016 s
->extends_to_end_of_line_p
= 1;
4018 /* If S extends its face to the end of the line, set its
4019 background_width to the distance to the right edge of the drawing
4021 if (s
->extends_to_end_of_line_p
)
4022 s
->background_width
= last_x
- s
->x
;
4024 s
->background_width
= s
->width
;
4028 /* Add a glyph string for a stretch glyph to the list of strings
4029 between HEAD and TAIL. START is the index of the stretch glyph in
4030 row area AREA of glyph row ROW. END is the index of the last glyph
4031 in that glyph row area. X is the current output position assigned
4032 to the new glyph string constructed. HL overrides that face of the
4033 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4034 is the right-most x-position of the drawing area. */
4036 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, \
4040 s = (struct glyph_string *) alloca (sizeof *s); \
4041 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4042 x_fill_stretch_glyph_string (s); \
4043 x_append_glyph_string (&HEAD, &TAIL, s); \
4050 /* Add a glyph string for an image glyph to the list of strings
4051 between HEAD and TAIL. START is the index of the image glyph in
4052 row area AREA of glyph row ROW. END is the index of the last glyph
4053 in that glyph row area. X is the current output position assigned
4054 to the new glyph string constructed. HL overrides that face of the
4055 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4056 is the right-most x-position of the drawing area. */
4058 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, \
4062 s = (struct glyph_string *) alloca (sizeof *s); \
4063 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4064 x_fill_image_glyph_string (s); \
4065 x_append_glyph_string (&HEAD, &TAIL, s); \
4072 /* Add a glyph string for a sequence of character glyphs to the list
4073 of strings between HEAD and TAIL. START is the index of the first
4074 glyph in row area AREA of glyph row ROW that is part of the new
4075 glyph string. END is the index of the last glyph in that glyph row
4076 area. X is the current output position assigned to the new glyph
4077 string constructed. HL overrides that face of the glyph; e.g. it
4078 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4079 right-most x-position of the drawing area. */
4081 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, \
4085 int c, charset, face_id; \
4088 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4089 charset = CHAR_CHARSET (c); \
4090 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4092 if (charset == CHARSET_COMPOSITION) \
4094 struct work *stack, *work, *new = NULL; \
4096 struct glyph_string *first_s = NULL; \
4098 /* Push an initial entry for character c on the stack. */ \
4100 work = (struct work *) alloca (sizeof *work); \
4101 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; \
4103 work->next = stack; \
4106 /* While the stack is not empty, append glyph_strings \
4107 to head/tail for glyphs to draw. */ \
4110 s = (struct glyph_string *) alloca (sizeof *s); \
4111 char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len \
4112 * sizeof (XChar2b)); \
4113 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4114 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4115 s->cmpcharp = stack->cmpcharp; \
4116 s->gidx = stack->gidx; \
4117 s->charset = charset; \
4122 /* Don't draw the background except for the \
4123 first glyph string. */ \
4124 s->background_filled_p = n > 0; \
4130 new = (struct work *) alloca (sizeof *new); \
4131 x_fill_composite_glyph_string (s, face_id, &stack, \
4140 s = (struct glyph_string *) alloca (sizeof *s); \
4141 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4142 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4143 x_append_glyph_string (&HEAD, &TAIL, s); \
4144 s->charset = charset; \
4146 START = x_fill_glyph_string (s, face_id, START, END); \
4152 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4153 of AREA of glyph row ROW on window W between indices START and END.
4154 HL overrides the face for drawing glyph strings, e.g. it is
4155 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4156 x-positions of the drawing area.
4158 This is an ugly monster macro construct because we must use alloca
4159 to allocate glyph strings (because x_draw_glyphs can be called
4162 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, \
4166 HEAD = TAIL = NULL; \
4167 while (START < END) \
4169 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4170 switch (first_glyph->type) \
4173 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4174 TAIL, HL, X, LAST_X); \
4177 case STRETCH_GLYPH: \
4178 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4179 HEAD, TAIL, HL, X, LAST_X); \
4183 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4184 TAIL, HL, X, LAST_X); \
4191 x_set_glyph_string_background_width (s, START, LAST_X); \
4198 /* Draw glyphs between START and END in AREA of ROW on window W,
4199 starting at x-position X. X is relative to AREA in W. HL is a
4200 face-override with the following meaning:
4202 DRAW_NORMAL_TEXT draw normally
4203 DRAW_CURSOR draw in cursor face
4204 DRAW_MOUSE_FACE draw in mouse face.
4205 DRAW_INVERSE_VIDEO draw in mode line face
4206 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4207 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4209 If REAL_START is non-null, return in *REAL_START the real starting
4210 position for display. This can be different from START in case
4211 overlapping glyphs must be displayed. If REAL_END is non-null,
4212 return in *REAL_END the real end position for display. This can be
4213 different from END in case overlapping glyphs must be displayed.
4215 Value is the x-position reached, relative to AREA of W. */
4218 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, real_start
, real_end
)
4221 struct glyph_row
*row
;
4222 enum glyph_row_area area
;
4224 enum draw_glyphs_face hl
;
4225 int *real_start
, *real_end
;
4227 struct glyph_string
*head
, *tail
;
4228 struct glyph_string
*s
;
4229 int last_x
, area_width
;
4233 /* Let's rather be paranoid than getting a SEGV. */
4234 start
= max (0, start
);
4235 end
= min (end
, row
->used
[area
]);
4237 *real_start
= start
;
4241 /* Translate X to frame coordinates. Set last_x to the right
4242 end of the drawing area. */
4243 if (row
->full_width_p
)
4245 /* X is relative to the left edge of W, without scroll bars
4247 struct frame
*f
= XFRAME (w
->frame
);
4248 int width
= FRAME_FLAGS_AREA_WIDTH (f
);
4249 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
4252 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4253 last_x
= window_left_x
+ area_width
;
4255 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4257 width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4258 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4264 /* If row should extend over internal borders, adjust x and
4265 width accordingly. */
4266 if (row
->internal_border_p
)
4268 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
4269 width
-= 2 * FRAME_INTERNAL_BORDER_WIDTH (f
);
4274 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
4275 area_width
= window_box_width (w
, area
);
4276 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
4279 /* Build a doubly-linked list of glyph_string structures between
4280 head and tail from what we have to draw. Note that the macro
4281 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4282 the reason we use a separate variable `i'. */
4284 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
);
4286 x_reached
= tail
->x
+ tail
->background_width
;
4290 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4291 the row, redraw some glyphs in front or following the glyph
4292 strings built above. */
4293 if (row
->contains_overlapping_glyphs_p
)
4296 struct glyph_string
*h
, *t
;
4298 /* Compute overhangs for all glyph strings. */
4299 for (s
= head
; s
; s
= s
->next
)
4300 x_compute_glyph_string_overhangs (s
);
4302 /* Prepend glyph strings for glyphs in front of the first glyph
4303 string that are overwritten because of the first glyph
4304 string's left overhang. The background of all strings
4305 prepended must be drawn because the first glyph string
4307 i
= x_left_overwritten (head
);
4311 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
4312 DRAW_NORMAL_TEXT
, dummy_x
, last_x
);
4315 *real_start
= start
;
4316 x_compute_overhangs_and_x (t
, head
->x
, 1);
4317 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4320 /* Prepend glyph strings for glyphs in front of the first glyph
4321 string that overwrite that glyph string because of their
4322 right overhang. For these strings, only the foreground must
4323 be drawn, because it draws over the glyph string at `head'.
4324 The background must not be drawn because this would overwrite
4325 right overhangs of preceding glyphs for which no glyph
4327 i
= x_left_overwriting (head
);
4330 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
4331 DRAW_NORMAL_TEXT
, dummy_x
, last_x
);
4332 for (s
= h
; s
; s
= s
->next
)
4333 s
->background_filled_p
= 1;
4336 x_compute_overhangs_and_x (t
, head
->x
, 1);
4337 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4340 /* Append glyphs strings for glyphs following the last glyph
4341 string tail that are overwritten by tail. The background of
4342 these strings has to be drawn because tail's foreground draws
4344 i
= x_right_overwritten (tail
);
4347 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4348 DRAW_NORMAL_TEXT
, x
, last_x
);
4349 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4350 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4355 /* Append glyph strings for glyphs following the last glyph
4356 string tail that overwrite tail. The foreground of such
4357 glyphs has to be drawn because it writes into the background
4358 of tail. The background must not be drawn because it could
4359 paint over the foreground of following glyphs. */
4360 i
= x_right_overwriting (tail
);
4363 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4364 DRAW_NORMAL_TEXT
, x
, last_x
);
4365 for (s
= h
; s
; s
= s
->next
)
4366 s
->background_filled_p
= 1;
4367 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4368 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4374 /* Draw all strings. */
4375 for (s
= head
; s
; s
= s
->next
)
4376 x_draw_glyph_string (s
);
4378 /* Value is the x-position up to which drawn, relative to AREA of W.
4379 This doesn't include parts drawn because of overhangs. */
4380 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
4381 if (!row
->full_width_p
)
4383 if (area
> LEFT_MARGIN_AREA
)
4384 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
4385 if (area
> TEXT_AREA
)
4386 x_reached
-= window_box_width (w
, TEXT_AREA
);
4392 /* Output LEN glyphs starting at START at the nominal cursor position.
4393 Advance the nominal cursor over the text. The global variable
4394 updated_window contains the window being updated, updated_row is
4395 the glyph row being updated, and updated_area is the area of that
4396 row being updated. */
4399 x_write_glyphs (start
, len
)
4400 struct glyph
*start
;
4403 int x
, hpos
, real_start
, real_end
;
4405 xassert (updated_window
&& updated_row
);
4410 hpos
= start
- updated_row
->glyphs
[updated_area
];
4411 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
4412 updated_row
, updated_area
,
4414 (updated_row
->inverse_p
4415 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4416 &real_start
, &real_end
);
4418 /* If we drew over the cursor, note that it is not visible any more. */
4419 note_overwritten_text_cursor (updated_window
, real_start
,
4420 real_end
- real_start
);
4424 /* Advance the output cursor. */
4425 output_cursor
.hpos
+= len
;
4426 output_cursor
.x
= x
;
4430 /* Insert LEN glyphs from START at the nominal cursor position. */
4433 x_insert_glyphs (start
, len
)
4434 struct glyph
*start
;
4439 int line_height
, shift_by_width
, shifted_region_width
;
4440 struct glyph_row
*row
;
4441 struct glyph
*glyph
;
4442 int frame_x
, frame_y
, hpos
, real_start
, real_end
;
4444 xassert (updated_window
&& updated_row
);
4447 f
= XFRAME (WINDOW_FRAME (w
));
4449 /* Get the height of the line we are in. */
4451 line_height
= row
->height
;
4453 /* Get the width of the glyphs to insert. */
4455 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
4456 shift_by_width
+= glyph
->pixel_width
;
4458 /* Get the width of the region to shift right. */
4459 shifted_region_width
= (window_box_width (w
, updated_area
)
4464 frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, output_cursor
.x
);
4465 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
4466 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4467 f
->output_data
.x
->normal_gc
,
4469 shifted_region_width
, line_height
,
4470 frame_x
+ shift_by_width
, frame_y
);
4472 /* Write the glyphs. */
4473 hpos
= start
- row
->glyphs
[updated_area
];
4474 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
4475 DRAW_NORMAL_TEXT
, &real_start
, &real_end
);
4476 note_overwritten_text_cursor (w
, real_start
, real_end
- real_start
);
4478 /* Advance the output cursor. */
4479 output_cursor
.hpos
+= len
;
4480 output_cursor
.x
+= shift_by_width
;
4485 /* Delete N glyphs at the nominal cursor position. Not implemented
4496 /* Erase the current text line from the nominal cursor position
4497 (inclusive) to pixel column TO_X (exclusive). The idea is that
4498 everything from TO_X onward is already erased.
4500 TO_X is a pixel position relative to updated_area of
4501 updated_window. TO_X == -1 means clear to the end of this area. */
4504 x_clear_end_of_line (to_x
)
4508 struct window
*w
= updated_window
;
4509 int max_x
, min_y
, max_y
;
4510 int from_x
, from_y
, to_y
;
4512 xassert (updated_window
&& updated_row
);
4513 f
= XFRAME (w
->frame
);
4515 if (updated_row
->full_width_p
)
4517 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4518 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4519 && !w
->pseudo_window_p
)
4520 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4523 max_x
= window_box_width (w
, updated_area
);
4524 max_y
= window_text_bottom_y (w
);
4526 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4527 of window. For TO_X > 0, truncate to end of drawing area. */
4533 to_x
= min (to_x
, max_x
);
4535 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
4537 /* Notice if the cursor will be cleared by this operation. */
4538 if (!updated_row
->full_width_p
)
4539 note_overwritten_text_cursor (w
, output_cursor
.hpos
, -1);
4541 from_x
= output_cursor
.x
;
4543 /* Translate to frame coordinates. */
4544 if (updated_row
->full_width_p
)
4546 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
4547 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
4551 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
4552 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
4555 min_y
= WINDOW_DISPLAY_TOP_LINE_HEIGHT (w
);
4556 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
4557 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
4559 /* Prevent inadvertently clearing to end of the X window. */
4560 if (to_x
> from_x
&& to_y
> from_y
)
4563 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4564 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
4571 /* Clear entire frame. If updating_frame is non-null, clear that
4572 frame. Otherwise clear selected_frame. */
4584 /* Clearing the frame will erase any cursor, so mark them all as no
4586 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4587 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4588 output_cursor
.x
= -1;
4590 /* We don't set the output cursor here because there will always
4591 follow an explicit cursor_to. */
4593 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4595 /* We have to clear the scroll bars, too. If we have changed
4596 colors or something like that, then they should be notified. */
4597 x_scroll_bar_clear (f
);
4599 XFlush (FRAME_X_DISPLAY (f
));
4605 /* Invert the middle quarter of the frame for .15 sec. */
4607 /* We use the select system call to do the waiting, so we have to make
4608 sure it's available. If it isn't, we just won't do visual bells. */
4610 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4613 /* Subtract the `struct timeval' values X and Y, storing the result in
4614 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4617 timeval_subtract (result
, x
, y
)
4618 struct timeval
*result
, x
, y
;
4620 /* Perform the carry for the later subtraction by updating y. This
4621 is safer because on some systems the tv_sec member is unsigned. */
4622 if (x
.tv_usec
< y
.tv_usec
)
4624 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4625 y
.tv_usec
-= 1000000 * nsec
;
4629 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4631 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4632 y
.tv_usec
+= 1000000 * nsec
;
4636 /* Compute the time remaining to wait. tv_usec is certainly
4638 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4639 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4641 /* Return indication of whether the result should be considered
4643 return x
.tv_sec
< y
.tv_sec
;
4655 /* Create a GC that will use the GXxor function to flip foreground
4656 pixels into background pixels. */
4660 values
.function
= GXxor
;
4661 values
.foreground
= (f
->output_data
.x
->foreground_pixel
4662 ^ f
->output_data
.x
->background_pixel
);
4664 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4665 GCFunction
| GCForeground
, &values
);
4669 /* Get the height not including a menu bar widget. */
4670 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
4671 /* Height of each line to flash. */
4672 int flash_height
= FRAME_LINE_HEIGHT (f
);
4673 /* These will be the left and right margins of the rectangles. */
4674 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4675 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4679 /* Don't flash the area between a scroll bar and the frame
4680 edge it is next to. */
4681 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4683 case vertical_scroll_bar_left
:
4684 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4687 case vertical_scroll_bar_right
:
4688 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4695 width
= flash_right
- flash_left
;
4697 /* If window is tall, flash top and bottom line. */
4698 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4700 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4702 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4703 + FRAME_TOOLBAR_LINES (f
) * CANON_Y_UNIT (f
)),
4704 width
, flash_height
);
4705 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4707 (height
- flash_height
4708 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4709 width
, flash_height
);
4712 /* If it is short, flash it all. */
4713 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4714 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4715 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4720 struct timeval wakeup
;
4722 EMACS_GET_TIME (wakeup
);
4724 /* Compute time to wait until, propagating carry from usecs. */
4725 wakeup
.tv_usec
+= 150000;
4726 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4727 wakeup
.tv_usec
%= 1000000;
4729 /* Keep waiting until past the time wakeup. */
4732 struct timeval timeout
;
4734 EMACS_GET_TIME (timeout
);
4736 /* In effect, timeout = wakeup - timeout.
4737 Break if result would be negative. */
4738 if (timeval_subtract (&timeout
, wakeup
, timeout
))
4741 /* Try to wait that long--but we might wake up sooner. */
4742 select (0, NULL
, NULL
, NULL
, &timeout
);
4746 /* If window is tall, flash top and bottom line. */
4747 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4749 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4751 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4752 + FRAME_TOOLBAR_LINES (f
) * CANON_Y_UNIT (f
)),
4753 width
, flash_height
);
4754 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4756 (height
- flash_height
4757 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4758 width
, flash_height
);
4761 /* If it is short, flash it all. */
4762 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4763 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4764 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4766 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
4774 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4777 /* Make audible bell. */
4779 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
4784 if (FRAME_X_DISPLAY (selected_frame
) == 0)
4787 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4789 XTflash (selected_frame
);
4795 XFlush (FRAME_X_DISPLAY (selected_frame
));
4801 /* Specify how many text lines, from the top of the window,
4802 should be affected by insert-lines and delete-lines operations.
4803 This, and those operations, are used only within an update
4804 that is bounded by calls to x_update_begin and x_update_end. */
4807 XTset_terminal_window (n
)
4810 /* This function intentionally left blank. */
4815 /***********************************************************************
4817 ***********************************************************************/
4819 /* Perform an insert-lines or delete-lines operation, inserting N
4820 lines or deleting -N lines at vertical position VPOS. */
4823 x_ins_del_lines (vpos
, n
)
4830 /* Scroll part of the display as described by RUN. */
4833 x_scroll_run (w
, run
)
4837 struct frame
*f
= XFRAME (w
->frame
);
4838 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4840 /* Get frame-relative bounding box of the text display area of W,
4841 without mode lines. Include in this box the flags areas to the
4842 left and right of W. */
4843 window_box (w
, -1, &x
, &y
, &width
, &height
);
4844 width
+= 2 * FRAME_X_FLAGS_AREA_WIDTH (f
);
4845 x
-= FRAME_X_FLAGS_AREA_WIDTH (f
);
4847 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
4848 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
4849 bottom_y
= y
+ height
;
4853 /* Scrolling up. Make sure we don't copy part of the mode
4854 line at the bottom. */
4855 if (from_y
+ run
->height
> bottom_y
)
4856 height
= bottom_y
- from_y
;
4858 height
= run
->height
;
4862 /* Scolling down. Make sure we don't copy over the mode line.
4864 if (to_y
+ run
->height
> bottom_y
)
4865 height
= bottom_y
- to_y
;
4867 height
= run
->height
;
4872 /* Cursor off. Will be switched on again in x_update_window_end. */
4876 XCopyArea (FRAME_X_DISPLAY (f
),
4877 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4878 f
->output_data
.x
->normal_gc
,
4888 /***********************************************************************
4890 ***********************************************************************/
4892 /* Redisplay an exposed area of frame F. X and Y are the upper-left
4893 corner of the exposed rectangle. W and H are width and height of
4894 the exposed area. All are pixel values. W or H zero means redraw
4895 the entire frame. */
4898 expose_frame (f
, x
, y
, w
, h
)
4904 TRACE ((stderr
, "expose_frame "));
4906 /* No need to redraw if frame will be redrawn soon. */
4907 if (FRAME_GARBAGED_P (f
))
4909 TRACE ((stderr
, " garbaged\n"));
4913 /* If basic faces haven't been realized yet, there is no point in
4914 trying to redraw anything. This can happen when we get an expose
4915 event while Emacs is starting, e.g. by moving another window. */
4916 if (FRAME_FACE_CACHE (f
) == NULL
4917 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
4919 TRACE ((stderr
, " no faces\n"));
4923 if (w
== 0 || h
== 0)
4926 r
.width
= CANON_X_UNIT (f
) * f
->width
;
4927 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
4937 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
4938 expose_window_tree (XWINDOW (f
->root_window
), &r
);
4940 if (WINDOWP (f
->toolbar_window
))
4942 struct window
*w
= XWINDOW (f
->toolbar_window
);
4943 XRectangle window_rect
;
4944 XRectangle intersection_rect
;
4945 int window_x
, window_y
, window_width
, window_height
;
4948 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
4949 window_rect
.x
= window_x
;
4950 window_rect
.y
= window_y
;
4951 window_rect
.width
= window_width
;
4952 window_rect
.height
= window_height
;
4954 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
4955 expose_window (w
, &intersection_rect
);
4958 #ifndef USE_X_TOOLKIT
4959 if (WINDOWP (f
->menu_bar_window
))
4961 struct window
*w
= XWINDOW (f
->menu_bar_window
);
4962 XRectangle window_rect
;
4963 XRectangle intersection_rect
;
4964 int window_x
, window_y
, window_width
, window_height
;
4967 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
4968 window_rect
.x
= window_x
;
4969 window_rect
.y
= window_y
;
4970 window_rect
.width
= window_width
;
4971 window_rect
.height
= window_height
;
4973 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
4974 expose_window (w
, &intersection_rect
);
4976 #endif /* not USE_X_TOOLKIT */
4980 /* Redraw (parts) of all windows in the window tree rooted at W that
4981 intersect R. R contains frame pixel coordinates. */
4984 expose_window_tree (w
, r
)
4990 if (!NILP (w
->hchild
))
4991 expose_window_tree (XWINDOW (w
->hchild
), r
);
4992 else if (!NILP (w
->vchild
))
4993 expose_window_tree (XWINDOW (w
->vchild
), r
);
4996 XRectangle window_rect
;
4997 XRectangle intersection_rect
;
4998 struct frame
*f
= XFRAME (w
->frame
);
4999 int window_x
, window_y
, window_width
, window_height
;
5001 /* Frame-relative pixel rectangle of W. */
5002 window_box (w
, -1, &window_x
, &window_y
, &window_width
,
5006 - FRAME_X_FLAGS_AREA_WIDTH (f
)
5007 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_Y_UNIT (f
));
5008 window_rect
.y
= window_y
;
5011 + 2 * FRAME_X_FLAGS_AREA_WIDTH (f
)
5012 + FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5014 = window_height
+ CURRENT_MODE_LINE_HEIGHT (w
);
5016 if (x_intersect_rectangles (r
, &window_rect
, &intersection_rect
))
5017 expose_window (w
, &intersection_rect
);
5020 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5025 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5026 which intersects rectangle R. R is in window-relative coordinates. */
5029 expose_area (w
, row
, r
, area
)
5031 struct glyph_row
*row
;
5033 enum glyph_row_area area
;
5036 struct glyph
*first
= row
->glyphs
[area
];
5037 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5041 /* Set x to the window-relative start position for drawing glyphs of
5042 AREA. The first glyph of the text area can be partially visible.
5043 The first glyphs of other areas cannot. */
5044 if (area
== LEFT_MARGIN_AREA
)
5046 else if (area
== TEXT_AREA
)
5047 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5049 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5050 + window_box_width (w
, TEXT_AREA
));
5052 /* Find the first glyph that must be redrawn. */
5054 && x
+ first
->pixel_width
< r
->x
)
5056 x
+= first
->pixel_width
;
5060 /* Find the last one. */
5064 && x
< r
->x
+ r
->width
)
5066 x
+= last
->pixel_width
;
5072 x_draw_glyphs (w
, first_x
, row
, area
,
5073 first
- row
->glyphs
[area
],
5074 last
- row
->glyphs
[area
],
5075 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5080 /* Redraw the parts of the glyph row ROW on window W intersecting
5081 rectangle R. R is in window-relative coordinates. */
5084 expose_line (w
, row
, r
)
5086 struct glyph_row
*row
;
5089 xassert (row
->enabled_p
);
5091 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5092 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5093 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5097 if (row
->used
[LEFT_MARGIN_AREA
])
5098 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5099 if (row
->used
[TEXT_AREA
])
5100 expose_area (w
, row
, r
, TEXT_AREA
);
5101 if (row
->used
[RIGHT_MARGIN_AREA
])
5102 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5103 x_draw_row_bitmaps (w
, row
);
5108 /* Return non-zero if W's cursor intersects rectangle R. */
5111 x_phys_cursor_in_rect_p (w
, r
)
5115 XRectangle cr
, result
;
5116 struct glyph
*cursor_glyph
;
5118 cursor_glyph
= get_phys_cursor_glyph (w
);
5121 cr
.x
= w
->phys_cursor
.x
;
5122 cr
.y
= w
->phys_cursor
.y
;
5123 cr
.width
= cursor_glyph
->pixel_width
;
5124 cr
.height
= w
->phys_cursor_height
;
5125 return x_intersect_rectangles (&cr
, r
, &result
);
5132 /* Redraw a rectangle of window W. R is a rectangle in window
5133 relative coordinates. Call this function with input blocked. */
5136 expose_window (w
, r
)
5140 struct glyph_row
*row
;
5142 int yb
= window_text_bottom_y (w
);
5143 int cursor_cleared_p
;
5145 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
5146 r
->x
, r
->y
, r
->width
, r
->height
));
5148 /* Convert to window coordinates. */
5149 r
->x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
->x
);
5150 r
->y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
->y
);
5152 /* Turn off the cursor. */
5153 if (!w
->pseudo_window_p
5154 && x_phys_cursor_in_rect_p (w
, r
))
5157 cursor_cleared_p
= 1;
5160 cursor_cleared_p
= 0;
5162 /* Find the first row intersecting the rectangle R. */
5163 row
= w
->current_matrix
->rows
;
5165 while (row
->enabled_p
5167 && y
+ row
->height
< r
->y
)
5173 /* Display the text in the rectangle, one text line at a time. */
5174 while (row
->enabled_p
5176 && y
< r
->y
+ r
->height
)
5178 expose_line (w
, row
, r
);
5183 /* Display the mode line if there is one. */
5184 if (WINDOW_WANTS_MODELINE_P (w
)
5185 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
5187 && row
->y
< r
->y
+ r
->height
)
5188 expose_line (w
, row
, r
);
5190 if (!w
->pseudo_window_p
)
5192 /* Draw border between windows. */
5193 x_draw_vertical_border (w
);
5195 /* Turn the cursor on again. */
5196 if (cursor_cleared_p
)
5197 x_update_window_cursor (w
, 1);
5202 /* Determine the intersection of two rectangles R1 and R2. Return
5203 the intersection in *RESULT. Value is non-zero if RESULT is not
5207 x_intersect_rectangles (r1
, r2
, result
)
5208 XRectangle
*r1
, *r2
, *result
;
5210 XRectangle
*left
, *right
;
5211 XRectangle
*upper
, *lower
;
5212 int intersection_p
= 0;
5214 /* Rearrange so that R1 is the left-most rectangle. */
5216 left
= r1
, right
= r2
;
5218 left
= r2
, right
= r1
;
5220 /* X0 of the intersection is right.x0, if this is inside R1,
5221 otherwise there is no intersection. */
5222 if (right
->x
<= left
->x
+ left
->width
)
5224 result
->x
= right
->x
;
5226 /* The right end of the intersection is the minimum of the
5227 the right ends of left and right. */
5228 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
5231 /* Same game for Y. */
5233 upper
= r1
, lower
= r2
;
5235 upper
= r2
, lower
= r1
;
5237 /* The upper end of the intersection is lower.y0, if this is inside
5238 of upper. Otherwise, there is no intersection. */
5239 if (lower
->y
<= upper
->y
+ upper
->height
)
5241 result
->y
= lower
->y
;
5243 /* The lower end of the intersection is the minimum of the lower
5244 ends of upper and lower. */
5245 result
->height
= (min (lower
->y
+ lower
->height
,
5246 upper
->y
+ upper
->height
)
5252 return intersection_p
;
5263 /* We used to only do this if Vx_no_window_manager was non-nil, but
5264 the ICCCM (section 4.1.6) says that the window's border pixmap
5265 and border pixel are window attributes which are "private to the
5266 client", so we can always change it to whatever we want. */
5268 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5269 f
->output_data
.x
->border_pixel
);
5271 x_update_cursor (f
, 1);
5275 frame_unhighlight (f
)
5278 /* We used to only do this if Vx_no_window_manager was non-nil, but
5279 the ICCCM (section 4.1.6) says that the window's border pixmap
5280 and border pixel are window attributes which are "private to the
5281 client", so we can always change it to whatever we want. */
5283 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5284 f
->output_data
.x
->border_tile
);
5286 x_update_cursor (f
, 1);
5289 /* The focus has changed. Update the frames as necessary to reflect
5290 the new situation. Note that we can't change the selected frame
5291 here, because the Lisp code we are interrupting might become confused.
5292 Each event gets marked with the frame in which it occurred, so the
5293 Lisp code can tell when the switch took place by examining the events. */
5296 x_new_focus_frame (dpyinfo
, frame
)
5297 struct x_display_info
*dpyinfo
;
5298 struct frame
*frame
;
5300 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5302 if (frame
!= dpyinfo
->x_focus_frame
)
5304 /* Set this before calling other routines, so that they see
5305 the correct value of x_focus_frame. */
5306 dpyinfo
->x_focus_frame
= frame
;
5308 if (old_focus
&& old_focus
->auto_lower
)
5309 x_lower_frame (old_focus
);
5312 selected_frame
= frame
;
5313 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
5315 Fselect_window (selected_frame
->selected_window
);
5316 choose_minibuf_frame ();
5319 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
5320 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
5322 pending_autoraise_frame
= 0;
5325 x_frame_rehighlight (dpyinfo
);
5328 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5331 x_mouse_leave (dpyinfo
)
5332 struct x_display_info
*dpyinfo
;
5334 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
5337 /* The focus has changed, or we have redirected a frame's focus to
5338 another frame (this happens when a frame uses a surrogate
5339 mini-buffer frame). Shift the highlight as appropriate.
5341 The FRAME argument doesn't necessarily have anything to do with which
5342 frame is being highlighted or un-highlighted; we only use it to find
5343 the appropriate X display info. */
5346 XTframe_rehighlight (frame
)
5347 struct frame
*frame
;
5349 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
5353 x_frame_rehighlight (dpyinfo
)
5354 struct x_display_info
*dpyinfo
;
5356 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
5358 if (dpyinfo
->x_focus_frame
)
5360 dpyinfo
->x_highlight_frame
5361 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
5362 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
5363 : dpyinfo
->x_focus_frame
);
5364 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
5366 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
5367 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
5371 dpyinfo
->x_highlight_frame
= 0;
5373 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
5376 frame_unhighlight (old_highlight
);
5377 if (dpyinfo
->x_highlight_frame
)
5378 frame_highlight (dpyinfo
->x_highlight_frame
);
5384 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5386 /* Initialize mode_switch_bit and modifier_meaning. */
5388 x_find_modifier_meanings (dpyinfo
)
5389 struct x_display_info
*dpyinfo
;
5391 int min_code
, max_code
;
5394 XModifierKeymap
*mods
;
5396 dpyinfo
->meta_mod_mask
= 0;
5397 dpyinfo
->shift_lock_mask
= 0;
5398 dpyinfo
->alt_mod_mask
= 0;
5399 dpyinfo
->super_mod_mask
= 0;
5400 dpyinfo
->hyper_mod_mask
= 0;
5403 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
5405 min_code
= dpyinfo
->display
->min_keycode
;
5406 max_code
= dpyinfo
->display
->max_keycode
;
5409 syms
= XGetKeyboardMapping (dpyinfo
->display
,
5410 min_code
, max_code
- min_code
+ 1,
5412 mods
= XGetModifierMapping (dpyinfo
->display
);
5414 /* Scan the modifier table to see which modifier bits the Meta and
5415 Alt keysyms are on. */
5417 int row
, col
; /* The row and column in the modifier table. */
5419 for (row
= 3; row
< 8; row
++)
5420 for (col
= 0; col
< mods
->max_keypermod
; col
++)
5423 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
5425 /* Zeroes are used for filler. Skip them. */
5429 /* Are any of this keycode's keysyms a meta key? */
5433 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
5435 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
5441 dpyinfo
->meta_mod_mask
|= (1 << row
);
5446 dpyinfo
->alt_mod_mask
|= (1 << row
);
5451 dpyinfo
->hyper_mod_mask
|= (1 << row
);
5456 dpyinfo
->super_mod_mask
|= (1 << row
);
5460 /* Ignore this if it's not on the lock modifier. */
5461 if ((1 << row
) == LockMask
)
5462 dpyinfo
->shift_lock_mask
= LockMask
;
5470 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5471 if (! dpyinfo
->meta_mod_mask
)
5473 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
5474 dpyinfo
->alt_mod_mask
= 0;
5477 /* If some keys are both alt and meta,
5478 make them just meta, not alt. */
5479 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
5481 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
5484 XFree ((char *) syms
);
5485 XFreeModifiermap (mods
);
5488 /* Convert between the modifier bits X uses and the modifier bits
5492 x_x_to_emacs_modifiers (dpyinfo
, state
)
5493 struct x_display_info
*dpyinfo
;
5496 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
5497 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
5498 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
5499 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
5500 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
5501 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
5505 x_emacs_to_x_modifiers (dpyinfo
, state
)
5506 struct x_display_info
*dpyinfo
;
5509 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
5510 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
5511 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
5512 | ((state
& shift_modifier
) ? ShiftMask
: 0)
5513 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
5514 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
5517 /* Convert a keysym to its name. */
5520 x_get_keysym_name (keysym
)
5526 value
= XKeysymToString (keysym
);
5534 /* Mouse clicks and mouse movement. Rah. */
5536 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5537 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5538 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5539 not force the value into range. */
5542 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
5544 register int pix_x
, pix_y
;
5545 register int *x
, *y
;
5549 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5550 even for negative values. */
5552 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
5554 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
5556 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
5557 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
5561 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
5562 bounds
->height
= f
->output_data
.x
->line_height
;
5563 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
5564 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
5571 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
5572 pix_x
= FRAME_WINDOW_WIDTH (f
);
5576 else if (pix_y
> f
->height
)
5585 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5586 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5587 can't tell the positions because W's display is not up to date,
5591 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
5594 int *frame_x
, *frame_y
;
5598 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
5599 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
5601 if (display_completed
)
5603 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
5604 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
5605 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
5611 *frame_x
+= glyph
->pixel_width
;
5619 *frame_y
= *frame_x
= 0;
5623 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
5624 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
5629 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5631 If the event is a button press, then note that we have grabbed
5635 construct_mouse_click (result
, event
, f
)
5636 struct input_event
*result
;
5637 XButtonEvent
*event
;
5640 /* Make the event type no_event; we'll change that when we decide
5642 result
->kind
= mouse_click
;
5643 result
->code
= event
->button
- Button1
;
5644 result
->timestamp
= event
->time
;
5645 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5647 | (event
->type
== ButtonRelease
5651 XSETINT (result
->x
, event
->x
);
5652 XSETINT (result
->y
, event
->y
);
5653 XSETFRAME (result
->frame_or_window
, f
);
5657 #if 0 /* This function isn't called. --gerd */
5659 /* Prepare a menu-event in *RESULT for placement in the input queue. */
5662 construct_menu_click (result
, event
, f
)
5663 struct input_event
*result
;
5664 XButtonEvent
*event
;
5667 /* Make the event type no_event; we'll change that when we decide
5669 result
->kind
= mouse_click
;
5670 result
->code
= event
->button
- Button1
;
5671 result
->timestamp
= event
->time
;
5672 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5674 | (event
->type
== ButtonRelease
5678 XSETINT (result
->x
, event
->x
);
5679 XSETINT (result
->y
, -1);
5680 XSETFRAME (result
->frame_or_window
, f
);
5686 /* Function to report a mouse movement to the mainstream Emacs code.
5687 The input handler calls this.
5689 We have received a mouse movement event, which is given in *event.
5690 If the mouse is over a different glyph than it was last time, tell
5691 the mainstream emacs code by setting mouse_moved. If not, ask for
5692 another motion event, so we can check again the next time it moves. */
5694 static XMotionEvent last_mouse_motion_event
;
5695 static Lisp_Object last_mouse_motion_frame
;
5698 note_mouse_movement (frame
, event
)
5700 XMotionEvent
*event
;
5702 last_mouse_movement_time
= event
->time
;
5703 last_mouse_motion_event
= *event
;
5704 XSETFRAME (last_mouse_motion_frame
, frame
);
5706 if (event
->window
!= FRAME_X_WINDOW (frame
))
5708 frame
->mouse_moved
= 1;
5709 last_mouse_scroll_bar
= Qnil
;
5710 note_mouse_highlight (frame
, -1, -1);
5713 /* Has the mouse moved off the glyph it was on at the last sighting? */
5714 else if (event
->x
< last_mouse_glyph
.x
5715 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
5716 || event
->y
< last_mouse_glyph
.y
5717 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
5719 frame
->mouse_moved
= 1;
5720 last_mouse_scroll_bar
= Qnil
;
5721 note_mouse_highlight (frame
, event
->x
, event
->y
);
5725 /* This is used for debugging, to turn off note_mouse_highlight. */
5727 int disable_mouse_highlight
;
5731 /************************************************************************
5733 ************************************************************************/
5735 /* Find the glyph under window-relative coordinates X/Y in window W.
5736 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5737 strings. Return in *HPOS and *VPOS the row and column number of
5738 the glyph found. Return in *AREA the glyph area containing X.
5739 Value is a pointer to the glyph found or null if X/Y is not on
5740 text, or we can't tell because W's current matrix is not up to
5743 static struct glyph
*
5744 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
)
5747 int *hpos
, *vpos
, *area
;
5749 struct glyph
*glyph
, *end
;
5750 struct glyph_row
*row
;
5751 int x0
, i
, left_area_width
;
5753 /* Find row containing Y. Give up if some row is not enabled. */
5754 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
5756 row
= MATRIX_ROW (w
->current_matrix
, i
);
5757 if (!row
->enabled_p
)
5759 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
5766 /* Give up if Y is not in the window. */
5767 if (i
== w
->current_matrix
->nrows
)
5770 /* Get the glyph area containing X. */
5771 if (w
->pseudo_window_p
)
5778 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
5779 if (x
< left_area_width
)
5781 *area
= LEFT_MARGIN_AREA
;
5784 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
5787 x0
= row
->x
+ left_area_width
;
5791 *area
= RIGHT_MARGIN_AREA
;
5792 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
5796 /* Find glyph containing X. */
5797 glyph
= row
->glyphs
[*area
];
5798 end
= glyph
+ row
->used
[*area
];
5801 if (x
< x0
+ glyph
->pixel_width
)
5803 if (w
->pseudo_window_p
)
5805 else if (BUFFERP (glyph
->object
))
5809 x0
+= glyph
->pixel_width
;
5816 *hpos
= glyph
- row
->glyphs
[*area
];
5821 /* Convert frame-relative x/y to coordinates relative to window W.
5822 Takes pseudo-windows into account. */
5825 frame_to_window_pixel_xy (w
, x
, y
)
5829 if (w
->pseudo_window_p
)
5831 /* A pseudo-window is always full-width, and starts at the
5832 left edge of the frame, plus a frame border. */
5833 struct frame
*f
= XFRAME (w
->frame
);
5834 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
5835 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
5839 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
5840 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
5845 /* Take proper action when mouse has moved to the mode or top line of
5846 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
5847 mode line. X is relative to the start of the text display area of
5848 W, so the width of bitmap areas and scroll bars must be subtracted
5849 to get a position relative to the start of the mode line. */
5852 note_mode_line_highlight (w
, x
, mode_line_p
)
5856 struct frame
*f
= XFRAME (w
->frame
);
5857 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5858 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
5859 struct glyph_row
*row
;
5862 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
5864 row
= MATRIX_TOP_LINE_ROW (w
->current_matrix
);
5868 struct glyph
*glyph
, *end
;
5869 Lisp_Object help
, map
;
5872 /* Find the glyph under X. */
5873 glyph
= row
->glyphs
[TEXT_AREA
];
5874 end
= glyph
+ row
->used
[TEXT_AREA
];
5875 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
5876 + FRAME_X_FLAGS_AREA_WIDTH (f
));
5878 && x
>= x0
+ glyph
->pixel_width
)
5880 x0
+= glyph
->pixel_width
;
5885 && STRINGP (glyph
->object
)
5886 && XSTRING (glyph
->object
)->intervals
5887 && glyph
->charpos
>= 0
5888 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
5890 /* If we're on a string with `help-echo' text property,
5891 arrange for the help to be displayed. This is done by
5892 setting the global variable help_echo to the help string. */
5893 help
= Fget_text_property (make_number (glyph
->charpos
),
5894 Qhelp_echo
, glyph
->object
);
5898 /* Change the mouse pointer according to what is under X/Y. */
5899 map
= Fget_text_property (make_number (glyph
->charpos
),
5900 Qlocal_map
, glyph
->object
);
5901 if (!NILP (Fkeymapp (map
)))
5902 cursor
= f
->output_data
.x
->nontext_cursor
;
5906 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
5910 /* Take proper action when the mouse has moved to position X, Y on
5911 frame F as regards highlighting characters that have mouse-face
5912 properties. Also de-highlighting chars where the mouse was before.
5913 X and Y can be negative or out of range. */
5916 note_mouse_highlight (f
, x
, y
)
5920 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5925 /* When a menu is active, don't highlight because this looks odd. */
5926 #ifdef USE_X_TOOLKIT
5927 if (popup_activated ())
5931 if (disable_mouse_highlight
)
5934 dpyinfo
->mouse_face_mouse_x
= x
;
5935 dpyinfo
->mouse_face_mouse_y
= y
;
5936 dpyinfo
->mouse_face_mouse_frame
= f
;
5938 if (dpyinfo
->mouse_face_defer
)
5943 dpyinfo
->mouse_face_deferred_gc
= 1;
5947 /* Which window is that in? */
5948 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
5950 /* If we were displaying active text in another window, clear that. */
5951 if (! EQ (window
, dpyinfo
->mouse_face_window
))
5952 clear_mouse_face (dpyinfo
);
5954 /* Not on a window -> return. */
5955 if (!WINDOWP (window
))
5958 /* Convert to window-relative pixel coordinates. */
5959 w
= XWINDOW (window
);
5960 frame_to_window_pixel_xy (w
, &x
, &y
);
5962 /* Handle toolbar window differently since it doesn't display a
5964 if (EQ (window
, f
->toolbar_window
))
5966 note_toolbar_highlight (f
, x
, y
);
5970 if (portion
== 1 || portion
== 3)
5972 /* Mouse is on the mode or top line. */
5973 note_mode_line_highlight (w
, x
, portion
== 1);
5977 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5978 f
->output_data
.x
->text_cursor
);
5980 /* Are we in a window whose display is up to date?
5981 And verify the buffer's text has not changed. */
5982 if (/* Within text portion of the window. */
5984 && EQ (w
->window_end_valid
, w
->buffer
)
5985 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
5986 && (XFASTINT (w
->last_overlay_modified
)
5987 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
5989 int hpos
, vpos
, pos
, i
, area
;
5990 struct glyph
*glyph
;
5992 /* Find the glyph under X/Y. */
5993 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
);
5995 /* Clear mouse face if X/Y not over text. */
5997 || area
!= TEXT_AREA
5998 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6000 clear_mouse_face (dpyinfo
);
6004 pos
= glyph
->charpos
;
6005 xassert (w
->pseudo_window_p
|| BUFFERP (glyph
->object
));
6007 /* Check for mouse-face and help-echo. */
6009 Lisp_Object mouse_face
, overlay
, position
;
6010 Lisp_Object
*overlay_vec
;
6012 struct buffer
*obuf
;
6015 /* If we get an out-of-range value, return now; avoid an error. */
6016 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
6019 /* Make the window's buffer temporarily current for
6020 overlays_at and compute_char_face. */
6021 obuf
= current_buffer
;
6022 current_buffer
= XBUFFER (w
->buffer
);
6028 /* Is this char mouse-active or does it have help-echo? */
6029 XSETINT (position
, pos
);
6031 /* Put all the overlays we want in a vector in overlay_vec.
6032 Store the length in len. If there are more than 10, make
6033 enough space for all, and try again. */
6035 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6036 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6037 if (noverlays
> len
)
6040 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6041 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6044 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
6046 /* Check mouse-face highlighting. */
6047 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
6048 && vpos
>= dpyinfo
->mouse_face_beg_row
6049 && vpos
<= dpyinfo
->mouse_face_end_row
6050 && (vpos
> dpyinfo
->mouse_face_beg_row
6051 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6052 && (vpos
< dpyinfo
->mouse_face_end_row
6053 || hpos
< dpyinfo
->mouse_face_end_col
6054 || dpyinfo
->mouse_face_past_end
)))
6056 /* Clear the display of the old active region, if any. */
6057 clear_mouse_face (dpyinfo
);
6059 /* Find the highest priority overlay that has a mouse-face prop. */
6061 for (i
= 0; i
< noverlays
; i
++)
6063 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
6064 if (!NILP (mouse_face
))
6066 overlay
= overlay_vec
[i
];
6071 /* If no overlay applies, get a text property. */
6073 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
6075 /* Handle the overlay case. */
6076 if (! NILP (overlay
))
6078 /* Find the range of text around this char that
6079 should be active. */
6080 Lisp_Object before
, after
;
6083 before
= Foverlay_start (overlay
);
6084 after
= Foverlay_end (overlay
);
6085 /* Record this as the current active region. */
6086 fast_find_position (w
, XFASTINT (before
),
6087 &dpyinfo
->mouse_face_beg_col
,
6088 &dpyinfo
->mouse_face_beg_row
,
6089 &dpyinfo
->mouse_face_beg_x
,
6090 &dpyinfo
->mouse_face_beg_y
);
6091 dpyinfo
->mouse_face_past_end
6092 = !fast_find_position (w
, XFASTINT (after
),
6093 &dpyinfo
->mouse_face_end_col
,
6094 &dpyinfo
->mouse_face_end_row
,
6095 &dpyinfo
->mouse_face_end_x
,
6096 &dpyinfo
->mouse_face_end_y
);
6097 dpyinfo
->mouse_face_window
= window
;
6098 dpyinfo
->mouse_face_face_id
6099 = face_at_buffer_position (w
, pos
, 0, 0,
6100 &ignore
, pos
+ 1, 1);
6102 /* Display it as active. */
6103 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6105 /* Handle the text property case. */
6106 else if (! NILP (mouse_face
))
6108 /* Find the range of text around this char that
6109 should be active. */
6110 Lisp_Object before
, after
, beginning
, end
;
6113 beginning
= Fmarker_position (w
->start
);
6114 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
6115 - XFASTINT (w
->window_end_pos
)));
6117 = Fprevious_single_property_change (make_number (pos
+ 1),
6119 w
->buffer
, beginning
);
6121 = Fnext_single_property_change (position
, Qmouse_face
,
6123 /* Record this as the current active region. */
6124 fast_find_position (w
, XFASTINT (before
),
6125 &dpyinfo
->mouse_face_beg_col
,
6126 &dpyinfo
->mouse_face_beg_row
,
6127 &dpyinfo
->mouse_face_beg_x
,
6128 &dpyinfo
->mouse_face_beg_y
);
6129 dpyinfo
->mouse_face_past_end
6130 = !fast_find_position (w
, XFASTINT (after
),
6131 &dpyinfo
->mouse_face_end_col
,
6132 &dpyinfo
->mouse_face_end_row
,
6133 &dpyinfo
->mouse_face_end_x
,
6134 &dpyinfo
->mouse_face_end_y
);
6135 dpyinfo
->mouse_face_window
= window
;
6136 dpyinfo
->mouse_face_face_id
6137 = face_at_buffer_position (w
, pos
, 0, 0,
6138 &ignore
, pos
+ 1, 1);
6140 /* Display it as active. */
6141 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6145 /* Look for a `help-echo' property. */
6149 /* Check overlays first. */
6151 for (i
= 0; i
< noverlays
&& !STRINGP (help
); ++i
)
6152 help
= Foverlay_get (overlay_vec
[i
], Qhelp_echo
);
6154 /* Try text properties. */
6156 && ((STRINGP (glyph
->object
)
6157 && glyph
->charpos
>= 0
6158 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6159 || (BUFFERP (glyph
->object
)
6160 && glyph
->charpos
>= BEGV
6161 && glyph
->charpos
< ZV
)))
6162 help
= Fget_text_property (make_number (glyph
->charpos
),
6163 Qhelp_echo
, glyph
->object
);
6171 current_buffer
= obuf
;
6177 redo_mouse_highlight ()
6179 if (!NILP (last_mouse_motion_frame
)
6180 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
6181 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
6182 last_mouse_motion_event
.x
,
6183 last_mouse_motion_event
.y
);
6188 /***********************************************************************
6190 ***********************************************************************/
6192 static int x_toolbar_item
P_ ((struct frame
*, int, int,
6193 struct glyph
**, int *, int *, int *));
6195 /* Toolbar item index of the item on which a mouse button was pressed
6198 static int last_toolbar_item
;
6201 /* Get information about the toolbar item at position X/Y on frame F.
6202 Return in *GLYPH a pointer to the glyph of the toolbar item in
6203 the current matrix of the toolbar window of F, or NULL if not
6204 on a toolbar item. Return in *PROP_IDX the index of the toolbar
6205 item in F->current_toolbar_items. Value is
6207 -1 if X/Y is not on a toolbar item
6208 0 if X/Y is on the same item that was highlighted before.
6212 x_toolbar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
6215 struct glyph
**glyph
;
6216 int *hpos
, *vpos
, *prop_idx
;
6218 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6219 struct window
*w
= XWINDOW (f
->toolbar_window
);
6222 /* Find the glyph under X/Y. */
6223 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
);
6227 /* Get the start of this toolbar item's properties in
6228 f->current_toolbar_items. */
6229 if (!toolbar_item_info (f
, *glyph
, prop_idx
))
6232 /* Is mouse on the highlighted item? */
6233 if (EQ (f
->toolbar_window
, dpyinfo
->mouse_face_window
)
6234 && *vpos
>= dpyinfo
->mouse_face_beg_row
6235 && *vpos
<= dpyinfo
->mouse_face_end_row
6236 && (*vpos
> dpyinfo
->mouse_face_beg_row
6237 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
6238 && (*vpos
< dpyinfo
->mouse_face_end_row
6239 || *hpos
< dpyinfo
->mouse_face_end_col
6240 || dpyinfo
->mouse_face_past_end
))
6247 /* Handle mouse button event on the toolbar of frame F, at
6248 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6252 x_handle_toolbar_click (f
, button_event
)
6254 XButtonEvent
*button_event
;
6256 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6257 struct window
*w
= XWINDOW (f
->toolbar_window
);
6258 int hpos
, vpos
, prop_idx
;
6259 struct glyph
*glyph
;
6260 Lisp_Object enabled_p
;
6261 int x
= button_event
->x
;
6262 int y
= button_event
->y
;
6264 /* If not on the highlighted toolbar item, return. */
6265 frame_to_window_pixel_xy (w
, &x
, &y
);
6266 if (x_toolbar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
6269 /* If item is disabled, do nothing. */
6270 enabled_p
= (XVECTOR (f
->current_toolbar_items
)
6271 ->contents
[prop_idx
+ TOOLBAR_ITEM_ENABLED_P
]);
6272 if (NILP (enabled_p
))
6275 if (button_event
->type
== ButtonPress
)
6277 /* Show item in pressed state. */
6278 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
6279 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
6280 last_toolbar_item
= prop_idx
;
6284 Lisp_Object key
, frame
;
6285 struct input_event event
;
6287 /* Show item in released state. */
6288 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
6289 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
6291 key
= (XVECTOR (f
->current_toolbar_items
)
6292 ->contents
[prop_idx
+ TOOLBAR_ITEM_KEY
]);
6294 XSETFRAME (frame
, f
);
6295 event
.kind
= TOOLBAR_EVENT
;
6296 event
.frame_or_window
= Fcons (frame
, Fcons (Qtoolbar
, Qnil
));
6297 kbd_buffer_store_event (&event
);
6299 event
.kind
= TOOLBAR_EVENT
;
6300 event
.frame_or_window
= Fcons (frame
, key
);
6301 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6302 button_event
->state
);
6303 kbd_buffer_store_event (&event
);
6304 last_toolbar_item
= -1;
6309 /* Possibly highlight a toolbar item on frame F when mouse moves to
6310 toolbar window-relative coordinates X/Y. Called from
6311 note_mouse_highlight. */
6314 note_toolbar_highlight (f
, x
, y
)
6318 Lisp_Object window
= f
->toolbar_window
;
6319 struct window
*w
= XWINDOW (window
);
6320 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6322 struct glyph
*glyph
;
6323 struct glyph_row
*row
;
6325 Lisp_Object enabled_p
;
6327 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
6328 int on_highlight_p
, mouse_down_p
, rc
;
6330 /* Function note_mouse_highlight is called with negative x(y
6331 values when mouse moves outside of the frame. */
6332 if (x
<= 0 || y
<= 0)
6334 clear_mouse_face (dpyinfo
);
6338 rc
= x_toolbar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
6341 /* Not on toolbar item. */
6342 clear_mouse_face (dpyinfo
);
6346 /* On same toolbar item as before. */
6349 clear_mouse_face (dpyinfo
);
6351 /* Mouse is down, but on different toolbar item? */
6352 mouse_down_p
= (dpyinfo
->grabbed
6353 && f
== last_mouse_frame
6354 && FRAME_LIVE_P (f
));
6356 && last_toolbar_item
!= prop_idx
)
6359 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
6360 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
6362 /* If toolbar item is not enabled, don't highlight it. */
6363 enabled_p
= (XVECTOR (f
->current_toolbar_items
)
6364 ->contents
[prop_idx
+ TOOLBAR_ITEM_ENABLED_P
]);
6365 if (!NILP (enabled_p
))
6367 /* Compute the x-position of the glyph. In front and past the
6368 image is a space. We include this is the highlighted area. */
6369 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6370 for (i
= x
= 0; i
< hpos
; ++i
)
6371 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
6373 /* Record this as the current active region. */
6374 dpyinfo
->mouse_face_beg_col
= hpos
;
6375 dpyinfo
->mouse_face_beg_row
= vpos
;
6376 dpyinfo
->mouse_face_beg_x
= x
;
6377 dpyinfo
->mouse_face_beg_y
= row
->y
;
6378 dpyinfo
->mouse_face_past_end
= 0;
6380 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
6381 dpyinfo
->mouse_face_end_row
= vpos
;
6382 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
6383 dpyinfo
->mouse_face_end_y
= row
->y
;
6384 dpyinfo
->mouse_face_window
= window
;
6385 dpyinfo
->mouse_face_face_id
= TOOLBAR_FACE_ID
;
6387 /* Display it as active. */
6388 show_mouse_face (dpyinfo
, draw
);
6389 dpyinfo
->mouse_face_image_state
= draw
;
6394 /* Set help_echo to a help string.to display for this toolbar item.
6395 XTread_socket does the rest. */
6396 help_echo
= (XVECTOR (f
->current_toolbar_items
)
6397 ->contents
[prop_idx
+ TOOLBAR_ITEM_HELP
]);
6398 if (!STRINGP (help_echo
))
6399 help_echo
= (XVECTOR (f
->current_toolbar_items
)
6400 ->contents
[prop_idx
+ TOOLBAR_ITEM_CAPTION
]);
6405 /* Find the glyph matrix position of buffer position POS in window W.
6406 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6407 current glyphs must be up to date. If POS is above window start
6408 return (0, 0, 0, 0). If POS is after end of W, return end of
6412 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
)
6415 int *hpos
, *vpos
, *x
, *y
;
6419 int maybe_next_line_p
= 0;
6420 int line_start_position
;
6421 int yb
= window_text_bottom_y (w
);
6422 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0);
6423 struct glyph_row
*best_row
= row
;
6424 int row_vpos
= 0, best_row_vpos
= 0;
6429 if (row
->used
[TEXT_AREA
])
6430 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
6432 line_start_position
= 0;
6434 if (line_start_position
> pos
)
6436 /* If the position sought is the end of the buffer,
6437 don't include the blank lines at the bottom of the window. */
6438 else if (line_start_position
== pos
6439 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
6441 maybe_next_line_p
= 1;
6444 else if (line_start_position
> 0)
6447 best_row_vpos
= row_vpos
;
6454 /* Find the right column within BEST_ROW. */
6456 current_x
= best_row
->x
;
6457 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
6459 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
6462 charpos
= glyph
->charpos
;
6466 *vpos
= best_row_vpos
;
6471 else if (charpos
> pos
)
6473 else if (charpos
> 0)
6476 current_x
+= glyph
->pixel_width
;
6479 /* If we're looking for the end of the buffer,
6480 and we didn't find it in the line we scanned,
6481 use the start of the following line. */
6482 if (maybe_next_line_p
)
6487 current_x
= best_row
->x
;
6490 *vpos
= best_row_vpos
;
6491 *hpos
= lastcol
+ 1;
6498 /* Display the active region described by mouse_face_*
6499 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6502 show_mouse_face (dpyinfo
, draw
)
6503 struct x_display_info
*dpyinfo
;
6504 enum draw_glyphs_face draw
;
6506 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
6507 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6509 int cursor_off_p
= 0;
6510 struct cursor_pos saved_cursor
;
6512 saved_cursor
= output_cursor
;
6514 /* If window is in the process of being destroyed, don't bother
6516 if (w
->current_matrix
== NULL
)
6519 /* Recognize when we are called to operate on rows that don't exist
6520 anymore. This can happen when a window is split. */
6521 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
6524 set_output_cursor (&w
->phys_cursor
);
6526 /* Note that mouse_face_beg_row etc. are window relative. */
6527 for (i
= dpyinfo
->mouse_face_beg_row
;
6528 i
<= dpyinfo
->mouse_face_end_row
;
6531 int start_hpos
, end_hpos
, start_x
;
6532 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
6534 /* Don't do anything if row doesn't have valid contents. */
6535 if (!row
->enabled_p
)
6538 /* For all but the first row, the highlight starts at column 0. */
6539 if (i
== dpyinfo
->mouse_face_beg_row
)
6541 start_hpos
= dpyinfo
->mouse_face_beg_col
;
6542 start_x
= dpyinfo
->mouse_face_beg_x
;
6550 if (i
== dpyinfo
->mouse_face_end_row
)
6551 end_hpos
= dpyinfo
->mouse_face_end_col
;
6553 end_hpos
= row
->used
[TEXT_AREA
];
6555 /* If the cursor's in the text we are about to rewrite, turn the
6557 if (!w
->pseudo_window_p
6558 && i
== output_cursor
.vpos
6559 && output_cursor
.hpos
>= start_hpos
- 1
6560 && output_cursor
.hpos
<= end_hpos
)
6562 x_update_window_cursor (w
, 0);
6566 if (end_hpos
> start_hpos
)
6567 x_draw_glyphs (w
, start_x
, row
, updated_area
,
6568 start_hpos
, end_hpos
, draw
, NULL
, NULL
);
6571 /* If we turned the cursor off, turn it back on. */
6573 x_display_cursor (w
, 1,
6574 output_cursor
.hpos
, output_cursor
.vpos
,
6575 output_cursor
.x
, output_cursor
.y
);
6577 output_cursor
= saved_cursor
;
6581 /* Change the mouse cursor. */
6582 if (draw
== DRAW_NORMAL_TEXT
)
6583 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6584 f
->output_data
.x
->text_cursor
);
6585 else if (draw
== DRAW_MOUSE_FACE
)
6586 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6587 f
->output_data
.x
->cross_cursor
);
6589 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6590 f
->output_data
.x
->nontext_cursor
);
6593 /* Clear out the mouse-highlighted active region.
6594 Redraw it un-highlighted first. */
6597 clear_mouse_face (dpyinfo
)
6598 struct x_display_info
*dpyinfo
;
6603 if (! NILP (dpyinfo
->mouse_face_window
))
6604 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
6606 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6607 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6608 dpyinfo
->mouse_face_window
= Qnil
;
6611 /* Just discard the mouse face information for frame F, if any.
6612 This is used when the size of F is changed. */
6615 cancel_mouse_face (f
)
6619 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6621 window
= dpyinfo
->mouse_face_window
;
6622 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
6624 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6625 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6626 dpyinfo
->mouse_face_window
= Qnil
;
6630 static struct scroll_bar
*x_window_to_scroll_bar ();
6631 static void x_scroll_bar_report_motion ();
6633 /* Return the current position of the mouse.
6634 *fp should be a frame which indicates which display to ask about.
6636 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6637 and *part to the frame, window, and scroll bar part that the mouse
6638 is over. Set *x and *y to the portion and whole of the mouse's
6639 position on the scroll bar.
6641 If the mouse movement started elsewhere, set *fp to the frame the
6642 mouse is on, *bar_window to nil, and *x and *y to the character cell
6645 Set *time to the server time-stamp for the time at which the mouse
6646 was at this position.
6648 Don't store anything if we don't have a valid set of values to report.
6650 This clears the mouse_moved flag, so we can wait for the next mouse
6654 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
6657 Lisp_Object
*bar_window
;
6658 enum scroll_bar_part
*part
;
6660 unsigned long *time
;
6666 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
6667 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
6673 Window dummy_window
;
6676 Lisp_Object frame
, tail
;
6678 /* Clear the mouse-moved flag for every frame on this display. */
6679 FOR_EACH_FRAME (tail
, frame
)
6680 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
6681 XFRAME (frame
)->mouse_moved
= 0;
6683 last_mouse_scroll_bar
= Qnil
;
6685 /* Figure out which root window we're on. */
6686 XQueryPointer (FRAME_X_DISPLAY (*fp
),
6687 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
6689 /* The root window which contains the pointer. */
6692 /* Trash which we can't trust if the pointer is on
6693 a different screen. */
6696 /* The position on that root window. */
6699 /* More trash we can't trust. */
6702 /* Modifier keys and pointer buttons, about which
6704 (unsigned int *) &dummy
);
6706 /* Now we have a position on the root; find the innermost window
6707 containing the pointer. */
6711 int parent_x
= 0, parent_y
= 0;
6716 /* XTranslateCoordinates can get errors if the window
6717 structure is changing at the same time this function
6718 is running. So at least we must not crash from them. */
6720 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
6722 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
6723 && FRAME_LIVE_P (last_mouse_frame
))
6725 /* If mouse was grabbed on a frame, give coords for that frame
6726 even if the mouse is now outside it. */
6727 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
6729 /* From-window, to-window. */
6730 root
, FRAME_X_WINDOW (last_mouse_frame
),
6732 /* From-position, to-position. */
6733 root_x
, root_y
, &win_x
, &win_y
,
6737 f1
= last_mouse_frame
;
6743 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
6745 /* From-window, to-window. */
6748 /* From-position, to-position. */
6749 root_x
, root_y
, &win_x
, &win_y
,
6754 if (child
== None
|| child
== win
)
6762 /* Now we know that:
6763 win is the innermost window containing the pointer
6764 (XTC says it has no child containing the pointer),
6765 win_x and win_y are the pointer's position in it
6766 (XTC did this the last time through), and
6767 parent_x and parent_y are the pointer's position in win's parent.
6768 (They are what win_x and win_y were when win was child.
6769 If win is the root window, it has no parent, and
6770 parent_{x,y} are invalid, but that's okay, because we'll
6771 never use them in that case.) */
6773 /* Is win one of our frames? */
6774 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
6777 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
6780 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
6782 /* If not, is it one of our scroll bars? */
6785 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
6789 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6795 if (f1
== 0 && insist
> 0)
6796 f1
= selected_frame
;
6800 /* Ok, we found a frame. Store all the values.
6801 last_mouse_glyph is a rectangle used to reduce the
6802 generation of mouse events. To not miss any motion
6803 events, we must divide the frame into rectangles of the
6804 size of the smallest character that could be displayed
6805 on it, i.e. into the same rectangles that matrices on
6806 the frame are divided into. */
6808 #if OLD_REDISPLAY_CODE
6809 int ignore1
, ignore2
;
6810 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
6812 FRAME_X_DISPLAY_INFO (f1
)->grabbed
6816 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
6817 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
6821 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6822 round down even for negative values. */
6828 last_mouse_glyph
.width
= width
;
6829 last_mouse_glyph
.height
= height
;
6830 last_mouse_glyph
.x
= (x
+ width
- 1) / width
* width
;
6831 last_mouse_glyph
.y
= (y
+ height
- 1) / height
* height
;
6838 XSETINT (*x
, win_x
);
6839 XSETINT (*y
, win_y
);
6840 *time
= last_mouse_movement_time
;
6849 DEFUN ("xt-process-timeouts", Fxt_process_timeouts
, Sxt_process_timeouts
,
6851 "Arrange for Xt timeout callbacks to be called.")
6854 #ifdef USE_X_TOOLKIT
6856 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
6857 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
6859 #endif /* USE_X_TOOLKIT */
6866 /* Scroll bar support. */
6868 /* Given an X window ID, find the struct scroll_bar which manages it.
6869 This can be called in GC, so we have to make sure to strip off mark
6871 static struct scroll_bar
*
6872 x_window_to_scroll_bar (window_id
)
6877 for (tail
= Vframe_list
;
6878 XGCTYPE (tail
) == Lisp_Cons
;
6879 tail
= XCONS (tail
)->cdr
)
6881 Lisp_Object frame
, bar
, condemned
;
6883 frame
= XCONS (tail
)->car
;
6884 /* All elements of Vframe_list should be frames. */
6885 if (! GC_FRAMEP (frame
))
6888 /* Scan this frame's scroll bar list for a scroll bar with the
6890 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
6891 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
6892 /* This trick allows us to search both the ordinary and
6893 condemned scroll bar lists with one loop. */
6894 ! GC_NILP (bar
) || (bar
= condemned
,
6897 bar
= XSCROLL_BAR (bar
)->next
)
6898 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
6899 return XSCROLL_BAR (bar
);
6907 /************************************************************************
6909 ************************************************************************/
6911 #if USE_TOOLKIT_SCROLL_BARS
6913 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
6914 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
6915 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
6916 struct scroll_bar
*));
6917 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
6921 /* Id of action hook installed for scroll bars. */
6923 static XtActionHookId action_hook_id
;
6925 /* Lisp window being scrolled. Set when starting to interact with
6926 a toolkit scroll bar, reset to nil when ending the interaction. */
6928 static Lisp_Object window_being_scrolled
;
6930 /* Last scroll bar part sent in xm_scroll_callback. */
6932 static int last_scroll_bar_part
;
6935 /* Action hook installed via XtAppAddActionHook when toolkit scroll
6936 bars are used.. The hoos is responsible for detecting when
6937 the user ends an interaction with the scroll bar, and generates
6938 a `end-scroll' scroll_bar_click' event if so. */
6941 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
6944 XtPointer client_data
;
6948 Cardinal
*num_params
;
6954 scroll_bar_p
= XmIsScrollBar (widget
);
6955 end_action
= "Release";
6956 #elif defined HAVE_XAW3D
6957 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
6958 end_action
= "EndScroll";
6960 #error unknown scroll bar toolkit
6961 #endif /* HAVE_XAW3D */
6963 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
6964 let Xt timeouts be processed doesn't work. */
6966 && strcmp (action_name
, end_action
) == 0
6967 && WINDOWP (window_being_scrolled
))
6971 x_send_scroll_bar_event (window_being_scrolled
,
6972 scroll_bar_end_scroll
, 0, 0);
6973 w
= XWINDOW (window_being_scrolled
);
6974 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
6975 window_being_scrolled
= Qnil
;
6976 last_scroll_bar_part
= -1;
6981 /* Send a client message with message type Xatom_Scrollbar for a
6982 scroll action to the frame of WINDOW. PART is a value identifying
6983 the part of the scroll bar that was clicked on. PORTION is the
6984 amount to scroll of a whole of WHOLE. */
6987 x_send_scroll_bar_event (window
, part
, portion
, whole
)
6989 int part
, portion
, whole
;
6992 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
6993 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
6995 /* Construct a ClientMessage event to send to the frame. */
6996 ev
->type
= ClientMessage
;
6997 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
6998 ev
->display
= FRAME_X_DISPLAY (f
);
6999 ev
->window
= FRAME_X_WINDOW (f
);
7001 ev
->data
.l
[0] = (long) window
;
7002 ev
->data
.l
[1] = (long) part
;
7003 ev
->data
.l
[2] = (long) 0;
7004 ev
->data
.l
[3] = (long) portion
;
7005 ev
->data
.l
[4] = (long) whole
;
7007 /* Setting the event mask to zero means that the message will
7008 be sent to the client that created the window, and if that
7009 window no longer exists, no event will be sent. */
7011 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
7016 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7020 x_scroll_bar_to_input_event (event
, ievent
)
7022 struct input_event
*ievent
;
7024 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
7025 Lisp_Object window
= (Lisp_Object
) ev
->data
.l
[0];
7026 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7028 ievent
->kind
= scroll_bar_click
;
7029 ievent
->frame_or_window
= window
;
7030 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
7031 ievent
->part
= ev
->data
.l
[1];
7032 ievent
->code
= ev
->data
.l
[2];
7033 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
7034 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
7035 ievent
->modifiers
= 0;
7041 /* Minimum and maximum values used for Motif scroll bars. */
7044 #define XM_SB_MAX 10000000
7045 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7048 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7049 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7050 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7053 xm_scroll_callback (widget
, client_data
, call_data
)
7055 XtPointer client_data
, call_data
;
7057 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7058 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
7060 int part
= -1, whole
= 0, portion
= 0;
7064 case XmCR_DECREMENT
:
7065 bar
->dragging
= Qnil
;
7066 part
= scroll_bar_up_arrow
;
7069 case XmCR_INCREMENT
:
7070 bar
->dragging
= Qnil
;
7071 part
= scroll_bar_down_arrow
;
7074 case XmCR_PAGE_DECREMENT
:
7075 bar
->dragging
= Qnil
;
7076 part
= scroll_bar_above_handle
;
7079 case XmCR_PAGE_INCREMENT
:
7080 bar
->dragging
= Qnil
;
7081 part
= scroll_bar_below_handle
;
7085 bar
->dragging
= Qnil
;
7086 part
= scroll_bar_to_top
;
7089 case XmCR_TO_BOTTOM
:
7090 bar
->dragging
= Qnil
;
7091 part
= scroll_bar_to_bottom
;
7097 int dragging_down_p
= (INTEGERP (bar
->dragging
)
7098 && XINT (bar
->dragging
) <= cs
->value
);
7100 /* Get the slider size. */
7102 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
7105 /* At the max position of the scroll bar, do a line-wise
7106 movement. Without doing anything, the LessTif scroll bar
7107 calls us with the same cs->value again and again. If we
7108 want to make sure that we can reach the end of the buffer,
7109 we have to do something.
7111 Implementation note: setting bar->dragging always to
7112 cs->value gives a smoother movement at the max position.
7113 Setting it to nil when doing line-wise movement gives
7114 a better slider behavior. */
7116 if (cs
->value
+ slider_size
== XM_SB_MAX
7118 && last_scroll_bar_part
== scroll_bar_down_arrow
))
7120 part
= scroll_bar_down_arrow
;
7121 bar
->dragging
= Qnil
;
7125 whole
= XM_SB_RANGE
;
7126 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
7127 part
= scroll_bar_handle
;
7128 bar
->dragging
= make_number (cs
->value
);
7133 case XmCR_VALUE_CHANGED
:
7139 window_being_scrolled
= bar
->window
;
7140 last_scroll_bar_part
= part
;
7141 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7146 #else /* not USE_MOTIF, i.e. XAW3D. */
7149 /* Xaw3d scroll bar callback. Invoked when the thumb is dragged.
7150 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7151 scroll bar struct. CALL_DATA is a pointer to a float saying where
7155 xaw3d_jump_callback (widget
, client_data
, call_data
)
7157 XtPointer client_data
, call_data
;
7159 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7160 float top
= *(float *) call_data
;
7163 int dragging_down_p
, part
;
7164 double epsilon
= 0.01;
7166 /* Get the size of the thumb, a value between 0 and 1. */
7168 XtVaGetValues (widget
, XtNshown
, &shown
, NULL
);
7172 portion
= shown
< 1 ? top
* whole
: 0;
7173 dragging_down_p
= (INTEGERP (bar
->dragging
)
7174 && XINT (bar
->dragging
) < portion
);
7177 && (abs (top
+ shown
- 1) < epsilon
7179 && last_scroll_bar_part
== scroll_bar_down_arrow
)))
7180 part
= scroll_bar_down_arrow
;
7182 part
= scroll_bar_handle
;
7184 window_being_scrolled
= bar
->window
;
7185 bar
->dragging
= make_number (portion
);
7186 last_scroll_bar_part
= part
;
7187 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7191 /* Xaw3d scroll bar callback. Invoked for incremental scrolling.,
7192 i.e. line or page up or down. WIDGET is the Xaw3d scroll bar
7193 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7194 the scroll bar. CALL_DATA is an integer specifying the action that
7195 has taken place. It's magnitude is in the range 0..height of the
7196 scroll bar. Negative values mean scroll towards buffer start.
7197 Values < height of scroll bar mean line-wise movement. */
7200 xaw3d_scroll_callback (widget
, client_data
, call_data
)
7202 XtPointer client_data
, call_data
;
7204 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7205 int position
= (int) call_data
;
7209 /* Get the height of the scroll bar. */
7211 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
7216 if (abs (position
) < height
)
7217 part
= scroll_bar_up_arrow
;
7219 part
= scroll_bar_above_handle
;
7223 if (abs (position
) < height
)
7224 part
= scroll_bar_down_arrow
;
7226 part
= scroll_bar_below_handle
;
7229 window_being_scrolled
= bar
->window
;
7230 bar
->dragging
= Qnil
;
7231 last_scroll_bar_part
= part
;
7232 x_send_scroll_bar_event (bar
->window
, part
, 0, 0);
7236 #endif /* not USE_MOTIF */
7239 /* Create the widget for scroll bar BAR on frame F. Record the widget
7240 and X window of the scroll bar in BAR. */
7243 x_create_toolkit_scroll_bar (f
, bar
)
7245 struct scroll_bar
*bar
;
7251 char *scroll_bar_name
= "verticalScrollBar";
7252 unsigned long pixel
;
7257 /* LessTif 0.85, problems:
7259 1. When the mouse if over the scroll bar, the scroll bar will
7260 get keyboard events. I didn't find a way to turn this off.
7262 2. Do we have to explicitly set the cursor to get an arrow
7263 cursor (see below)? */
7265 /* Set resources. Create the widget. */
7266 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7267 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
7268 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
7269 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
7270 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
7271 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
7272 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
7274 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7277 XtSetArg (av
[ac
], XmNforeground
, pixel
);
7281 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7284 XtSetArg (av
[ac
], XmNbackground
, pixel
);
7288 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
7289 scroll_bar_name
, av
, ac
);
7291 /* Add one callback for everything that can happen. */
7292 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
7294 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
7296 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
7298 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
7300 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
7302 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
7304 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
7307 /* Realize the widget. Only after that is the X window created. */
7308 XtRealizeWidget (widget
);
7310 /* Set the cursor to an arrow. I didn't find a resource to do that.
7311 And I'm wondering why it hasn't an arrow cursor by default. */
7312 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
7313 f
->output_data
.x
->nontext_cursor
);
7315 #elif defined HAVE_XAW3D
7317 /* Set resources. Create the widget. The background of the
7318 Xaw3d scroll bar widget is a little bit light for my taste.
7319 We don't alter it here to let users change it according
7320 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7321 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7322 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
7323 XtSetArg (av
[ac
], XtNcursorName
, "left_ptr"); ++ac
;
7324 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
); ++ac
;
7326 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7329 XtSetArg (av
[ac
], XtNforeground
, pixel
);
7333 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7336 XtSetArg (av
[ac
], XtNbackground
, pixel
);
7340 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
7341 f
->output_data
.x
->edit_widget
, av
, ac
);
7343 /* Define callbacks. */
7344 XtAddCallback (widget
, XtNjumpProc
, xaw3d_jump_callback
, (XtPointer
) bar
);
7345 XtAddCallback (widget
, XtNscrollProc
, xaw3d_scroll_callback
,
7348 /* Realize the widget. Only after that is the X window created. */
7349 XtRealizeWidget (widget
);
7351 #endif /* HAVE_XAW3D */
7353 /* Install an action hook that let's us detect when the user
7354 finishes interacting with a scroll bar. */
7355 if (action_hook_id
== 0)
7356 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
7358 /* Remember X window and widget in the scroll bar vector. */
7359 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
7360 xwindow
= XtWindow (widget
);
7361 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
7367 /* Set the thumb size and position of scroll bar BAR. We are currently
7368 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7371 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
7372 struct scroll_bar
*bar
;
7373 int portion
, position
, whole
;
7377 Widget widget
= SCROLL_BAR_X_WIDGET (bar
);
7383 top
= (float) position
/ whole
;
7384 shown
= (float) portion
/ whole
;
7392 Boolean arrow1_selected
, arrow2_selected
;
7393 unsigned char flags
;
7394 XmScrollBarWidget sb
;
7396 /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX
7397 is the scroll bar's maximum and MIN is the scroll bar's minimum
7399 size
= shown
* XM_SB_RANGE
;
7400 size
= min (size
, XM_SB_RANGE
);
7401 size
= max (size
, 1);
7403 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7404 value
= top
* XM_SB_RANGE
;
7405 value
= min (value
, XM_SB_MAX
- size
);
7406 value
= max (value
, XM_SB_MIN
);
7408 /* LessTif: Calling XmScrollBarSetValues after an increment or
7409 decrement turns off auto-repeat LessTif-internally. This can
7410 be seen in ScrollBar.c which resets Arrow1Selected and
7411 Arrow2Selected. It also sets internal flags so that LessTif
7412 believes the mouse is in the slider. We either have to change
7413 our code, or work around that by accessing private data. */
7415 sb
= (XmScrollBarWidget
) widget
;
7416 arrow1_selected
= sb
->scrollBar
.arrow1_selected
;
7417 arrow2_selected
= sb
->scrollBar
.arrow2_selected
;
7418 flags
= sb
->scrollBar
.flags
;
7420 if (NILP (bar
->dragging
))
7421 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
7422 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7423 /* This has the negative side effect that the slider value is
7424 not would it would be if we scrolled here using line-wise or
7425 page-wise movement. */
7426 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
7429 /* If currently dragging, only update the slider size.
7430 This reduces flicker effects. */
7431 int old_value
, old_size
, increment
, page_increment
;
7433 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
7434 &increment
, &page_increment
);
7435 XmScrollBarSetValues (widget
, old_value
,
7436 min (size
, XM_SB_RANGE
- old_value
),
7440 sb
->scrollBar
.arrow1_selected
= arrow1_selected
;
7441 sb
->scrollBar
.arrow2_selected
= arrow2_selected
;
7442 sb
->scrollBar
.flags
= flags
;
7444 #elif defined HAVE_XAW3D
7446 /* Restrict to [0 1]. */
7447 top
= max (0, min (1, top
));
7448 shown
= max (0, min (1, shown
));
7450 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7451 check that your system's configuration file contains a define
7452 for `NARROWPROTO'. See s/freebsd.h for an example. */
7453 if (NILP (bar
->dragging
))
7454 XawScrollbarSetThumb (widget
, top
, shown
);
7457 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
7458 int scroll_mode
= sb
->scrollbar
.scroll_mode
;
7460 sb
->scrollbar
.scroll_mode
= 0;
7462 if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7463 XawScrollbarSetThumb (widget
, top
, 1 - top
);
7467 XtVaGetValues (widget
, XtNtopOfThumb
, &old_top
, NULL
);
7468 XawScrollbarSetThumb (widget
, old_top
, min (shown
, 1 - old_top
));
7471 sb
->scrollbar
.scroll_mode
= scroll_mode
;
7474 #endif /* HAVE_XAW3D */
7479 #endif /* USE_TOOLKIT_SCROLL_BARS */
7483 /************************************************************************
7484 Scroll bars, general
7485 ************************************************************************/
7487 /* Create a scroll bar and return the scroll bar vector for it. W is
7488 the Emacs window on which to create the scroll bar. TOP, LEFT,
7489 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7492 static struct scroll_bar
*
7493 x_scroll_bar_create (w
, top
, left
, width
, height
)
7495 int top
, left
, width
, height
;
7497 struct frame
*f
= XFRAME (w
->frame
);
7498 #ifdef USE_X_TOOLKIT
7503 struct scroll_bar
*bar
7504 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
7508 #if USE_TOOLKIT_SCROLL_BARS
7509 x_create_toolkit_scroll_bar (f
, bar
);
7510 #else /* not USE_TOOLKIT_SCROLL_BARS */
7512 XSetWindowAttributes a
;
7515 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7516 if (a
.background_pixel
== -1)
7517 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
7519 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
7520 | ButtonMotionMask
| PointerMotionHintMask
7522 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
7524 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
7526 /* Clear the area of W that will serve as a scroll bar. This is
7527 for the case that a window has been split horizontally. In
7528 this case, no clear_frame is generated to reduce flickering. */
7529 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7531 window_box_height (w
), False
);
7533 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7534 /* Position and size of scroll bar. */
7535 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7537 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7539 /* Border width, depth, class, and visual. */
7546 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
7548 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7550 XSETWINDOW (bar
->window
, w
);
7551 XSETINT (bar
->top
, top
);
7552 XSETINT (bar
->left
, left
);
7553 XSETINT (bar
->width
, width
);
7554 XSETINT (bar
->height
, height
);
7555 XSETINT (bar
->start
, 0);
7556 XSETINT (bar
->end
, 0);
7557 bar
->dragging
= Qnil
;
7559 /* Add bar to its frame's list of scroll bars. */
7560 bar
->next
= FRAME_SCROLL_BARS (f
);
7562 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
7563 if (!NILP (bar
->next
))
7564 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
7566 /* Map the window/widget. */
7567 #if USE_TOOLKIT_SCROLL_BARS
7568 XtMapWidget (SCROLL_BAR_X_WIDGET (bar
));
7569 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
7570 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7572 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7574 #else /* not USE_TOOLKIT_SCROLL_BARS */
7575 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
7576 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7583 /* Draw BAR's handle in the proper position.
7585 If the handle is already drawn from START to END, don't bother
7586 redrawing it, unless REBUILD is non-zero; in that case, always
7587 redraw it. (REBUILD is handy for drawing the handle after expose
7590 Normally, we want to constrain the start and end of the handle to
7591 fit inside its rectangle, but if the user is dragging the scroll
7592 bar handle, we want to let them drag it down all the way, so that
7593 the bar's top is as far down as it goes; otherwise, there's no way
7594 to move to the very end of the buffer. */
7597 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
7598 struct scroll_bar
*bar
;
7602 #ifndef USE_TOOLKIT_SCROLL_BARS
7603 int dragging
= ! NILP (bar
->dragging
);
7604 Window w
= SCROLL_BAR_X_WINDOW (bar
);
7605 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7606 GC gc
= f
->output_data
.x
->normal_gc
;
7608 /* If the display is already accurate, do nothing. */
7610 && start
== XINT (bar
->start
)
7611 && end
== XINT (bar
->end
))
7617 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
7618 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
7619 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
7621 /* Make sure the values are reasonable, and try to preserve
7622 the distance between start and end. */
7624 int length
= end
- start
;
7628 else if (start
> top_range
)
7630 end
= start
+ length
;
7634 else if (end
> top_range
&& ! dragging
)
7638 /* Store the adjusted setting in the scroll bar. */
7639 XSETINT (bar
->start
, start
);
7640 XSETINT (bar
->end
, end
);
7642 /* Clip the end position, just for display. */
7643 if (end
> top_range
)
7646 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
7647 below top positions, to make sure the handle is always at least
7648 that many pixels tall. */
7649 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
7651 /* Draw the empty space above the handle. Note that we can't clear
7652 zero-height areas; that means "clear to end of window." */
7654 XClearArea (FRAME_X_DISPLAY (f
), w
,
7656 /* x, y, width, height, and exposures. */
7657 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
7658 VERTICAL_SCROLL_BAR_TOP_BORDER
,
7659 inside_width
, start
,
7662 /* Change to proper foreground color if one is specified. */
7663 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
7664 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
7665 f
->output_data
.x
->scroll_bar_foreground_pixel
);
7667 /* Draw the handle itself. */
7668 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
7670 /* x, y, width, height */
7671 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
7672 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
7673 inside_width
, end
- start
);
7675 /* Restore the foreground color of the GC if we changed it above. */
7676 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
7677 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
7678 f
->output_data
.x
->foreground_pixel
);
7680 /* Draw the empty space below the handle. Note that we can't
7681 clear zero-height areas; that means "clear to end of window." */
7682 if (end
< inside_height
)
7683 XClearArea (FRAME_X_DISPLAY (f
), w
,
7685 /* x, y, width, height, and exposures. */
7686 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
7687 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
7688 inside_width
, inside_height
- end
,
7694 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7698 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7702 x_scroll_bar_remove (bar
)
7703 struct scroll_bar
*bar
;
7705 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7709 #if USE_TOOLKIT_SCROLL_BARS
7710 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar
));
7711 #else /* not USE_TOOLKIT_SCROLL_BARS */
7712 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
7713 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7715 /* Disassociate this scroll bar from its window. */
7716 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
7722 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7723 that we are displaying PORTION characters out of a total of WHOLE
7724 characters, starting at POSITION. If WINDOW has no scroll bar,
7728 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
7730 int portion
, whole
, position
;
7732 struct frame
*f
= XFRAME (w
->frame
);
7733 struct scroll_bar
*bar
;
7734 int pixel_top
, pixel_left
, pixel_width
, pixel_height
;
7735 int window_x
, window_y
, window_width
, window_height
;
7736 int scroll_bar_area_width
;
7738 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
7740 /* Where should this scroll bar be, pixel-wise? */
7741 pixel_top
= window_y
;
7742 pixel_height
= window_height
;
7744 /* The width of the scroll bar itself. */
7745 pixel_width
= (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
7746 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
7747 : (FRAME_SCROLL_BAR_COLS (f
)
7748 * FONT_WIDTH (FRAME_FONT (f
))));
7750 /* The width on the screen reserved for the scroll bar plus maybe
7751 some empty room at both sides of the scroll bar. */
7752 scroll_bar_area_width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
7754 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
7755 pixel_left
= (window_x
7757 + FRAME_FLAGS_AREA_WIDTH (f
)
7758 + scroll_bar_area_width
7761 pixel_left
= (window_x
7762 - FRAME_FLAGS_AREA_WIDTH (f
)
7763 - scroll_bar_area_width
);
7765 /* Does the scroll bar exist yet? */
7766 if (NILP (w
->vertical_scroll_bar
))
7767 bar
= x_scroll_bar_create (w
, pixel_top
, pixel_left
, pixel_width
,
7771 /* It may just need to be moved and resized. */
7772 unsigned int mask
= 0;
7774 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
7778 if (pixel_left
!= XINT (bar
->left
))
7780 if (pixel_top
!= XINT (bar
->top
))
7782 if (pixel_width
!= XINT (bar
->width
))
7784 if (pixel_height
!= XINT (bar
->height
))
7787 #ifdef USE_TOOLKIT_SCROLL_BARS
7789 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
7791 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7792 pixel_left
+ pixel_width
- scroll_bar_area_width
,
7794 (scroll_bar_area_width
7796 + VERTICAL_SCROLL_BAR_WIDTH_TRIM
),
7797 pixel_height
, False
);
7798 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7801 - VERTICAL_SCROLL_BAR_WIDTH_TRIM
),
7803 VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7804 pixel_height
, False
);
7808 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7809 pixel_left
, pixel_top
,
7810 VERTICAL_SCROLL_BAR_WIDTH_TRIM
, pixel_height
, False
);
7811 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7814 - VERTICAL_SCROLL_BAR_WIDTH_TRIM
),
7816 (scroll_bar_area_width
7818 + VERTICAL_SCROLL_BAR_WIDTH_TRIM
),
7819 pixel_height
, False
);
7822 /* Move/size the scroll bar widget. */
7824 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
7825 pixel_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7827 pixel_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7830 #else /* not USE_TOOLKIT_SCROLL_BARS */
7832 /* Clear areas not covered by the scroll bar. This makes sure a
7833 previous mode line display is cleared after C-x 2 C-x 1, for
7834 example. Non-toolkit scroll bars are as wide as the area
7835 reserved for scroll bars - trim at both sides. */
7836 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7837 pixel_left
, pixel_top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7838 pixel_height
, False
);
7839 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7842 - VERTICAL_SCROLL_BAR_WIDTH_TRIM
),
7844 VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7845 pixel_height
, False
);
7847 /* Move/size the scroll bar window. */
7852 wc
.x
= pixel_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
7854 wc
.width
= pixel_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
7855 wc
.height
= pixel_height
;
7856 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
7860 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7862 /* Remember new settings. */
7863 XSETINT (bar
->left
, pixel_left
);
7864 XSETINT (bar
->top
, pixel_top
);
7865 XSETINT (bar
->width
, pixel_width
);
7866 XSETINT (bar
->height
, pixel_height
);
7871 #if USE_TOOLKIT_SCROLL_BARS
7872 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
7873 #else /* not USE_TOOLKIT_SCROLL_BARS */
7874 /* Set the scroll bar's current state, unless we're currently being
7876 if (NILP (bar
->dragging
))
7878 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, pixel_height
);
7881 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
7884 int start
= ((double) position
* top_range
) / whole
;
7885 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
7886 x_scroll_bar_set_handle (bar
, start
, end
, 0);
7889 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7891 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
7895 /* The following three hooks are used when we're doing a thorough
7896 redisplay of the frame. We don't explicitly know which scroll bars
7897 are going to be deleted, because keeping track of when windows go
7898 away is a real pain - "Can you say set-window-configuration, boys
7899 and girls?" Instead, we just assert at the beginning of redisplay
7900 that *all* scroll bars are to be removed, and then save a scroll bar
7901 from the fiery pit when we actually redisplay its window. */
7903 /* Arrange for all scroll bars on FRAME to be removed at the next call
7904 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
7905 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
7908 XTcondemn_scroll_bars (frame
)
7911 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
7912 while (! NILP (FRAME_SCROLL_BARS (frame
)))
7915 bar
= FRAME_SCROLL_BARS (frame
);
7916 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
7917 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
7918 XSCROLL_BAR (bar
)->prev
= Qnil
;
7919 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
7920 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
7921 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
7925 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
7926 Note that WINDOW isn't necessarily condemned at all. */
7928 XTredeem_scroll_bar (window
)
7929 struct window
*window
;
7931 struct scroll_bar
*bar
;
7933 /* We can't redeem this window's scroll bar if it doesn't have one. */
7934 if (NILP (window
->vertical_scroll_bar
))
7937 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
7939 /* Unlink it from the condemned list. */
7941 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
7943 if (NILP (bar
->prev
))
7945 /* If the prev pointer is nil, it must be the first in one of
7947 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
7948 /* It's not condemned. Everything's fine. */
7950 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
7951 window
->vertical_scroll_bar
))
7952 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
7954 /* If its prev pointer is nil, it must be at the front of
7955 one or the other! */
7959 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
7961 if (! NILP (bar
->next
))
7962 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
7964 bar
->next
= FRAME_SCROLL_BARS (f
);
7966 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
7967 if (! NILP (bar
->next
))
7968 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
7972 /* Remove all scroll bars on FRAME that haven't been saved since the
7973 last call to `*condemn_scroll_bars_hook'. */
7976 XTjudge_scroll_bars (f
)
7979 Lisp_Object bar
, next
;
7981 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
7983 /* Clear out the condemned list now so we won't try to process any
7984 more events on the hapless scroll bars. */
7985 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
7987 for (; ! NILP (bar
); bar
= next
)
7989 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
7991 x_scroll_bar_remove (b
);
7994 b
->next
= b
->prev
= Qnil
;
7997 /* Now there should be no references to the condemned scroll bars,
7998 and they should get garbage-collected. */
8002 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8003 is a no-op when using toolkit scroll bars.
8005 This may be called from a signal handler, so we have to ignore GC
8009 x_scroll_bar_expose (bar
, event
)
8010 struct scroll_bar
*bar
;
8013 #ifndef USE_TOOLKIT_SCROLL_BARS
8015 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8016 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8017 GC gc
= f
->output_data
.x
->normal_gc
;
8018 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8022 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
8024 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8025 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8027 /* x, y, width, height */
8029 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
8030 XINT (bar
->height
) - 1);
8034 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8037 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8038 is set to something other than no_event, it is enqueued.
8040 This may be called from a signal handler, so we have to ignore GC
8044 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
8045 struct scroll_bar
*bar
;
8047 struct input_event
*emacs_event
;
8049 if (! GC_WINDOWP (bar
->window
))
8052 emacs_event
->kind
= scroll_bar_click
;
8053 emacs_event
->code
= event
->xbutton
.button
- Button1
;
8054 emacs_event
->modifiers
8055 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8056 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
8057 event
->xbutton
.state
)
8058 | (event
->type
== ButtonRelease
8061 emacs_event
->frame_or_window
= bar
->window
;
8062 emacs_event
->timestamp
= event
->xbutton
.time
;
8065 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8067 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8070 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8071 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
8074 if (y
> top_range
) y
= top_range
;
8076 if (y
< XINT (bar
->start
))
8077 emacs_event
->part
= scroll_bar_above_handle
;
8078 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8079 emacs_event
->part
= scroll_bar_handle
;
8081 emacs_event
->part
= scroll_bar_below_handle
;
8083 /* Just because the user has clicked on the handle doesn't mean
8084 they want to drag it. Lisp code needs to be able to decide
8085 whether or not we're dragging. */
8087 /* If the user has just clicked on the handle, record where they're
8089 if (event
->type
== ButtonPress
8090 && emacs_event
->part
== scroll_bar_handle
)
8091 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
8094 /* If the user has released the handle, set it to its final position. */
8095 if (event
->type
== ButtonRelease
8096 && ! NILP (bar
->dragging
))
8098 int new_start
= y
- XINT (bar
->dragging
);
8099 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8101 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8102 bar
->dragging
= Qnil
;
8105 /* Same deal here as the other #if 0. */
8107 /* Clicks on the handle are always reported as occurring at the top of
8109 if (emacs_event
->part
== scroll_bar_handle
)
8110 emacs_event
->x
= bar
->start
;
8112 XSETINT (emacs_event
->x
, y
);
8114 XSETINT (emacs_event
->x
, y
);
8117 XSETINT (emacs_event
->y
, top_range
);
8121 /* Handle some mouse motion while someone is dragging the scroll bar.
8123 This may be called from a signal handler, so we have to ignore GC
8127 x_scroll_bar_note_movement (bar
, event
)
8128 struct scroll_bar
*bar
;
8131 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8133 last_mouse_movement_time
= event
->xmotion
.time
;
8136 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8138 /* If we're dragging the bar, display it. */
8139 if (! GC_NILP (bar
->dragging
))
8141 /* Where should the handle be now? */
8142 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
8144 if (new_start
!= XINT (bar
->start
))
8146 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8148 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8153 /* Return information to the user about the current position of the mouse
8154 on the scroll bar. */
8157 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8159 Lisp_Object
*bar_window
;
8160 enum scroll_bar_part
*part
;
8162 unsigned long *time
;
8164 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8165 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8166 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8168 Window dummy_window
;
8170 unsigned int dummy_mask
;
8174 /* Get the mouse's position relative to the scroll bar window, and
8176 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
8178 /* Root, child, root x and root y. */
8179 &dummy_window
, &dummy_window
,
8180 &dummy_coord
, &dummy_coord
,
8182 /* Position relative to scroll bar. */
8185 /* Mouse buttons and modifier keys. */
8192 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8195 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8197 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8199 if (! NILP (bar
->dragging
))
8200 win_y
-= XINT (bar
->dragging
);
8204 if (win_y
> top_range
)
8208 *bar_window
= bar
->window
;
8210 if (! NILP (bar
->dragging
))
8211 *part
= scroll_bar_handle
;
8212 else if (win_y
< XINT (bar
->start
))
8213 *part
= scroll_bar_above_handle
;
8214 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8215 *part
= scroll_bar_handle
;
8217 *part
= scroll_bar_below_handle
;
8219 XSETINT (*x
, win_y
);
8220 XSETINT (*y
, top_range
);
8223 last_mouse_scroll_bar
= Qnil
;
8226 *time
= last_mouse_movement_time
;
8232 /* The screen has been cleared so we may have changed foreground or
8233 background colors, and the scroll bars may need to be redrawn.
8234 Clear out the scroll bars, and ask for expose events, so we can
8238 x_scroll_bar_clear (f
)
8241 #ifndef USE_TOOLKIT_SCROLL_BARS
8244 /* We can have scroll bars even if this is 0,
8245 if we just turned off scroll bar mode.
8246 But in that case we should not clear them. */
8247 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8248 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
8249 bar
= XSCROLL_BAR (bar
)->next
)
8250 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
8252 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8255 /* This processes Expose events from the menu-bar specific X event
8256 loop in xmenu.c. This allows to redisplay the frame if necessary
8257 when handling menu-bar or pop-up items. */
8260 process_expose_from_menu (event
)
8264 struct x_display_info
*dpyinfo
;
8265 int frame_exposed_p
= 0;
8269 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
8270 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8273 if (f
->async_visible
== 0)
8275 f
->async_visible
= 1;
8276 f
->async_iconified
= 0;
8277 f
->output_data
.x
->has_been_visible
= 1;
8278 SET_FRAME_GARBAGED (f
);
8282 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
8283 event
.xexpose
.x
, event
.xexpose
.y
,
8284 event
.xexpose
.width
, event
.xexpose
.height
);
8285 frame_exposed_p
= 1;
8290 struct scroll_bar
*bar
8291 = x_window_to_scroll_bar (event
.xexpose
.window
);
8294 x_scroll_bar_expose (bar
, &event
);
8298 return frame_exposed_p
;
8301 /* Define a queue to save up SelectionRequest events for later handling. */
8303 struct selection_event_queue
8306 struct selection_event_queue
*next
;
8309 static struct selection_event_queue
*queue
;
8311 /* Nonzero means queue up certain events--don't process them yet. */
8313 static int x_queue_selection_requests
;
8315 /* Queue up an X event *EVENT, to be processed later. */
8318 x_queue_event (f
, event
)
8322 struct selection_event_queue
*queue_tmp
8323 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
8325 if (queue_tmp
!= NULL
)
8327 queue_tmp
->event
= *event
;
8328 queue_tmp
->next
= queue
;
8333 /* Take all the queued events and put them back
8334 so that they get processed afresh. */
8337 x_unqueue_events (display
)
8340 while (queue
!= NULL
)
8342 struct selection_event_queue
*queue_tmp
= queue
;
8343 XPutBackEvent (display
, &queue_tmp
->event
);
8344 queue
= queue_tmp
->next
;
8345 xfree ((char *)queue_tmp
);
8349 /* Start queuing SelectionRequest events. */
8352 x_start_queuing_selection_requests (display
)
8355 x_queue_selection_requests
++;
8358 /* Stop queuing SelectionRequest events. */
8361 x_stop_queuing_selection_requests (display
)
8364 x_queue_selection_requests
--;
8365 x_unqueue_events (display
);
8368 /* The main X event-reading loop - XTread_socket. */
8370 /* Time stamp of enter window event. This is only used by XTread_socket,
8371 but we have to put it out here, since static variables within functions
8372 sometimes don't work. */
8374 static Time enter_timestamp
;
8376 /* This holds the state XLookupString needs to implement dead keys
8377 and other tricks known as "compose processing". _X Window System_
8378 says that a portable program can't use this, but Stephen Gildea assures
8379 me that letting the compiler initialize it to zeros will work okay.
8381 This must be defined outside of XTread_socket, for the same reasons
8382 given for enter_time stamp, above. */
8384 static XComposeStatus compose_status
;
8386 /* Record the last 100 characters stored
8387 to help debug the loss-of-chars-during-GC problem. */
8389 static int temp_index
;
8390 static short temp_buffer
[100];
8392 /* Set this to nonzero to fake an "X I/O error"
8393 on a particular display. */
8395 struct x_display_info
*XTread_socket_fake_io_error
;
8397 /* When we find no input here, we occasionally do a no-op command
8398 to verify that the X server is still running and we can still talk with it.
8399 We try all the open displays, one by one.
8400 This variable is used for cycling thru the displays. */
8402 static struct x_display_info
*next_noop_dpyinfo
;
8404 #define SET_SAVED_MENU_EVENT(size) \
8407 if (f->output_data.x->saved_menu_event == 0) \
8408 f->output_data.x->saved_menu_event \
8409 = (XEvent *) xmalloc (sizeof (XEvent)); \
8410 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8411 if (numchars >= 1) \
8413 bufp->kind = menu_bar_activate_event; \
8414 XSETFRAME (bufp->frame_or_window, f); \
8422 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8423 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8425 /* Read events coming from the X server.
8426 This routine is called by the SIGIO handler.
8427 We return as soon as there are no more events to be read.
8429 Events representing keys are stored in buffer BUFP,
8430 which can hold up to NUMCHARS characters.
8431 We return the number of characters stored into the buffer,
8432 thus pretending to be `read'.
8434 EXPECTED is nonzero if the caller knows input is available. */
8437 XTread_socket (sd
, bufp
, numchars
, expected
)
8439 /* register */ struct input_event
*bufp
;
8440 /* register */ int numchars
;
8447 int event_found
= 0;
8448 struct x_display_info
*dpyinfo
;
8450 Status status_return
;
8453 if (interrupt_input_blocked
)
8455 interrupt_input_pending
= 1;
8459 interrupt_input_pending
= 0;
8462 /* So people can tell when we have read the available input. */
8463 input_signal_count
++;
8466 abort (); /* Don't think this happens. */
8468 /* Find the display we are supposed to read input for.
8469 It's the one communicating on descriptor SD. */
8470 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
8472 #if 0 /* This ought to be unnecessary; let's verify it. */
8474 /* If available, Xlib uses FIOSNBIO to make the socket
8475 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8476 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8477 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8478 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
8479 #endif /* ! defined (FIOSNBIO) */
8482 #if 0 /* This code can't be made to work, with multiple displays,
8483 and appears not to be used on any system any more.
8484 Also keyboard.c doesn't turn O_NDELAY on and off
8485 for X connections. */
8488 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
8490 extern int read_alarm_should_throw
;
8491 read_alarm_should_throw
= 1;
8492 XPeekEvent (dpyinfo
->display
, &event
);
8493 read_alarm_should_throw
= 0;
8495 #endif /* HAVE_SELECT */
8499 /* For debugging, this gives a way to fake an I/O error. */
8500 if (dpyinfo
== XTread_socket_fake_io_error
)
8502 XTread_socket_fake_io_error
= 0;
8503 x_io_error_quitter (dpyinfo
->display
);
8506 while (XPending (dpyinfo
->display
))
8508 XNextEvent (dpyinfo
->display
, &event
);
8510 if (display_busy_cursor_p
)
8512 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8513 display until the next X event is read and we come
8514 here again. Setting it to 1 inhibits busy-cursor
8515 display for direct commands. */
8516 if (event
.type
== MotionNotify
8517 || event
.type
== EnterNotify
8518 || (dpyinfo
->grabbed
8519 && event
.type
!= ButtonRelease
))
8520 inhibit_busy_cursor
= 2;
8522 inhibit_busy_cursor
= 1;
8527 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
8528 event
.xclient
.window
);
8529 /* The necessity of the following line took me
8530 a full work-day to decipher from the docs!! */
8531 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
8541 if (event
.xclient
.message_type
8542 == dpyinfo
->Xatom_wm_protocols
8543 && event
.xclient
.format
== 32)
8545 if (event
.xclient
.data
.l
[0]
8546 == dpyinfo
->Xatom_wm_take_focus
)
8548 /* Use x_any_window_to_frame because this
8549 could be the shell widget window
8550 if the frame has no title bar. */
8551 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8553 /* Not quite sure this is needed -pd */
8554 if (f
&& FRAME_XIC (f
))
8555 XSetICFocus (FRAME_XIC (f
));
8557 /* Since we set WM_TAKE_FOCUS, we must call
8558 XSetInputFocus explicitly. But not if f is null,
8559 since that might be an event for a deleted frame. */
8562 Display
*d
= event
.xclient
.display
;
8563 /* Catch and ignore errors, in case window has been
8564 iconified by a window manager such as GWM. */
8565 int count
= x_catch_errors (d
);
8566 XSetInputFocus (d
, event
.xclient
.window
,
8567 RevertToPointerRoot
,
8568 event
.xclient
.data
.l
[1]);
8569 /* This is needed to detect the error
8570 if there is an error. */
8572 x_uncatch_errors (d
, count
);
8574 /* Not certain about handling scroll bars here */
8576 else if (event
.xclient
.data
.l
[0]
8577 == dpyinfo
->Xatom_wm_save_yourself
)
8579 /* Save state modify the WM_COMMAND property to
8580 something which can reinstate us. This notifies
8581 the session manager, who's looking for such a
8582 PropertyNotify. Can restart processing when
8583 a keyboard or mouse event arrives. */
8586 f
= x_top_window_to_frame (dpyinfo
,
8587 event
.xclient
.window
);
8589 /* This is just so we only give real data once
8590 for a single Emacs process. */
8591 if (f
== selected_frame
)
8592 XSetCommand (FRAME_X_DISPLAY (f
),
8593 event
.xclient
.window
,
8594 initial_argv
, initial_argc
);
8596 XSetCommand (FRAME_X_DISPLAY (f
),
8597 event
.xclient
.window
,
8601 else if (event
.xclient
.data
.l
[0]
8602 == dpyinfo
->Xatom_wm_delete_window
)
8605 = x_any_window_to_frame (dpyinfo
,
8606 event
.xclient
.window
);
8613 bufp
->kind
= delete_window_event
;
8614 XSETFRAME (bufp
->frame_or_window
, f
);
8622 else if (event
.xclient
.message_type
8623 == dpyinfo
->Xatom_wm_configure_denied
)
8626 else if (event
.xclient
.message_type
8627 == dpyinfo
->Xatom_wm_window_moved
)
8631 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
8633 new_x
= event
.xclient
.data
.s
[0];
8634 new_y
= event
.xclient
.data
.s
[1];
8638 f
->output_data
.x
->left_pos
= new_x
;
8639 f
->output_data
.x
->top_pos
= new_y
;
8643 else if (event
.xclient
.message_type
8644 == dpyinfo
->Xatom_editres
)
8647 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8648 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
8651 #endif /* HACK_EDITRES */
8652 else if ((event
.xclient
.message_type
8653 == dpyinfo
->Xatom_DONE
)
8654 || (event
.xclient
.message_type
8655 == dpyinfo
->Xatom_PAGE
))
8657 /* Ghostview job completed. Kill it. We could
8658 reply with "Next" if we received "Page", but we
8659 currently never do because we are interested in
8660 images, only, which should have 1 page. */
8661 Window gs_window
= (Window
) event
.xclient
.data
.l
[0];
8662 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
8664 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
8665 x_kill_gs_process (pixmap
, f
);
8666 expose_frame (f
, 0, 0, 0, 0);
8668 #ifdef USE_TOOLKIT_SCROLL_BARS
8669 /* Scroll bar callbacks send a ClientMessage from which
8670 we construct an input_event. */
8671 else if (event
.xclient
.message_type
8672 == dpyinfo
->Xatom_Scrollbar
)
8674 x_scroll_bar_to_input_event (&event
, bufp
);
8675 ++bufp
, ++count
, --numchars
;
8678 #endif /* USE_TOOLKIT_SCROLL_BARS */
8684 case SelectionNotify
:
8685 #ifdef USE_X_TOOLKIT
8686 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
8688 #endif /* not USE_X_TOOLKIT */
8689 x_handle_selection_notify (&event
.xselection
);
8692 case SelectionClear
: /* Someone has grabbed ownership. */
8693 #ifdef USE_X_TOOLKIT
8694 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
8696 #endif /* USE_X_TOOLKIT */
8698 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
8703 bufp
->kind
= selection_clear_event
;
8704 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
8705 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
8706 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
8707 bufp
->frame_or_window
= Qnil
;
8715 case SelectionRequest
: /* Someone wants our selection. */
8716 #ifdef USE_X_TOOLKIT
8717 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
8719 #endif /* USE_X_TOOLKIT */
8720 if (x_queue_selection_requests
)
8721 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
8725 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
8730 bufp
->kind
= selection_request_event
;
8731 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
8732 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
8733 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
8734 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
8735 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
8736 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
8737 bufp
->frame_or_window
= Qnil
;
8745 case PropertyNotify
:
8746 #ifdef USE_X_TOOLKIT
8747 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
8749 #endif /* not USE_X_TOOLKIT */
8750 x_handle_property_notify (&event
.xproperty
);
8753 case ReparentNotify
:
8754 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
8758 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
8759 x_real_positions (f
, &x
, &y
);
8760 f
->output_data
.x
->left_pos
= x
;
8761 f
->output_data
.x
->top_pos
= y
;
8766 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8769 if (f
->async_visible
== 0)
8771 f
->async_visible
= 1;
8772 f
->async_iconified
= 0;
8773 f
->output_data
.x
->has_been_visible
= 1;
8774 SET_FRAME_GARBAGED (f
);
8777 expose_frame (x_window_to_frame (dpyinfo
,
8778 event
.xexpose
.window
),
8779 event
.xexpose
.x
, event
.xexpose
.y
,
8780 event
.xexpose
.width
, event
.xexpose
.height
);
8784 #ifdef USE_TOOLKIT_SCROLL_BARS
8785 /* Dispatch event to the widget. */
8787 #else /* not USE_TOOLKIT_SCROLL_BARS */
8788 struct scroll_bar
*bar
8789 = x_window_to_scroll_bar (event
.xexpose
.window
);
8792 x_scroll_bar_expose (bar
, &event
);
8793 #ifdef USE_X_TOOLKIT
8796 #endif /* USE_X_TOOLKIT */
8797 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8801 case GraphicsExpose
: /* This occurs when an XCopyArea's
8802 source area was obscured or not
8804 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
8808 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
8809 event
.xgraphicsexpose
.width
,
8810 event
.xgraphicsexpose
.height
);
8812 #ifdef USE_X_TOOLKIT
8815 #endif /* USE_X_TOOLKIT */
8818 case NoExpose
: /* This occurs when an XCopyArea's
8819 source area was completely
8824 /* Redo the mouse-highlight after the tooltip has gone. */
8825 if (event
.xmap
.window
== tip_window
)
8828 redo_mouse_highlight ();
8831 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
8832 if (f
) /* F may no longer exist if
8833 the frame was deleted. */
8835 /* While a frame is unmapped, display generation is
8836 disabled; you don't want to spend time updating a
8837 display that won't ever be seen. */
8838 f
->async_visible
= 0;
8839 /* We can't distinguish, from the event, whether the window
8840 has become iconified or invisible. So assume, if it
8841 was previously visible, than now it is iconified.
8842 But x_make_frame_invisible clears both
8843 the visible flag and the iconified flag;
8844 and that way, we know the window is not iconified now. */
8845 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
8847 f
->async_iconified
= 1;
8849 bufp
->kind
= iconify_event
;
8850 XSETFRAME (bufp
->frame_or_window
, f
);
8859 if (event
.xmap
.window
== tip_window
)
8860 /* The tooltip has been drawn already. Avoid
8861 the SET_FRAME_GARBAGED below. */
8864 /* We use x_top_window_to_frame because map events can
8865 come for sub-windows and they don't mean that the
8866 frame is visible. */
8867 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
8870 f
->async_visible
= 1;
8871 f
->async_iconified
= 0;
8872 f
->output_data
.x
->has_been_visible
= 1;
8874 /* wait_reading_process_input will notice this and update
8875 the frame's display structures. */
8876 SET_FRAME_GARBAGED (f
);
8880 bufp
->kind
= deiconify_event
;
8881 XSETFRAME (bufp
->frame_or_window
, f
);
8886 else if (! NILP (Vframe_list
)
8887 && ! NILP (XCONS (Vframe_list
)->cdr
))
8888 /* Force a redisplay sooner or later
8889 to update the frame titles
8890 in case this is the second frame. */
8891 record_asynch_buffer_change ();
8896 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
8899 /* I couldn't find a way to prevent LessTif scroll bars
8900 from consuming key events. */
8903 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
8905 if (widget
&& XmIsScrollBar (widget
))
8907 widget
= XtParent (widget
);
8908 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
8911 #endif /* USE_MOTIF */
8915 KeySym keysym
, orig_keysym
;
8916 /* al%imercury@uunet.uu.net says that making this 81 instead of
8917 80 fixed a bug whereby meta chars made his Emacs hang. */
8918 unsigned char copy_buffer
[81];
8922 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
8923 extra_keyboard_modifiers
);
8924 modifiers
= event
.xkey
.state
;
8926 /* This will have to go some day... */
8928 /* make_lispy_event turns chars into control chars.
8929 Don't do it here because XLookupString is too eager. */
8930 event
.xkey
.state
&= ~ControlMask
;
8931 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
8932 | dpyinfo
->super_mod_mask
8933 | dpyinfo
->hyper_mod_mask
8934 | dpyinfo
->alt_mod_mask
);
8936 /* In case Meta is ComposeCharacter,
8937 clear its status. According to Markus Ehrnsperger
8938 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
8939 this enables ComposeCharacter to work whether or
8940 not it is combined with Meta. */
8941 if (modifiers
& dpyinfo
->meta_mod_mask
)
8942 bzero (&compose_status
, sizeof (compose_status
));
8947 /* The necessity of the following line took me
8948 a full work-day to decipher from the docs!! */
8949 if (XFilterEvent (&event
, None
))
8951 nbytes
= XmbLookupString (FRAME_XIC (f
),
8952 &event
.xkey
, copy_buffer
,
8955 if (status_return
== XLookupNone
)
8957 else if (status_return
== XLookupChars
)
8959 else if (status_return
!= XLookupKeySym
8960 && status_return
!= XLookupBoth
)
8964 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
8965 80, &keysym
, &compose_status
);
8967 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
8968 80, &keysym
, &compose_status
);
8971 orig_keysym
= keysym
;
8975 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
8976 || keysym
== XK_Delete
8977 #ifdef XK_ISO_Left_Tab
8978 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
8980 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
8981 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
8982 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
8984 /* This recognizes the "extended function keys".
8985 It seems there's no cleaner way.
8986 Test IsModifierKey to avoid handling mode_switch
8988 || ((unsigned) (keysym
) >= XK_Select
8989 && (unsigned)(keysym
) < XK_KP_Space
)
8991 #ifdef XK_dead_circumflex
8992 || orig_keysym
== XK_dead_circumflex
8994 #ifdef XK_dead_grave
8995 || orig_keysym
== XK_dead_grave
8997 #ifdef XK_dead_tilde
8998 || orig_keysym
== XK_dead_tilde
9000 #ifdef XK_dead_diaeresis
9001 || orig_keysym
== XK_dead_diaeresis
9003 #ifdef XK_dead_macron
9004 || orig_keysym
== XK_dead_macron
9006 #ifdef XK_dead_degree
9007 || orig_keysym
== XK_dead_degree
9009 #ifdef XK_dead_acute
9010 || orig_keysym
== XK_dead_acute
9012 #ifdef XK_dead_cedilla
9013 || orig_keysym
== XK_dead_cedilla
9015 #ifdef XK_dead_breve
9016 || orig_keysym
== XK_dead_breve
9018 #ifdef XK_dead_ogonek
9019 || orig_keysym
== XK_dead_ogonek
9021 #ifdef XK_dead_caron
9022 || orig_keysym
== XK_dead_caron
9024 #ifdef XK_dead_doubleacute
9025 || orig_keysym
== XK_dead_doubleacute
9027 #ifdef XK_dead_abovedot
9028 || orig_keysym
== XK_dead_abovedot
9030 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
9031 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
9032 /* Any "vendor-specific" key is ok. */
9033 || (orig_keysym
& (1 << 28)))
9034 && ! (IsModifierKey (orig_keysym
)
9036 #ifdef XK_Mode_switch
9037 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
9040 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
9042 #endif /* not HAVE_X11R5 */
9045 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9047 temp_buffer
[temp_index
++] = keysym
;
9048 bufp
->kind
= non_ascii_keystroke
;
9049 bufp
->code
= keysym
;
9050 XSETFRAME (bufp
->frame_or_window
, f
);
9052 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9054 bufp
->timestamp
= event
.xkey
.time
;
9059 if (display_busy_cursor_p
)
9060 if (keysym
!= XK_Return
|| minibuf_level
== 0)
9061 inhibit_busy_cursor
= 2;
9063 else if (numchars
> nbytes
)
9067 for (i
= 0; i
< nbytes
; i
++)
9069 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9071 temp_buffer
[temp_index
++] = copy_buffer
[i
];
9072 bufp
->kind
= ascii_keystroke
;
9073 bufp
->code
= copy_buffer
[i
];
9074 XSETFRAME (bufp
->frame_or_window
, f
);
9076 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9078 bufp
->timestamp
= event
.xkey
.time
;
9085 if (keysym
== NoSymbol
)
9096 /* Here's a possible interpretation of the whole
9097 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9098 you get a FocusIn event, you have to get a FocusOut
9099 event before you relinquish the focus. If you
9100 haven't received a FocusIn event, then a mere
9101 LeaveNotify is enough to free you. */
9105 int from_menu_bar_p
= 0;
9107 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9109 #ifdef LESSTIF_VERSION
9110 /* When clicking outside of a menu bar popup to close
9111 it, we get a FocusIn/ EnterNotify sequence of
9112 events. The flag event.xcrossing.focus is not set
9113 in the EnterNotify event of that sequence because
9114 the focus is in the menu bar,
9115 event.xcrossing.window is the frame's X window.
9116 Unconditionally setting the focus frame to null in
9117 this case is not the right thing, because no event
9118 follows that could set the focus frame to the right
9121 This could be a LessTif bug, but I wasn't able to
9122 reproduce the behavior in a simple test program.
9124 (gerd, LessTif 0.88.1). */
9126 if (!event
.xcrossing
.focus
9128 && f
->output_data
.x
->menubar_widget
)
9133 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9134 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9135 from_menu_bar_p
= 1;
9137 #endif /* LESSTIF_VERSION */
9139 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9141 /* Avoid nasty pop/raise loops. */
9142 if (f
&& (!(f
->auto_raise
)
9144 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
9146 x_new_focus_frame (dpyinfo
, f
);
9147 enter_timestamp
= event
.xcrossing
.time
;
9150 else if (f
== dpyinfo
->x_focus_frame
)
9151 x_new_focus_frame (dpyinfo
, 0);
9153 /* EnterNotify counts as mouse movement,
9154 so update things that depend on mouse position. */
9155 if (f
&& !f
->output_data
.x
->busy_p
)
9156 note_mouse_movement (f
, &event
.xmotion
);
9161 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9162 if (event
.xfocus
.detail
!= NotifyPointer
)
9163 dpyinfo
->x_focus_event_frame
= f
;
9165 x_new_focus_frame (dpyinfo
, f
);
9168 if (f
&& FRAME_XIC (f
))
9169 XSetICFocus (FRAME_XIC (f
));
9175 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9179 int from_menu_bar_p
= 0;
9181 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9183 /* If we move outside the frame, then we're
9184 certainly no longer on any text in the frame. */
9185 clear_mouse_face (dpyinfo
);
9186 dpyinfo
->mouse_face_mouse_frame
= 0;
9189 /* Generate a nil HELP_EVENT to cancel a help-echo.
9190 Do it only if there's something to cancel.
9191 Otherwise, the startup message is cleared when
9192 the mouse leaves the frame. */
9193 if (any_help_event_p
)
9195 XSETFRAME (frame
, f
);
9196 bufp
->kind
= HELP_EVENT
;
9197 bufp
->frame_or_window
= Fcons (frame
, Qnil
);
9198 ++bufp
, ++count
, --numchars
;
9201 #ifdef LESSTIF_VERSION
9202 /* Please see the comment at the start of the
9203 EnterNotify case. */
9204 if (!event
.xcrossing
.focus
9205 && f
->output_data
.x
->menubar_widget
)
9209 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9210 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9211 from_menu_bar_p
= 1;
9213 #endif /* LESSTIF_VERSION */
9215 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9216 x_mouse_leave (dpyinfo
);
9219 if (f
== dpyinfo
->x_focus_event_frame
)
9220 dpyinfo
->x_focus_event_frame
= 0;
9221 if (f
== dpyinfo
->x_focus_frame
)
9222 x_new_focus_frame (dpyinfo
, 0);
9228 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9229 if (event
.xfocus
.detail
!= NotifyPointer
9230 && f
== dpyinfo
->x_focus_event_frame
)
9231 dpyinfo
->x_focus_event_frame
= 0;
9232 if (f
&& f
== dpyinfo
->x_focus_frame
)
9233 x_new_focus_frame (dpyinfo
, 0);
9236 if (f
&& FRAME_XIC (f
))
9237 XUnsetICFocus (FRAME_XIC (f
));
9244 previous_help_echo
= help_echo
;
9247 if (dpyinfo
->grabbed
&& last_mouse_frame
9248 && FRAME_LIVE_P (last_mouse_frame
))
9249 f
= last_mouse_frame
;
9251 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
9254 note_mouse_movement (f
, &event
.xmotion
);
9257 #ifndef USE_X_TOOLKIT
9258 struct scroll_bar
*bar
9259 = x_window_to_scroll_bar (event
.xmotion
.window
);
9262 x_scroll_bar_note_movement (bar
, &event
);
9263 #endif /* USE_X_TOOLKIT */
9265 /* If we move outside the frame, then we're
9266 certainly no longer on any text in the frame. */
9267 clear_mouse_face (dpyinfo
);
9270 /* If the contents of the global variable help_echo
9271 has changed, generate a HELP_EVENT. */
9272 if (STRINGP (help_echo
)
9273 || STRINGP (previous_help_echo
))
9278 XSETFRAME (frame
, f
);
9282 any_help_event_p
= 1;
9283 bufp
->kind
= HELP_EVENT
;
9284 bufp
->frame_or_window
= Fcons (frame
, help_echo
);
9285 ++bufp
, ++count
, --numchars
;
9291 case ConfigureNotify
:
9292 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
9295 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
9296 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
9298 #ifndef USE_X_TOOLKIT
9299 /* In the toolkit version, change_frame_size
9300 is called by the code that handles resizing
9301 of the EmacsFrame widget. */
9303 /* Even if the number of character rows and columns has
9304 not changed, the font size may have changed, so we need
9305 to check the pixel dimensions as well. */
9306 if (columns
!= f
->width
9307 || rows
!= f
->height
9308 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
9309 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
9311 change_frame_size (f
, rows
, columns
, 0, 1);
9312 SET_FRAME_GARBAGED (f
);
9313 cancel_mouse_face (f
);
9317 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
9318 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
9320 /* What we have now is the position of Emacs's own window.
9321 Convert that to the position of the window manager window. */
9322 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
9323 &f
->output_data
.x
->top_pos
);
9325 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
9327 /* Since the WM decorations come below top_pos now,
9328 we must put them below top_pos in the future. */
9329 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9330 x_wm_set_size_hint (f
, (long) 0, 0);
9333 /* Some window managers pass (0,0) as the location of
9334 the window, and the Motif event handler stores it
9335 in the emacs widget, which messes up Motif menus. */
9336 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
9338 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
9339 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
9341 #endif /* USE_MOTIF */
9348 /* If we decide we want to generate an event to be seen
9349 by the rest of Emacs, we put it here. */
9350 struct input_event emacs_event
;
9353 emacs_event
.kind
= no_event
;
9354 bzero (&compose_status
, sizeof (compose_status
));
9356 if (dpyinfo
->grabbed
9358 && FRAME_LIVE_P (last_mouse_frame
))
9359 f
= last_mouse_frame
;
9361 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9365 /* Is this in the toolbar? */
9366 if (WINDOWP (f
->toolbar_window
)
9367 && XFASTINT (XWINDOW (f
->toolbar_window
)->height
))
9372 x
= event
.xbutton
.x
;
9373 y
= event
.xbutton
.y
;
9376 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
9377 if (EQ (window
, f
->toolbar_window
))
9379 x_handle_toolbar_click (f
, &event
.xbutton
);
9385 if (!dpyinfo
->x_focus_frame
9386 || f
== dpyinfo
->x_focus_frame
)
9387 construct_mouse_click (&emacs_event
, &event
, f
);
9391 #ifndef USE_TOOLKIT_SCROLL_BARS
9392 struct scroll_bar
*bar
9393 = x_window_to_scroll_bar (event
.xbutton
.window
);
9396 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
9397 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9400 if (event
.type
== ButtonPress
)
9402 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
9403 last_mouse_frame
= f
;
9404 /* Ignore any mouse motion that happened
9405 before this event; any subsequent mouse-movement
9406 Emacs events should reflect only motion after
9412 last_toolbar_item
= -1;
9413 if (display_busy_cursor_p
)
9414 inhibit_busy_cursor
= 2;
9418 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
9421 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
9423 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
9429 #ifdef USE_X_TOOLKIT
9430 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9431 /* For a down-event in the menu bar,
9432 don't pass it to Xt right now.
9433 Instead, save it away
9434 and we will pass it to Xt from kbd_buffer_get_event.
9435 That way, we can run some Lisp code first. */
9436 if (f
&& event
.type
== ButtonPress
9437 /* Verify the event is really within the menu bar
9438 and not just sent to it due to grabbing. */
9439 && event
.xbutton
.x
>= 0
9440 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
9441 && event
.xbutton
.y
>= 0
9442 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
9443 && event
.xbutton
.same_screen
)
9445 SET_SAVED_BUTTON_EVENT
;
9446 XSETFRAME (last_mouse_press_frame
, f
);
9448 else if (event
.type
== ButtonPress
)
9450 last_mouse_press_frame
= Qnil
;
9454 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9455 but I am trying to be cautious. */
9456 else if (event
.type
== ButtonRelease
)
9458 if (!NILP (last_mouse_press_frame
))
9460 f
= XFRAME (last_mouse_press_frame
);
9461 if (f
->output_data
.x
)
9462 SET_SAVED_BUTTON_EVENT
;
9467 #endif /* USE_MOTIF */
9470 #endif /* USE_X_TOOLKIT */
9474 case CirculateNotify
:
9477 case CirculateRequest
:
9480 case VisibilityNotify
:
9484 /* Someone has changed the keyboard mapping - update the
9486 switch (event
.xmapping
.request
)
9488 case MappingModifier
:
9489 x_find_modifier_meanings (dpyinfo
);
9490 /* This is meant to fall through. */
9491 case MappingKeyboard
:
9492 XRefreshKeyboardMapping (&event
.xmapping
);
9498 #ifdef USE_X_TOOLKIT
9500 XtDispatchEvent (&event
);
9502 #endif /* USE_X_TOOLKIT */
9510 /* On some systems, an X bug causes Emacs to get no more events
9511 when the window is destroyed. Detect that. (1994.) */
9514 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9515 One XNOOP in 100 loops will make Emacs terminate.
9516 B. Bretthauer, 1994 */
9518 if (x_noop_count
>= 100)
9522 if (next_noop_dpyinfo
== 0)
9523 next_noop_dpyinfo
= x_display_list
;
9525 XNoOp (next_noop_dpyinfo
->display
);
9527 /* Each time we get here, cycle through the displays now open. */
9528 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
9532 /* If the focus was just given to an auto-raising frame,
9534 /* ??? This ought to be able to handle more than one such frame. */
9535 if (pending_autoraise_frame
)
9537 x_raise_frame (pending_autoraise_frame
);
9538 pending_autoraise_frame
= 0;
9548 /***********************************************************************
9550 ***********************************************************************/
9552 /* Note if the text cursor of window W has been overwritten by a
9553 drawing operation that outputs N glyphs starting at HPOS in the
9554 line given by output_cursor.vpos. N < 0 means all the rest of the
9555 line after HPOS has been written. */
9558 note_overwritten_text_cursor (w
, hpos
, n
)
9562 if (updated_area
== TEXT_AREA
9563 && output_cursor
.vpos
== w
->phys_cursor
.vpos
9564 && hpos
<= w
->phys_cursor
.hpos
9566 || hpos
+ n
> w
->phys_cursor
.hpos
))
9567 w
->phys_cursor_on_p
= 0;
9571 /* Set clipping for output in glyph row ROW. W is the window in which
9572 we operate. GC is the graphics context to set clipping in.
9573 WHOLE_LINE_P non-zero means include the areas used for truncation
9574 mark display and alike in the clipping rectangle.
9576 ROW may be a text row or, e.g., a mode line. Text rows must be
9577 clipped to the interior of the window dedicated to text display,
9578 mode lines must be clipped to the whole window. */
9581 x_clip_to_row (w
, row
, gc
, whole_line_p
)
9583 struct glyph_row
*row
;
9587 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9588 XRectangle clip_rect
;
9589 int window_x
, window_y
, window_width
, window_height
;
9591 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
9593 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
9594 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
9595 clip_rect
.y
= max (clip_rect
.y
, window_y
);
9596 clip_rect
.width
= window_width
;
9597 clip_rect
.height
= row
->visible_height
;
9599 /* If clipping to the whole line, including trunc marks, extend
9600 the rectangle to the left and increase its width. */
9603 clip_rect
.x
-= FRAME_X_FLAGS_AREA_WIDTH (f
);
9604 clip_rect
.width
+= 2 * FRAME_X_FLAGS_AREA_WIDTH (f
);
9607 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
9611 /* Draw a hollow box cursor on window W in glyph row ROW. */
9614 x_draw_hollow_cursor (w
, row
)
9616 struct glyph_row
*row
;
9618 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9619 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9620 Display
*dpy
= FRAME_X_DISPLAY (f
);
9623 struct glyph
*cursor_glyph
;
9626 /* Compute frame-relative coordinates from window-relative
9628 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9629 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
9630 + row
->ascent
- w
->phys_cursor_ascent
);
9631 h
= row
->height
- 1;
9633 /* Get the glyph the cursor is on. If we can't tell because
9634 the current matrix is invalid or such, give up. */
9635 cursor_glyph
= get_phys_cursor_glyph (w
);
9636 if (cursor_glyph
== NULL
)
9639 /* Compute the width of the rectangle to draw. If on a stretch
9640 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9641 rectangle as wide as the glyph, but use a canonical character
9643 wd
= cursor_glyph
->pixel_width
- 1;
9644 if (cursor_glyph
->type
== STRETCH_GLYPH
9645 && !x_stretch_cursor_p
)
9646 wd
= min (CANON_X_UNIT (f
), wd
);
9648 /* The foreground of cursor_gc is typically the same as the normal
9649 background color, which can cause the cursor box to be invisible. */
9650 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
9651 if (dpyinfo
->scratch_cursor_gc
)
9652 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
9654 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
9655 GCForeground
, &xgcv
);
9656 gc
= dpyinfo
->scratch_cursor_gc
;
9658 /* Set clipping, draw the rectangle, and reset clipping again. */
9659 x_clip_to_row (w
, row
, gc
, 0);
9660 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
9661 XSetClipMask (dpy
, gc
, None
);
9665 /* Draw a bar cursor on window W in glyph row ROW.
9667 Implementation note: One would like to draw a bar cursor with an
9668 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9669 Unfortunately, I didn't find a font yet that has this property set.
9673 x_draw_bar_cursor (w
, row
)
9675 struct glyph_row
*row
;
9677 /* If cursor hpos is out of bounds, don't draw garbage. This can
9678 happen in mini-buffer windows when switching between echo area
9679 glyphs and mini-buffer. */
9680 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9682 struct frame
*f
= XFRAME (w
->frame
);
9683 struct glyph
*cursor_glyph
;
9691 cursor_glyph
= get_phys_cursor_glyph (w
);
9692 if (cursor_glyph
== NULL
)
9695 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
9696 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
9697 xgcv
.graphics_exposures
= 0;
9698 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
9699 dpy
= FRAME_X_DISPLAY (f
);
9700 window
= FRAME_X_WINDOW (f
);
9701 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
9704 XChangeGC (dpy
, gc
, mask
, &xgcv
);
9707 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
9708 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
9711 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9712 x_clip_to_row (w
, row
, gc
, 0);
9713 XFillRectangle (dpy
, window
, gc
,
9715 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
9716 min (cursor_glyph
->pixel_width
,
9717 f
->output_data
.x
->cursor_width
),
9719 XSetClipMask (dpy
, gc
, None
);
9724 /* Clear the cursor of window W to background color, and mark the
9725 cursor as not shown. This is used when the text where the cursor
9726 is is about to be rewritten. */
9732 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
9733 x_update_window_cursor (w
, 0);
9737 /* Draw the cursor glyph of window W in glyph row ROW. See the
9738 comment of x_draw_glyphs for the meaning of HL. */
9741 x_draw_phys_cursor_glyph (w
, row
, hl
)
9743 struct glyph_row
*row
;
9744 enum draw_glyphs_face hl
;
9746 /* If cursor hpos is out of bounds, don't draw garbage. This can
9747 happen in mini-buffer windows when switching between echo area
9748 glyphs and mini-buffer. */
9749 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9750 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
9751 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1, hl
, 0, 0);
9755 /* Erase the image of a cursor of window W from the screen. */
9758 x_erase_phys_cursor (w
)
9761 struct frame
*f
= XFRAME (w
->frame
);
9762 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9763 int hpos
= w
->phys_cursor
.hpos
;
9764 int vpos
= w
->phys_cursor
.vpos
;
9765 int mouse_face_here_p
= 0;
9766 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
9767 struct glyph_row
*cursor_row
;
9768 struct glyph
*cursor_glyph
;
9769 enum draw_glyphs_face hl
;
9771 /* No cursor displayed or row invalidated => nothing to do on the
9773 if (w
->phys_cursor_type
== NO_CURSOR
)
9774 goto mark_cursor_off
;
9776 /* VPOS >= active_glyphs->nrows means that window has been resized.
9777 Don't bother to erase the cursor. */
9778 if (vpos
>= active_glyphs
->nrows
)
9779 goto mark_cursor_off
;
9781 /* If row containing cursor is marked invalid, there is nothing we
9783 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
9784 if (!cursor_row
->enabled_p
)
9785 goto mark_cursor_off
;
9787 /* This can happen when the new row is shorter than the old one.
9788 In this case, either x_draw_glyphs or clear_end_of_line
9789 should have cleared the cursor. Note that we wouldn't be
9790 able to erase the cursor in this case because we don't have a
9791 cursor glyph at hand. */
9792 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
9793 goto mark_cursor_off
;
9795 /* If the cursor is in the mouse face area, redisplay that when
9796 we clear the cursor. */
9797 if (w
== XWINDOW (dpyinfo
->mouse_face_window
)
9798 && (vpos
> dpyinfo
->mouse_face_beg_row
9799 || (vpos
== dpyinfo
->mouse_face_beg_row
9800 && hpos
>= dpyinfo
->mouse_face_beg_col
))
9801 && (vpos
< dpyinfo
->mouse_face_end_row
9802 || (vpos
== dpyinfo
->mouse_face_end_row
9803 && hpos
< dpyinfo
->mouse_face_end_col
))
9804 /* Don't redraw the cursor's spot in mouse face if it is at the
9805 end of a line (on a newline). The cursor appears there, but
9806 mouse highlighting does not. */
9807 && cursor_row
->used
[TEXT_AREA
] > hpos
)
9808 mouse_face_here_p
= 1;
9810 /* Maybe clear the display under the cursor. */
9811 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
9814 int top_line_height
= WINDOW_DISPLAY_TOP_LINE_HEIGHT (w
);
9816 cursor_glyph
= get_phys_cursor_glyph (w
);
9817 if (cursor_glyph
== NULL
)
9818 goto mark_cursor_off
;
9820 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
9822 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
9824 WINDOW_TO_FRAME_PIXEL_Y (w
, max (top_line_height
,
9826 cursor_glyph
->pixel_width
,
9827 cursor_row
->visible_height
,
9831 /* Erase the cursor by redrawing the character underneath it. */
9832 if (mouse_face_here_p
)
9833 hl
= DRAW_MOUSE_FACE
;
9834 else if (cursor_row
->inverse_p
)
9835 hl
= DRAW_INVERSE_VIDEO
;
9837 hl
= DRAW_NORMAL_TEXT
;
9838 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
9841 w
->phys_cursor_on_p
= 0;
9842 w
->phys_cursor_type
= NO_CURSOR
;
9846 /* Display or clear cursor of window W. If ON is zero, clear the
9847 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9848 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9851 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
9853 int on
, hpos
, vpos
, x
, y
;
9855 struct frame
*f
= XFRAME (w
->frame
);
9856 int new_cursor_type
;
9857 struct glyph_matrix
*current_glyphs
;
9858 struct glyph_row
*glyph_row
;
9859 struct glyph
*glyph
;
9861 /* This is pointless on invisible frames, and dangerous on garbaged
9862 windows and frames; in the latter case, the frame or window may
9863 be in the midst of changing its size, and x and y may be off the
9865 if (! FRAME_VISIBLE_P (f
)
9866 || FRAME_GARBAGED_P (f
)
9867 || vpos
>= w
->current_matrix
->nrows
9868 || hpos
>= w
->current_matrix
->matrix_w
)
9871 /* If cursor is off and we want it off, return quickly. */
9872 if (!on
&& !w
->phys_cursor_on_p
)
9875 current_glyphs
= w
->current_matrix
;
9876 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
9877 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
9879 /* If cursor row is not enabled, we don't really know where to
9880 display the cursor. */
9881 if (!glyph_row
->enabled_p
)
9883 w
->phys_cursor_on_p
= 0;
9887 xassert (interrupt_input_blocked
);
9889 /* Set new_cursor_type to the cursor we want to be displayed. In a
9890 mini-buffer window, we want the cursor only to appear if we are
9891 reading input from this window. For the selected window, we want
9892 the cursor type given by the frame parameter. If explicitly
9893 marked off, draw no cursor. In all other cases, we want a hollow
9895 if (w
!= XWINDOW (selected_window
)
9896 || f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
9898 if (MINI_WINDOW_P (w
))
9899 new_cursor_type
= NO_CURSOR
;
9901 new_cursor_type
= HOLLOW_BOX_CURSOR
;
9903 else if (w
->cursor_off_p
)
9904 new_cursor_type
= NO_CURSOR
;
9906 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
9908 /* If cursor is currently being shown and we don't want it to be or
9909 it is in the wrong place, or the cursor type is not what we want,
9911 if (w
->phys_cursor_on_p
9913 || w
->phys_cursor
.x
!= x
9914 || w
->phys_cursor
.y
!= y
9915 || new_cursor_type
!= w
->phys_cursor_type
))
9916 x_erase_phys_cursor (w
);
9918 /* If the cursor is now invisible and we want it to be visible,
9920 if (on
&& !w
->phys_cursor_on_p
)
9922 w
->phys_cursor_ascent
= glyph_row
->ascent
;
9923 w
->phys_cursor_height
= glyph_row
->height
;
9925 /* Set phys_cursor_.* before x_draw_.* is called because some
9926 of them may need the information. */
9927 w
->phys_cursor
.x
= x
;
9928 w
->phys_cursor
.y
= glyph_row
->y
;
9929 w
->phys_cursor
.hpos
= hpos
;
9930 w
->phys_cursor
.vpos
= vpos
;
9931 w
->phys_cursor_type
= new_cursor_type
;
9932 w
->phys_cursor_on_p
= 1;
9934 switch (new_cursor_type
)
9936 case HOLLOW_BOX_CURSOR
:
9937 x_draw_hollow_cursor (w
, glyph_row
);
9940 case FILLED_BOX_CURSOR
:
9941 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
9945 x_draw_bar_cursor (w
, glyph_row
);
9957 if (updating_frame
!= f
)
9958 XFlush (FRAME_X_DISPLAY (f
));
9963 /* Display the cursor on window W, or clear it. X and Y are window
9964 relative pixel coordinates. HPOS and VPOS are glyph matrix
9965 positions. If W is not the selected window, display a hollow
9966 cursor. ON non-zero means display the cursor at X, Y which
9967 correspond to HPOS, VPOS, otherwise it is cleared. */
9970 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
9972 int on
, hpos
, vpos
, x
, y
;
9975 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
9980 /* Display the cursor on window W, or clear it, according to ON_P.
9981 Don't change the cursor's position. */
9984 x_update_cursor (f
, on_p
)
9987 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
9991 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9992 in the window tree rooted at W. */
9995 x_update_cursor_in_window_tree (w
, on_p
)
10001 if (!NILP (w
->hchild
))
10002 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
10003 else if (!NILP (w
->vchild
))
10004 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
10006 x_update_window_cursor (w
, on_p
);
10008 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
10013 /* Switch the display of W's cursor on or off, according to the value
10017 x_update_window_cursor (w
, on
)
10022 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
10023 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
10032 /* Refresh bitmap kitchen sink icon for frame F
10033 when we get an expose event for it. */
10039 /* Normally, the window manager handles this function. */
10042 /* Make the x-window of frame F use the gnu icon bitmap. */
10045 x_bitmap_icon (f
, file
)
10051 if (FRAME_X_WINDOW (f
) == 0)
10054 /* Free up our existing icon bitmap if any. */
10055 if (f
->output_data
.x
->icon_bitmap
> 0)
10056 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10057 f
->output_data
.x
->icon_bitmap
= 0;
10059 if (STRINGP (file
))
10060 bitmap_id
= x_create_bitmap_from_file (f
, file
);
10063 /* Create the GNU bitmap if necessary. */
10064 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
10065 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
10066 = x_create_bitmap_from_data (f
, gnu_bits
,
10067 gnu_width
, gnu_height
);
10069 /* The first time we create the GNU bitmap,
10070 this increments the ref-count one extra time.
10071 As a result, the GNU bitmap is never freed.
10072 That way, we don't have to worry about allocating it again. */
10073 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
10075 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
10078 x_wm_set_icon_pixmap (f
, bitmap_id
);
10079 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
10085 /* Make the x-window of frame F use a rectangle with text.
10086 Use ICON_NAME as the text. */
10089 x_text_icon (f
, icon_name
)
10093 if (FRAME_X_WINDOW (f
) == 0)
10098 XTextProperty text
;
10099 text
.value
= (unsigned char *) icon_name
;
10100 text
.encoding
= XA_STRING
;
10102 text
.nitems
= strlen (icon_name
);
10103 #ifdef USE_X_TOOLKIT
10104 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10106 #else /* not USE_X_TOOLKIT */
10107 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
10108 #endif /* not USE_X_TOOLKIT */
10110 #else /* not HAVE_X11R4 */
10111 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
10112 #endif /* not HAVE_X11R4 */
10114 if (f
->output_data
.x
->icon_bitmap
> 0)
10115 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10116 f
->output_data
.x
->icon_bitmap
= 0;
10117 x_wm_set_icon_pixmap (f
, 0);
10122 #define X_ERROR_MESSAGE_SIZE 200
10124 /* If non-nil, this should be a string.
10125 It means catch X errors and store the error message in this string. */
10127 static Lisp_Object x_error_message_string
;
10129 /* An X error handler which stores the error message in
10130 x_error_message_string. This is called from x_error_handler if
10131 x_catch_errors is in effect. */
10134 x_error_catcher (display
, error
)
10136 XErrorEvent
*error
;
10138 XGetErrorText (display
, error
->error_code
,
10139 XSTRING (x_error_message_string
)->data
,
10140 X_ERROR_MESSAGE_SIZE
);
10143 /* Begin trapping X errors for display DPY. Actually we trap X errors
10144 for all displays, but DPY should be the display you are actually
10147 After calling this function, X protocol errors no longer cause
10148 Emacs to exit; instead, they are recorded in the string
10149 stored in x_error_message_string.
10151 Calling x_check_errors signals an Emacs error if an X error has
10152 occurred since the last call to x_catch_errors or x_check_errors.
10154 Calling x_uncatch_errors resumes the normal error handling. */
10156 void x_check_errors ();
10157 static Lisp_Object
x_catch_errors_unwind ();
10160 x_catch_errors (dpy
)
10163 int count
= specpdl_ptr
- specpdl
;
10165 /* Make sure any errors from previous requests have been dealt with. */
10166 XSync (dpy
, False
);
10168 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
10170 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
10171 XSTRING (x_error_message_string
)->data
[0] = 0;
10176 /* Unbind the binding that we made to check for X errors. */
10179 x_catch_errors_unwind (old_val
)
10180 Lisp_Object old_val
;
10182 x_error_message_string
= old_val
;
10186 /* If any X protocol errors have arrived since the last call to
10187 x_catch_errors or x_check_errors, signal an Emacs error using
10188 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10191 x_check_errors (dpy
, format
)
10195 /* Make sure to catch any errors incurred so far. */
10196 XSync (dpy
, False
);
10198 if (XSTRING (x_error_message_string
)->data
[0])
10199 error (format
, XSTRING (x_error_message_string
)->data
);
10202 /* Nonzero if we had any X protocol errors
10203 since we did x_catch_errors on DPY. */
10206 x_had_errors_p (dpy
)
10209 /* Make sure to catch any errors incurred so far. */
10210 XSync (dpy
, False
);
10212 return XSTRING (x_error_message_string
)->data
[0] != 0;
10215 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10218 x_clear_errors (dpy
)
10221 XSTRING (x_error_message_string
)->data
[0] = 0;
10224 /* Stop catching X protocol errors and let them make Emacs die.
10225 DPY should be the display that was passed to x_catch_errors.
10226 COUNT should be the value that was returned by
10227 the corresponding call to x_catch_errors. */
10230 x_uncatch_errors (dpy
, count
)
10234 unbind_to (count
, Qnil
);
10238 static unsigned int x_wire_count
;
10241 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
10246 /* Handle SIGPIPE, which can happen when the connection to a server
10247 simply goes away. SIGPIPE is handled by x_connection_signal.
10248 Don't need to do anything, because the write which caused the
10249 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10250 which will do the appropriate cleanup for us. */
10253 x_connection_signal (signalnum
) /* If we don't have an argument, */
10254 int signalnum
; /* some compilers complain in signal calls. */
10257 /* USG systems forget handlers when they are used;
10258 must reestablish each time */
10259 signal (signalnum
, x_connection_signal
);
10263 /* Handling X errors. */
10265 /* Handle the loss of connection to display DISPLAY. */
10268 x_connection_closed (display
, error_message
)
10270 char *error_message
;
10272 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
10273 Lisp_Object frame
, tail
;
10275 /* Indicate that this display is dead. */
10277 #ifdef USE_X_TOOLKIT
10278 XtCloseDisplay (display
);
10281 dpyinfo
->display
= 0;
10283 /* First delete frames whose mini-buffers are on frames
10284 that are on the dead display. */
10285 FOR_EACH_FRAME (tail
, frame
)
10287 Lisp_Object minibuf_frame
;
10289 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
10290 if (FRAME_X_P (XFRAME (frame
))
10291 && FRAME_X_P (XFRAME (minibuf_frame
))
10292 && ! EQ (frame
, minibuf_frame
)
10293 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
10294 Fdelete_frame (frame
, Qt
);
10297 /* Now delete all remaining frames on the dead display.
10298 We are now sure none of these is used as the mini-buffer
10299 for another frame that we need to delete. */
10300 FOR_EACH_FRAME (tail
, frame
)
10301 if (FRAME_X_P (XFRAME (frame
))
10302 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
10304 /* Set this to t so that Fdelete_frame won't get confused
10305 trying to find a replacement. */
10306 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
10307 Fdelete_frame (frame
, Qt
);
10311 x_delete_display (dpyinfo
);
10313 if (x_display_list
== 0)
10315 fprintf (stderr
, "%s\n", error_message
);
10316 shut_down_emacs (0, 0, Qnil
);
10320 /* Ordinary stack unwind doesn't deal with these. */
10322 sigunblock (sigmask (SIGIO
));
10324 sigunblock (sigmask (SIGALRM
));
10325 TOTALLY_UNBLOCK_INPUT
;
10327 clear_waiting_for_input ();
10328 error ("%s", error_message
);
10331 /* This is the usual handler for X protocol errors.
10332 It kills all frames on the display that we got the error for.
10333 If that was the only one, it prints an error message and kills Emacs. */
10336 x_error_quitter (display
, error
)
10338 XErrorEvent
*error
;
10340 char buf
[256], buf1
[356];
10342 /* Note that there is no real way portable across R3/R4 to get the
10343 original error handler. */
10345 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
10346 sprintf (buf1
, "X protocol error: %s on protocol request %d",
10347 buf
, error
->request_code
);
10348 x_connection_closed (display
, buf1
);
10351 /* This is the first-level handler for X protocol errors.
10352 It calls x_error_quitter or x_error_catcher. */
10355 x_error_handler (display
, error
)
10357 XErrorEvent
*error
;
10359 if (! NILP (x_error_message_string
))
10360 x_error_catcher (display
, error
);
10362 x_error_quitter (display
, error
);
10366 /* This is the handler for X IO errors, always.
10367 It kills all frames on the display that we lost touch with.
10368 If that was the only one, it prints an error message and kills Emacs. */
10371 x_io_error_quitter (display
)
10376 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
10377 x_connection_closed (display
, buf
);
10381 /* Changing the font of the frame. */
10383 /* Give frame F the font named FONTNAME as its default font, and
10384 return the full name of that font. FONTNAME may be a wildcard
10385 pattern; in that case, we choose some font that fits the pattern.
10386 The return value shows which font we chose. */
10389 x_new_font (f
, fontname
)
10391 register char *fontname
;
10393 struct font_info
*fontp
10394 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
10399 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
10400 f
->output_data
.x
->font_baseline
10401 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
10402 f
->output_data
.x
->fontset
= -1;
10404 /* Compute the scroll bar width in character columns. */
10405 if (f
->scroll_bar_pixel_width
> 0)
10407 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10408 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
10412 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10413 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
10416 /* Now make the frame display the given font. */
10417 if (FRAME_X_WINDOW (f
) != 0)
10419 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
10420 f
->output_data
.x
->font
->fid
);
10421 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
10422 f
->output_data
.x
->font
->fid
);
10423 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
10424 f
->output_data
.x
->font
->fid
);
10426 frame_update_line_height (f
);
10427 x_set_window_size (f
, 0, f
->width
, f
->height
);
10430 /* If we are setting a new frame's font for the first time,
10431 there are no faces yet, so this font's height is the line height. */
10432 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
10434 return build_string (fontp
->full_name
);
10437 /* Give frame F the fontset named FONTSETNAME as its default font, and
10438 return the full name of that fontset. FONTSETNAME may be a wildcard
10439 pattern; in that case, we choose some fontset that fits the pattern.
10440 The return value shows which fontset we chose. */
10443 x_new_fontset (f
, fontsetname
)
10447 int fontset
= fs_query_fontset (f
, fontsetname
);
10448 struct fontset_info
*fontsetp
;
10449 Lisp_Object result
;
10454 if (f
->output_data
.x
->fontset
== fontset
)
10455 /* This fontset is already set in frame F. There's nothing more
10457 return build_string (fontsetname
);
10459 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
10461 if (!fontsetp
->fontname
[CHARSET_ASCII
])
10462 /* This fontset doesn't contain ASCII font. */
10465 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
10467 if (!STRINGP (result
))
10468 /* Can't load ASCII font. */
10471 /* Since x_new_font doesn't update any fontset information, do it now. */
10472 f
->output_data
.x
->fontset
= fontset
;
10473 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
10474 CHARSET_ASCII
, fontsetp
->fontname
[CHARSET_ASCII
], fontset
);
10476 return build_string (fontsetname
);
10479 /* Calculate the absolute position in frame F
10480 from its current recorded position values and gravity. */
10483 x_calc_absolute_position (f
)
10487 int win_x
= 0, win_y
= 0;
10488 int flags
= f
->output_data
.x
->size_hint_flags
;
10491 /* We have nothing to do if the current position
10492 is already for the top-left corner. */
10493 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
10496 #ifdef USE_X_TOOLKIT
10497 this_window
= XtWindow (f
->output_data
.x
->widget
);
10499 this_window
= FRAME_X_WINDOW (f
);
10502 /* Find the position of the outside upper-left corner of
10503 the inner window, with respect to the outer window.
10504 But do this only if we will need the results. */
10505 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
10510 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
10513 x_clear_errors (FRAME_X_DISPLAY (f
));
10514 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
10516 /* From-window, to-window. */
10518 f
->output_data
.x
->parent_desc
,
10520 /* From-position, to-position. */
10521 0, 0, &win_x
, &win_y
,
10523 /* Child of win. */
10525 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
10527 Window newroot
, newparent
= 0xdeadbeef;
10528 Window
*newchildren
;
10531 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
10532 &newparent
, &newchildren
, &nchildren
))
10535 XFree ((char *) newchildren
);
10537 f
->output_data
.x
->parent_desc
= newparent
;
10543 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
10547 /* Treat negative positions as relative to the leftmost bottommost
10548 position that fits on the screen. */
10549 if (flags
& XNegative
)
10550 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
10551 - 2 * f
->output_data
.x
->border_width
- win_x
10553 + f
->output_data
.x
->left_pos
);
10555 if (flags
& YNegative
)
10557 int menubar_height
= 0;
10559 #ifdef USE_X_TOOLKIT
10560 if (f
->output_data
.x
->menubar_widget
)
10562 = (f
->output_data
.x
->menubar_widget
->core
.height
10563 + f
->output_data
.x
->menubar_widget
->core
.border_width
);
10566 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
10567 - 2 * f
->output_data
.x
->border_width
10571 + f
->output_data
.x
->top_pos
);
10574 /* The left_pos and top_pos
10575 are now relative to the top and left screen edges,
10576 so the flags should correspond. */
10577 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10580 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10581 to really change the position, and 0 when calling from
10582 x_make_frame_visible (in that case, XOFF and YOFF are the current
10583 position values). It is -1 when calling from x_set_frame_parameters,
10584 which means, do adjust for borders but don't change the gravity. */
10587 x_set_offset (f
, xoff
, yoff
, change_gravity
)
10589 register int xoff
, yoff
;
10590 int change_gravity
;
10592 int modified_top
, modified_left
;
10594 if (change_gravity
> 0)
10596 f
->output_data
.x
->top_pos
= yoff
;
10597 f
->output_data
.x
->left_pos
= xoff
;
10598 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10600 f
->output_data
.x
->size_hint_flags
|= XNegative
;
10602 f
->output_data
.x
->size_hint_flags
|= YNegative
;
10603 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10605 x_calc_absolute_position (f
);
10608 x_wm_set_size_hint (f
, (long) 0, 0);
10610 modified_left
= f
->output_data
.x
->left_pos
;
10611 modified_top
= f
->output_data
.x
->top_pos
;
10612 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
10613 this seems to be unnecessary and incorrect. rms, 4/17/97. */
10614 /* It is a mystery why we need to add the border_width here
10615 when the frame is already visible, but experiment says we do. */
10616 if (change_gravity
!= 0)
10618 modified_left
+= f
->output_data
.x
->border_width
;
10619 modified_top
+= f
->output_data
.x
->border_width
;
10623 #ifdef USE_X_TOOLKIT
10624 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10625 modified_left
, modified_top
);
10626 #else /* not USE_X_TOOLKIT */
10627 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10628 modified_left
, modified_top
);
10629 #endif /* not USE_X_TOOLKIT */
10633 /* Call this to change the size of frame F's x-window.
10634 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10635 for this size change and subsequent size changes.
10636 Otherwise we leave the window gravity unchanged. */
10639 x_set_window_size (f
, change_gravity
, cols
, rows
)
10641 int change_gravity
;
10644 #ifndef USE_X_TOOLKIT
10645 int pixelwidth
, pixelheight
;
10650 #ifdef USE_X_TOOLKIT
10652 /* The x and y position of the widget is clobbered by the
10653 call to XtSetValues within EmacsFrameSetCharSize.
10654 This is a real kludge, but I don't understand Xt so I can't
10655 figure out a correct fix. Can anyone else tell me? -- rms. */
10656 int xpos
= f
->output_data
.x
->widget
->core
.x
;
10657 int ypos
= f
->output_data
.x
->widget
->core
.y
;
10658 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
10659 f
->output_data
.x
->widget
->core
.x
= xpos
;
10660 f
->output_data
.x
->widget
->core
.y
= ypos
;
10663 #else /* not USE_X_TOOLKIT */
10665 check_frame_size (f
, &rows
, &cols
);
10666 f
->output_data
.x
->vertical_scroll_bar_extra
10667 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
10669 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
10670 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
10671 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
10672 f
->output_data
.x
->flags_areas_extra
10673 = 2 * FRAME_FLAGS_AREA_WIDTH (f
);
10674 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
10675 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
10677 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10678 x_wm_set_size_hint (f
, (long) 0, 0);
10680 XSync (FRAME_X_DISPLAY (f
), False
);
10681 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10682 pixelwidth
, pixelheight
);
10684 /* Now, strictly speaking, we can't be sure that this is accurate,
10685 but the window manager will get around to dealing with the size
10686 change request eventually, and we'll hear how it went when the
10687 ConfigureNotify event gets here.
10689 We could just not bother storing any of this information here,
10690 and let the ConfigureNotify event set everything up, but that
10691 might be kind of confusing to the lisp code, since size changes
10692 wouldn't be reported in the frame parameters until some random
10693 point in the future when the ConfigureNotify event arrives. */
10694 change_frame_size (f
, rows
, cols
, 0, 0);
10695 PIXEL_WIDTH (f
) = pixelwidth
;
10696 PIXEL_HEIGHT (f
) = pixelheight
;
10698 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10699 receive in the ConfigureNotify event; if we get what we asked
10700 for, then the event won't cause the screen to become garbaged, so
10701 we have to make sure to do it here. */
10702 SET_FRAME_GARBAGED (f
);
10704 XFlush (FRAME_X_DISPLAY (f
));
10706 #endif /* not USE_X_TOOLKIT */
10708 /* If cursor was outside the new size, mark it as off. */
10709 mark_window_cursors_off (XWINDOW (f
->root_window
));
10711 /* Clear out any recollection of where the mouse highlighting was,
10712 since it might be in a place that's outside the new frame size.
10713 Actually checking whether it is outside is a pain in the neck,
10714 so don't try--just let the highlighting be done afresh with new size. */
10715 cancel_mouse_face (f
);
10720 /* Mouse warping. */
10723 x_set_mouse_position (f
, x
, y
)
10729 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
10730 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
10732 if (pix_x
< 0) pix_x
= 0;
10733 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
10735 if (pix_y
< 0) pix_y
= 0;
10736 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
10740 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
10741 0, 0, 0, 0, pix_x
, pix_y
);
10745 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
10748 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
10754 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
10755 0, 0, 0, 0, pix_x
, pix_y
);
10759 /* focus shifting, raising and lowering. */
10762 x_focus_on_frame (f
)
10765 #if 0 /* This proves to be unpleasant. */
10769 /* I don't think that the ICCCM allows programs to do things like this
10770 without the interaction of the window manager. Whatever you end up
10771 doing with this code, do it to x_unfocus_frame too. */
10772 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10773 RevertToPointerRoot
, CurrentTime
);
10778 x_unfocus_frame (f
)
10782 /* Look at the remarks in x_focus_on_frame. */
10783 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
10784 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
10785 RevertToPointerRoot
, CurrentTime
);
10789 /* Raise frame F. */
10795 if (f
->async_visible
)
10798 #ifdef USE_X_TOOLKIT
10799 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
10800 #else /* not USE_X_TOOLKIT */
10801 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10802 #endif /* not USE_X_TOOLKIT */
10803 XFlush (FRAME_X_DISPLAY (f
));
10808 /* Lower frame F. */
10814 if (f
->async_visible
)
10817 #ifdef USE_X_TOOLKIT
10818 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
10819 #else /* not USE_X_TOOLKIT */
10820 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10821 #endif /* not USE_X_TOOLKIT */
10822 XFlush (FRAME_X_DISPLAY (f
));
10828 XTframe_raise_lower (f
, raise_flag
)
10838 /* Change of visibility. */
10840 /* This tries to wait until the frame is really visible.
10841 However, if the window manager asks the user where to position
10842 the frame, this will return before the user finishes doing that.
10843 The frame will not actually be visible at that time,
10844 but it will become visible later when the window manager
10845 finishes with it. */
10848 x_make_frame_visible (f
)
10852 int original_top
, original_left
;
10856 type
= x_icon_type (f
);
10858 x_bitmap_icon (f
, type
);
10860 if (! FRAME_VISIBLE_P (f
))
10862 /* We test FRAME_GARBAGED_P here to make sure we don't
10863 call x_set_offset a second time
10864 if we get to x_make_frame_visible a second time
10865 before the window gets really visible. */
10866 if (! FRAME_ICONIFIED_P (f
)
10867 && ! f
->output_data
.x
->asked_for_visible
)
10868 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
10870 f
->output_data
.x
->asked_for_visible
= 1;
10872 if (! EQ (Vx_no_window_manager
, Qt
))
10873 x_wm_set_window_state (f
, NormalState
);
10874 #ifdef USE_X_TOOLKIT
10875 /* This was XtPopup, but that did nothing for an iconified frame. */
10876 XtMapWidget (f
->output_data
.x
->widget
);
10877 #else /* not USE_X_TOOLKIT */
10878 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10879 #endif /* not USE_X_TOOLKIT */
10880 #if 0 /* This seems to bring back scroll bars in the wrong places
10881 if the window configuration has changed. They seem
10882 to come back ok without this. */
10883 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
10884 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
10888 XFlush (FRAME_X_DISPLAY (f
));
10890 /* Synchronize to ensure Emacs knows the frame is visible
10891 before we do anything else. We do this loop with input not blocked
10892 so that incoming events are handled. */
10895 int count
= input_signal_count
;
10896 /* This must be before UNBLOCK_INPUT
10897 since events that arrive in response to the actions above
10898 will set it when they are handled. */
10899 int previously_visible
= f
->output_data
.x
->has_been_visible
;
10901 original_left
= f
->output_data
.x
->left_pos
;
10902 original_top
= f
->output_data
.x
->top_pos
;
10904 /* This must come after we set COUNT. */
10907 /* We unblock here so that arriving X events are processed. */
10909 /* Now move the window back to where it was "supposed to be".
10910 But don't do it if the gravity is negative.
10911 When the gravity is negative, this uses a position
10912 that is 3 pixels too low. Perhaps that's really the border width.
10914 Don't do this if the window has never been visible before,
10915 because the window manager may choose the position
10916 and we don't want to override it. */
10918 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
10919 && f
->output_data
.x
->win_gravity
== NorthWestGravity
10920 && previously_visible
)
10924 unsigned int width
, height
, border
, depth
;
10928 /* On some window managers (such as FVWM) moving an existing
10929 window, even to the same place, causes the window manager
10930 to introduce an offset. This can cause the window to move
10931 to an unexpected location. Check the geometry (a little
10932 slow here) and then verify that the window is in the right
10933 place. If the window is not in the right place, move it
10934 there, and take the potential window manager hit. */
10935 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10936 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
10938 if (original_left
!= x
|| original_top
!= y
)
10939 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
10940 original_left
, original_top
);
10945 XSETFRAME (frame
, f
);
10950 /* Once we have handled input events,
10951 we should have received the MapNotify if one is coming.
10952 So if we have not got it yet, stop looping.
10953 Some window managers make their own decisions
10954 about visibility. */
10955 if (input_signal_count
!= count
)
10957 /* Machines that do polling rather than SIGIO have been observed
10958 to go into a busy-wait here. So we'll fake an alarm signal
10959 to let the handler know that there's something to be read.
10960 We used to raise a real alarm, but it seems that the handler
10961 isn't always enabled here. This is probably a bug. */
10962 if (input_polling_used ())
10964 /* It could be confusing if a real alarm arrives while processing
10965 the fake one. Turn it off and let the handler reset it. */
10967 input_poll_signal (0);
10969 /* Once we have handled input events,
10970 we should have received the MapNotify if one is coming.
10971 So if we have not got it yet, stop looping.
10972 Some window managers make their own decisions
10973 about visibility. */
10974 if (input_signal_count
!= count
)
10977 FRAME_SAMPLE_VISIBILITY (f
);
10981 /* Change from mapped state to withdrawn state. */
10983 /* Make the frame visible (mapped and not iconified). */
10986 x_make_frame_invisible (f
)
10991 #ifdef USE_X_TOOLKIT
10992 /* Use the frame's outermost window, not the one we normally draw on. */
10993 window
= XtWindow (f
->output_data
.x
->widget
);
10994 #else /* not USE_X_TOOLKIT */
10995 window
= FRAME_X_WINDOW (f
);
10996 #endif /* not USE_X_TOOLKIT */
10998 /* Don't keep the highlight on an invisible frame. */
10999 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11000 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11002 #if 0/* This might add unreliability; I don't trust it -- rms. */
11003 if (! f
->async_visible
&& ! f
->async_iconified
)
11009 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11010 that the current position of the window is user-specified, rather than
11011 program-specified, so that when the window is mapped again, it will be
11012 placed at the same location, without forcing the user to position it
11013 by hand again (they have already done that once for this window.) */
11014 x_wm_set_size_hint (f
, (long) 0, 1);
11018 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11019 DefaultScreen (FRAME_X_DISPLAY (f
))))
11021 UNBLOCK_INPUT_RESIGNAL
;
11022 error ("Can't notify window manager of window withdrawal");
11024 #else /* ! defined (HAVE_X11R4) */
11026 /* Tell the window manager what we're going to do. */
11027 if (! EQ (Vx_no_window_manager
, Qt
))
11031 unmap
.xunmap
.type
= UnmapNotify
;
11032 unmap
.xunmap
.window
= window
;
11033 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
11034 unmap
.xunmap
.from_configure
= False
;
11035 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11036 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11038 SubstructureRedirectMaskSubstructureNotifyMask
,
11041 UNBLOCK_INPUT_RESIGNAL
;
11042 error ("Can't notify window manager of withdrawal");
11046 /* Unmap the window ourselves. Cheeky! */
11047 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
11048 #endif /* ! defined (HAVE_X11R4) */
11050 /* We can't distinguish this from iconification
11051 just by the event that we get from the server.
11052 So we can't win using the usual strategy of letting
11053 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11054 and synchronize with the server to make sure we agree. */
11056 FRAME_ICONIFIED_P (f
) = 0;
11057 f
->async_visible
= 0;
11058 f
->async_iconified
= 0;
11065 /* Change window state from mapped to iconified. */
11068 x_iconify_frame (f
)
11074 /* Don't keep the highlight on an invisible frame. */
11075 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11076 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11078 if (f
->async_iconified
)
11083 FRAME_SAMPLE_VISIBILITY (f
);
11085 type
= x_icon_type (f
);
11087 x_bitmap_icon (f
, type
);
11089 #ifdef USE_X_TOOLKIT
11091 if (! FRAME_VISIBLE_P (f
))
11093 if (! EQ (Vx_no_window_manager
, Qt
))
11094 x_wm_set_window_state (f
, IconicState
);
11095 /* This was XtPopup, but that did nothing for an iconified frame. */
11096 XtMapWidget (f
->output_data
.x
->widget
);
11097 /* The server won't give us any event to indicate
11098 that an invisible frame was changed to an icon,
11099 so we have to record it here. */
11102 f
->async_iconified
= 1;
11103 f
->async_visible
= 0;
11108 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11109 XtWindow (f
->output_data
.x
->widget
),
11110 DefaultScreen (FRAME_X_DISPLAY (f
)));
11114 error ("Can't notify window manager of iconification");
11116 f
->async_iconified
= 1;
11117 f
->async_visible
= 0;
11121 XFlush (FRAME_X_DISPLAY (f
));
11123 #else /* not USE_X_TOOLKIT */
11125 /* Make sure the X server knows where the window should be positioned,
11126 in case the user deiconifies with the window manager. */
11127 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
11128 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11130 /* Since we don't know which revision of X we're running, we'll use both
11131 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11133 /* X11R4: send a ClientMessage to the window manager using the
11134 WM_CHANGE_STATE type. */
11138 message
.xclient
.window
= FRAME_X_WINDOW (f
);
11139 message
.xclient
.type
= ClientMessage
;
11140 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
11141 message
.xclient
.format
= 32;
11142 message
.xclient
.data
.l
[0] = IconicState
;
11144 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11145 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11147 SubstructureRedirectMask
| SubstructureNotifyMask
,
11150 UNBLOCK_INPUT_RESIGNAL
;
11151 error ("Can't notify window manager of iconification");
11155 /* X11R3: set the initial_state field of the window manager hints to
11157 x_wm_set_window_state (f
, IconicState
);
11159 if (!FRAME_VISIBLE_P (f
))
11161 /* If the frame was withdrawn, before, we must map it. */
11162 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11165 f
->async_iconified
= 1;
11166 f
->async_visible
= 0;
11168 XFlush (FRAME_X_DISPLAY (f
));
11170 #endif /* not USE_X_TOOLKIT */
11173 /* Destroy the X window of frame F. */
11176 x_destroy_window (f
)
11179 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11183 /* If a display connection is dead, don't try sending more
11184 commands to the X server. */
11185 if (dpyinfo
->display
!= 0)
11187 if (f
->output_data
.x
->icon_desc
!= 0)
11188 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
11192 XDestroyIC (FRAME_XIC (f
));
11193 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11194 /* This line causes crashes on Solaris with Openwin,
11195 due to an apparent bug in XCloseIM.
11196 X11R6 seems not to have the bug. */
11197 XCloseIM (FRAME_XIM (f
));
11201 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
11202 #ifdef USE_X_TOOLKIT
11203 if (f
->output_data
.x
->widget
)
11204 XtDestroyWidget (f
->output_data
.x
->widget
);
11205 free_frame_menubar (f
);
11206 #endif /* USE_X_TOOLKIT */
11208 free_frame_faces (f
);
11209 XFlush (FRAME_X_DISPLAY (f
));
11212 if (f
->output_data
.x
->saved_menu_event
)
11213 xfree (f
->output_data
.x
->saved_menu_event
);
11215 xfree (f
->output_data
.x
);
11216 f
->output_data
.x
= 0;
11217 if (f
== dpyinfo
->x_focus_frame
)
11218 dpyinfo
->x_focus_frame
= 0;
11219 if (f
== dpyinfo
->x_focus_event_frame
)
11220 dpyinfo
->x_focus_event_frame
= 0;
11221 if (f
== dpyinfo
->x_highlight_frame
)
11222 dpyinfo
->x_highlight_frame
= 0;
11224 dpyinfo
->reference_count
--;
11226 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11228 dpyinfo
->mouse_face_beg_row
11229 = dpyinfo
->mouse_face_beg_col
= -1;
11230 dpyinfo
->mouse_face_end_row
11231 = dpyinfo
->mouse_face_end_col
= -1;
11232 dpyinfo
->mouse_face_window
= Qnil
;
11233 dpyinfo
->mouse_face_deferred_gc
= 0;
11234 dpyinfo
->mouse_face_mouse_frame
= 0;
11240 /* Setting window manager hints. */
11242 /* Set the normal size hints for the window manager, for frame F.
11243 FLAGS is the flags word to use--or 0 meaning preserve the flags
11244 that the window now has.
11245 If USER_POSITION is nonzero, we set the USPosition
11246 flag (this is useful when FLAGS is 0). */
11249 x_wm_set_size_hint (f
, flags
, user_position
)
11254 XSizeHints size_hints
;
11256 #ifdef USE_X_TOOLKIT
11259 Dimension widget_width
, widget_height
;
11260 Window window
= XtWindow (f
->output_data
.x
->widget
);
11261 #else /* not USE_X_TOOLKIT */
11262 Window window
= FRAME_X_WINDOW (f
);
11263 #endif /* not USE_X_TOOLKIT */
11265 /* Setting PMaxSize caused various problems. */
11266 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
11268 size_hints
.x
= f
->output_data
.x
->left_pos
;
11269 size_hints
.y
= f
->output_data
.x
->top_pos
;
11271 #ifdef USE_X_TOOLKIT
11272 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
11273 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
11274 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
11275 size_hints
.height
= widget_height
;
11276 size_hints
.width
= widget_width
;
11277 #else /* not USE_X_TOOLKIT */
11278 size_hints
.height
= PIXEL_HEIGHT (f
);
11279 size_hints
.width
= PIXEL_WIDTH (f
);
11280 #endif /* not USE_X_TOOLKIT */
11282 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
11283 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
11284 size_hints
.max_width
11285 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
11286 size_hints
.max_height
11287 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
11289 /* Calculate the base and minimum sizes.
11291 (When we use the X toolkit, we don't do it here.
11292 Instead we copy the values that the widgets are using, below.) */
11293 #ifndef USE_X_TOOLKIT
11295 int base_width
, base_height
;
11296 int min_rows
= 0, min_cols
= 0;
11298 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
11299 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
11301 check_frame_size (f
, &min_rows
, &min_cols
);
11303 /* The window manager uses the base width hints to calculate the
11304 current number of rows and columns in the frame while
11305 resizing; min_width and min_height aren't useful for this
11306 purpose, since they might not give the dimensions for a
11307 zero-row, zero-column frame.
11309 We use the base_width and base_height members if we have
11310 them; otherwise, we set the min_width and min_height members
11311 to the size for a zero x zero frame. */
11314 size_hints
.flags
|= PBaseSize
;
11315 size_hints
.base_width
= base_width
;
11316 size_hints
.base_height
= base_height
;
11317 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
11318 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
11320 size_hints
.min_width
= base_width
;
11321 size_hints
.min_height
= base_height
;
11325 /* If we don't need the old flags, we don't need the old hint at all. */
11328 size_hints
.flags
|= flags
;
11331 #endif /* not USE_X_TOOLKIT */
11334 XSizeHints hints
; /* Sometimes I hate X Windows... */
11335 long supplied_return
;
11339 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
11342 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
11345 #ifdef USE_X_TOOLKIT
11346 size_hints
.base_height
= hints
.base_height
;
11347 size_hints
.base_width
= hints
.base_width
;
11348 size_hints
.min_height
= hints
.min_height
;
11349 size_hints
.min_width
= hints
.min_width
;
11353 size_hints
.flags
|= flags
;
11358 if (hints
.flags
& PSize
)
11359 size_hints
.flags
|= PSize
;
11360 if (hints
.flags
& PPosition
)
11361 size_hints
.flags
|= PPosition
;
11362 if (hints
.flags
& USPosition
)
11363 size_hints
.flags
|= USPosition
;
11364 if (hints
.flags
& USSize
)
11365 size_hints
.flags
|= USSize
;
11369 #ifndef USE_X_TOOLKIT
11374 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
11375 size_hints
.flags
|= PWinGravity
;
11379 size_hints
.flags
&= ~ PPosition
;
11380 size_hints
.flags
|= USPosition
;
11382 #endif /* PWinGravity */
11385 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11387 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11391 /* Used for IconicState or NormalState */
11394 x_wm_set_window_state (f
, state
)
11398 #ifdef USE_X_TOOLKIT
11401 XtSetArg (al
[0], XtNinitialState
, state
);
11402 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11403 #else /* not USE_X_TOOLKIT */
11404 Window window
= FRAME_X_WINDOW (f
);
11406 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
11407 f
->output_data
.x
->wm_hints
.initial_state
= state
;
11409 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11410 #endif /* not USE_X_TOOLKIT */
11414 x_wm_set_icon_pixmap (f
, pixmap_id
)
11418 Pixmap icon_pixmap
;
11420 #ifndef USE_X_TOOLKIT
11421 Window window
= FRAME_X_WINDOW (f
);
11426 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
11427 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
11431 /* It seems there is no way to turn off use of an icon pixmap.
11432 The following line does it, only if no icon has yet been created,
11433 for some window managers. But with mwm it crashes.
11434 Some people say it should clear the IconPixmapHint bit in this case,
11435 but that doesn't work, and the X consortium said it isn't the
11436 right thing at all. Since there is no way to win,
11437 best to explicitly give up. */
11439 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
11445 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11449 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
11450 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11453 #else /* not USE_X_TOOLKIT */
11455 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
11456 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11458 #endif /* not USE_X_TOOLKIT */
11462 x_wm_set_icon_position (f
, icon_x
, icon_y
)
11464 int icon_x
, icon_y
;
11466 #ifdef USE_X_TOOLKIT
11467 Window window
= XtWindow (f
->output_data
.x
->widget
);
11469 Window window
= FRAME_X_WINDOW (f
);
11472 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
11473 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
11474 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
11476 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11480 /***********************************************************************
11482 ***********************************************************************/
11484 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
11487 x_get_font_info (f
, font_idx
)
11491 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
11495 /* Return a list of names of available fonts matching PATTERN on frame
11496 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11497 to be listed. Frame F NULL means we have not yet created any
11498 frame on X, and consult the first display in x_display_list.
11499 MAXNAMES sets a limit on how many fonts to match. */
11502 x_list_fonts (f
, pattern
, size
, maxnames
)
11504 Lisp_Object pattern
;
11508 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
11509 Lisp_Object tem
, second_best
;
11510 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
11511 int try_XLoadQueryFont
= 0;
11514 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
11515 if (NILP (patterns
))
11516 patterns
= Fcons (pattern
, Qnil
);
11518 if (maxnames
== 1 && !size
)
11519 /* We can return any single font matching PATTERN. */
11520 try_XLoadQueryFont
= 1;
11522 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
11527 pattern
= XCONS (patterns
)->car
;
11528 /* See if we cached the result for this particular query.
11529 The cache is an alist of the form:
11530 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11532 if (f
&& (tem
= XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
,
11533 key
= Fcons (pattern
, make_number (maxnames
)),
11534 !NILP (list
= Fassoc (key
, tem
))))
11536 list
= Fcdr_safe (list
);
11537 /* We have a cashed list. Don't have to get the list again. */
11541 /* At first, put PATTERN in the cache. */
11544 count
= x_catch_errors (dpy
);
11546 if (try_XLoadQueryFont
)
11549 unsigned long value
;
11551 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
11552 if (x_had_errors_p (dpy
))
11554 /* This error is perhaps due to insufficient memory on X
11555 server. Let's just ignore it. */
11557 x_clear_errors (dpy
);
11561 && XGetFontProperty (font
, XA_FONT
, &value
))
11563 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
11564 int len
= strlen (name
);
11567 /* If DXPC (a Differential X Protocol Compressor)
11568 Ver.3.7 is running, XGetAtomName will return null
11569 string. We must avoid such a name. */
11571 try_XLoadQueryFont
= 0;
11575 names
= (char **) alloca (sizeof (char *));
11576 /* Some systems only allow alloca assigned to a
11578 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
11579 bcopy (name
, names
[0], len
+ 1);
11584 try_XLoadQueryFont
= 0;
11587 XFreeFont (dpy
, font
);
11590 if (!try_XLoadQueryFont
)
11592 /* We try at least 10 fonts because XListFonts will return
11593 auto-scaled fonts at the head. */
11594 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
11596 if (x_had_errors_p (dpy
))
11598 /* This error is perhaps due to insufficient memory on X
11599 server. Let's just ignore it. */
11601 x_clear_errors (dpy
);
11605 x_uncatch_errors (dpy
, count
);
11612 /* Make a list of all the fonts we got back.
11613 Store that in the font cache for the display. */
11614 for (i
= 0; i
< num_fonts
; i
++)
11617 char *p
= names
[i
];
11618 int average_width
= -1, dashes
= 0;
11620 /* Count the number of dashes in NAMES[I]. If there are
11621 14 dashes, and the field value following 12th dash
11622 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
11623 is usually too ugly to be used for editing. Let's
11629 if (dashes
== 7) /* PIXEL_SIZE field */
11631 else if (dashes
== 12) /* AVERAGE_WIDTH field */
11632 average_width
= atoi (p
);
11634 if (dashes
< 14 || average_width
!= 0)
11636 tem
= build_string (names
[i
]);
11637 if (NILP (Fassoc (tem
, list
)))
11639 if (STRINGP (Vx_pixel_size_width_font_regexp
)
11640 && ((fast_c_string_match_ignore_case
11641 (Vx_pixel_size_width_font_regexp
, names
[i
]))
11643 /* We can set the value of PIXEL_SIZE to the
11644 width of this font. */
11645 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
11647 /* For the moment, width is not known. */
11648 list
= Fcons (Fcons (tem
, Qnil
), list
);
11652 if (!try_XLoadQueryFont
)
11653 XFreeFontNames (names
);
11656 /* Now store the result in the cache. */
11658 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
11659 = Fcons (Fcons (key
, list
),
11660 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
11663 if (NILP (list
)) continue; /* Try the remaining alternatives. */
11665 newlist
= second_best
= Qnil
;
11666 /* Make a list of the fonts that have the right width. */
11667 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
11671 tem
= XCONS (list
)->car
;
11673 if (!CONSP (tem
) || NILP (XCONS (tem
)->car
))
11677 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
11681 if (!INTEGERP (XCONS (tem
)->cdr
))
11683 /* Since we have not yet known the size of this font, we
11684 must try slow function call XLoadQueryFont. */
11685 XFontStruct
*thisinfo
;
11688 count
= x_catch_errors (dpy
);
11689 thisinfo
= XLoadQueryFont (dpy
,
11690 XSTRING (XCONS (tem
)->car
)->data
);
11691 if (x_had_errors_p (dpy
))
11693 /* This error is perhaps due to insufficient memory on X
11694 server. Let's just ignore it. */
11696 x_clear_errors (dpy
);
11698 x_uncatch_errors (dpy
, count
);
11704 = (thisinfo
->min_bounds
.width
== 0
11706 : make_number (thisinfo
->max_bounds
.width
));
11707 XFreeFont (dpy
, thisinfo
);
11710 /* For unknown reason, the previous call of XListFont had
11711 returned a font which can't be opened. Record the size
11712 as 0 not to try to open it again. */
11713 XCONS (tem
)->cdr
= make_number (0);
11716 found_size
= XINT (XCONS (tem
)->cdr
);
11717 if (found_size
== size
)
11718 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
11719 else if (found_size
> 0)
11721 if (NILP (second_best
))
11723 else if (found_size
< size
)
11725 if (XINT (XCONS (second_best
)->cdr
) > size
11726 || XINT (XCONS (second_best
)->cdr
) < found_size
)
11731 if (XINT (XCONS (second_best
)->cdr
) > size
11732 && XINT (XCONS (second_best
)->cdr
) > found_size
)
11737 if (!NILP (newlist
))
11739 else if (!NILP (second_best
))
11741 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
11752 /* Check that FONT is valid on frame F. It is if it can be found in F's
11756 x_check_font (f
, font
)
11761 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11763 xassert (font
!= NULL
);
11765 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11766 if (dpyinfo
->font_table
[i
].name
11767 && font
== dpyinfo
->font_table
[i
].font
)
11770 xassert (i
< dpyinfo
->n_fonts
);
11773 #endif /* GLYPH_DEBUG != 0 */
11775 /* Set *W to the minimum width, *H to the minimum font height of FONT.
11776 Note: There are (broken) X fonts out there with invalid XFontStruct
11777 min_bounds contents. For example, handa@etl.go.jp reports that
11778 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
11779 have font->min_bounds.width == 0. */
11782 x_font_min_bounds (font
, w
, h
)
11786 *h
= FONT_HEIGHT (font
);
11787 *w
= font
->min_bounds
.width
;
11789 /* Try to handle the case where FONT->min_bounds has invalid
11790 contents. Since the only font known to have invalid min_bounds
11791 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
11793 *w
= font
->max_bounds
.width
;
11797 /* Compute the smallest character width and smallest font height over
11798 all fonts available on frame F. Set the members smallest_char_width
11799 and smallest_font_height in F's x_display_info structure to
11800 the values computed. Value is non-zero if smallest_font_height or
11801 smallest_char_width become smaller than they were before. */
11804 x_compute_min_glyph_bounds (f
)
11808 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11810 int old_width
= dpyinfo
->smallest_char_width
;
11811 int old_height
= dpyinfo
->smallest_font_height
;
11813 dpyinfo
->smallest_font_height
= 100000;
11814 dpyinfo
->smallest_char_width
= 100000;
11816 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
11817 if (dpyinfo
->font_table
[i
].name
)
11819 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
11822 font
= (XFontStruct
*) fontp
->font
;
11823 xassert (font
!= (XFontStruct
*) ~0);
11824 x_font_min_bounds (font
, &w
, &h
);
11826 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
11827 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
11830 xassert (dpyinfo
->smallest_char_width
> 0
11831 && dpyinfo
->smallest_font_height
> 0);
11833 return (dpyinfo
->n_fonts
== 1
11834 || dpyinfo
->smallest_char_width
< old_width
11835 || dpyinfo
->smallest_font_height
< old_height
);
11839 /* Load font named FONTNAME of the size SIZE for frame F, and return a
11840 pointer to the structure font_info while allocating it dynamically.
11841 If SIZE is 0, load any size of font.
11842 If loading is failed, return NULL. */
11845 x_load_font (f
, fontname
, size
)
11847 register char *fontname
;
11850 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11851 Lisp_Object font_names
;
11854 /* Get a list of all the fonts that match this name. Once we
11855 have a list of matching fonts, we compare them against the fonts
11856 we already have by comparing names. */
11857 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
11859 if (!NILP (font_names
))
11864 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11865 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
11866 if (dpyinfo
->font_table
[i
].name
11867 && (!strcmp (dpyinfo
->font_table
[i
].name
,
11868 XSTRING (XCONS (tail
)->car
)->data
)
11869 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
11870 XSTRING (XCONS (tail
)->car
)->data
)))
11871 return (dpyinfo
->font_table
+ i
);
11874 /* Load the font and add it to the table. */
11878 struct font_info
*fontp
;
11879 unsigned long value
;
11882 /* If we have found fonts by x_list_font, load one of them. If
11883 not, we still try to load a font by the name given as FONTNAME
11884 because XListFonts (called in x_list_font) of some X server has
11885 a bug of not finding a font even if the font surely exists and
11886 is loadable by XLoadQueryFont. */
11887 if (size
> 0 && !NILP (font_names
))
11888 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
11891 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
11892 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
11893 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
11895 /* This error is perhaps due to insufficient memory on X
11896 server. Let's just ignore it. */
11898 x_clear_errors (FRAME_X_DISPLAY (f
));
11900 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
11905 /* Find a free slot in the font table. */
11906 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
11907 if (dpyinfo
->font_table
[i
].name
== NULL
)
11910 /* If no free slot found, maybe enlarge the font table. */
11911 if (i
== dpyinfo
->n_fonts
11912 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
11915 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
11916 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
11917 dpyinfo
->font_table
11918 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
11921 fontp
= dpyinfo
->font_table
+ i
;
11922 if (i
== dpyinfo
->n_fonts
)
11923 ++dpyinfo
->n_fonts
;
11925 /* Now fill in the slots of *FONTP. */
11927 fontp
->font
= font
;
11928 fontp
->font_idx
= i
;
11929 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
11930 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
11932 /* Try to get the full name of FONT. Put it in FULL_NAME. */
11934 if (XGetFontProperty (font
, XA_FONT
, &value
))
11936 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
11940 /* Count the number of dashes in the "full name".
11941 If it is too few, this isn't really the font's full name,
11943 In X11R4, the fonts did not come with their canonical names
11954 full_name
= (char *) xmalloc (p
- name
+ 1);
11955 bcopy (name
, full_name
, p
- name
+ 1);
11961 if (full_name
!= 0)
11962 fontp
->full_name
= full_name
;
11964 fontp
->full_name
= fontp
->name
;
11966 fontp
->size
= font
->max_bounds
.width
;
11967 fontp
->height
= FONT_HEIGHT (font
);
11969 /* For some font, ascent and descent in max_bounds field is
11970 larger than the above value. */
11971 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
11972 if (max_height
> fontp
->height
)
11973 fontp
->height
= max_height
;
11976 if (NILP (font_names
))
11978 /* We come here because of a bug of XListFonts mentioned at
11979 the head of this block. Let's store this information in
11980 the cache for x_list_fonts. */
11981 Lisp_Object lispy_name
= build_string (fontname
);
11982 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
11984 XCONS (dpyinfo
->name_list_element
)->cdr
11985 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
11986 Fcons (Fcons (lispy_full_name
,
11987 make_number (fontp
->size
)),
11989 XCONS (dpyinfo
->name_list_element
)->cdr
);
11991 XCONS (dpyinfo
->name_list_element
)->cdr
11992 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
11993 Fcons (Fcons (lispy_full_name
,
11994 make_number (fontp
->size
)),
11996 XCONS (dpyinfo
->name_list_element
)->cdr
);
11999 /* The slot `encoding' specifies how to map a character
12000 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12001 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12002 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12003 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12004 2:0xA020..0xFF7F). For the moment, we don't know which charset
12005 uses this font. So, we set information in fontp->encoding[1]
12006 which is never used by any charset. If mapping can't be
12007 decided, set FONT_ENCODING_NOT_DECIDED. */
12009 = (font
->max_byte1
== 0
12011 ? (font
->min_char_or_byte2
< 0x80
12012 ? (font
->max_char_or_byte2
< 0x80
12013 ? 0 /* 0x20..0x7F */
12014 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
12015 : 1) /* 0xA0..0xFF */
12017 : (font
->min_byte1
< 0x80
12018 ? (font
->max_byte1
< 0x80
12019 ? (font
->min_char_or_byte2
< 0x80
12020 ? (font
->max_char_or_byte2
< 0x80
12021 ? 0 /* 0x2020..0x7F7F */
12022 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
12023 : 3) /* 0x20A0..0x7FFF */
12024 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
12025 : (font
->min_char_or_byte2
< 0x80
12026 ? (font
->max_char_or_byte2
< 0x80
12027 ? 2 /* 0xA020..0xFF7F */
12028 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
12029 : 1))); /* 0xA0A0..0xFFFF */
12031 fontp
->baseline_offset
12032 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
12033 ? (long) value
: 0);
12034 fontp
->relative_compose
12035 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
12036 ? (long) value
: 0);
12037 fontp
->default_ascent
12038 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
12039 ? (long) value
: 0);
12041 /* Set global flag fonts_changed_p to non-zero if the font loaded
12042 has a character with a smaller width than any other character
12043 before, or if the font loaded has a smalle>r height than any
12044 other font loaded before. If this happens, it will make a
12045 glyph matrix reallocation necessary. */
12046 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
12053 /* Return a pointer to struct font_info of a font named FONTNAME for
12054 frame F. If no such font is loaded, return NULL. */
12057 x_query_font (f
, fontname
)
12059 register char *fontname
;
12061 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12064 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12065 if (dpyinfo
->font_table
[i
].name
12066 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
12067 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
12068 return (dpyinfo
->font_table
+ i
);
12073 /* Find a CCL program for a font specified by FONTP, and set the member
12074 `encoder' of the structure. */
12077 x_find_ccl_program (fontp
)
12078 struct font_info
*fontp
;
12080 extern Lisp_Object Vfont_ccl_encoder_alist
, Vccl_program_table
;
12081 extern Lisp_Object Qccl_program_idx
;
12082 extern Lisp_Object
resolve_symbol_ccl_program ();
12083 Lisp_Object list
, elt
, ccl_prog
, ccl_id
;
12085 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCONS (list
)->cdr
)
12087 elt
= XCONS (list
)->car
;
12089 && STRINGP (XCONS (elt
)->car
)
12090 && (fast_c_string_match_ignore_case (XCONS (elt
)->car
, fontp
->name
)
12093 if (SYMBOLP (XCONS (elt
)->cdr
) &&
12094 (!NILP (ccl_id
= Fget (XCONS (elt
)->cdr
, Qccl_program_idx
))))
12096 ccl_prog
= XVECTOR (Vccl_program_table
)->contents
[XUINT (ccl_id
)];
12097 if (!CONSP (ccl_prog
)) continue;
12098 ccl_prog
= XCONS (ccl_prog
)->cdr
;
12102 ccl_prog
= XCONS (elt
)->cdr
;
12103 if (!VECTORP (ccl_prog
)) continue;
12106 fontp
->font_encoder
12107 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
12108 setup_ccl_program (fontp
->font_encoder
,
12109 resolve_symbol_ccl_program (ccl_prog
));
12117 /***********************************************************************
12119 ***********************************************************************/
12121 #ifdef USE_X_TOOLKIT
12122 static XrmOptionDescRec emacs_options
[] = {
12123 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
12124 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
12126 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12127 XrmoptionSepArg
, NULL
},
12128 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
12130 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12131 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12132 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12133 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12134 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12135 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
12136 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
12138 #endif /* USE_X_TOOLKIT */
12140 static int x_initialized
;
12142 #ifdef MULTI_KBOARD
12143 /* Test whether two display-name strings agree up to the dot that separates
12144 the screen number from the server number. */
12146 same_x_server (name1
, name2
)
12147 char *name1
, *name2
;
12149 int seen_colon
= 0;
12150 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
12151 int system_name_length
= strlen (system_name
);
12152 int length_until_period
= 0;
12154 while (system_name
[length_until_period
] != 0
12155 && system_name
[length_until_period
] != '.')
12156 length_until_period
++;
12158 /* Treat `unix' like an empty host name. */
12159 if (! strncmp (name1
, "unix:", 5))
12161 if (! strncmp (name2
, "unix:", 5))
12163 /* Treat this host's name like an empty host name. */
12164 if (! strncmp (name1
, system_name
, system_name_length
)
12165 && name1
[system_name_length
] == ':')
12166 name1
+= system_name_length
;
12167 if (! strncmp (name2
, system_name
, system_name_length
)
12168 && name2
[system_name_length
] == ':')
12169 name2
+= system_name_length
;
12170 /* Treat this host's domainless name like an empty host name. */
12171 if (! strncmp (name1
, system_name
, length_until_period
)
12172 && name1
[length_until_period
] == ':')
12173 name1
+= length_until_period
;
12174 if (! strncmp (name2
, system_name
, length_until_period
)
12175 && name2
[length_until_period
] == ':')
12176 name2
+= length_until_period
;
12178 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
12182 if (seen_colon
&& *name1
== '.')
12186 && (*name1
== '.' || *name1
== '\0')
12187 && (*name2
== '.' || *name2
== '\0'));
12191 #if defined (HAVE_X_I18N) || (defined (USE_X_TOOLKIT) && defined (HAVE_X11XTR6))
12192 /* Recover from setlocale (LC_ALL, ""). */
12196 /* Currently we require strerror to use the "C" locale,
12197 since we don't yet support decoding its string result. */
12199 setlocale (LC_MESSAGES
, "C");
12202 /* The Emacs Lisp reader needs LC_NUMERIC to be "C",
12203 so that numbers are read and printed properly for Emacs Lisp. */
12204 setlocale (LC_NUMERIC
, "C");
12206 /* Currently we require strftime to use the "C" locale,
12207 since we don't yet support encoding its format argument,
12208 or decoding its string result. */
12209 setlocale (LC_TIME
, "C");
12213 struct x_display_info
*
12214 x_term_init (display_name
, xrm_option
, resource_name
)
12215 Lisp_Object display_name
;
12217 char *resource_name
;
12221 struct x_display_info
*dpyinfo
;
12226 if (!x_initialized
)
12233 setlocale (LC_ALL
, "");
12237 #ifdef USE_X_TOOLKIT
12238 /* weiner@footloose.sps.mot.com reports that this causes
12240 X protocol error: BadAtom (invalid Atom parameter)
12241 on protocol request 18skiloaf.
12242 So let's not use it until R6. */
12243 #ifdef HAVE_X11XTR6
12244 XtSetLanguageProc (NULL
, NULL
, NULL
);
12255 argv
[argc
++] = "-xrm";
12256 argv
[argc
++] = xrm_option
;
12258 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
12259 resource_name
, EMACS_CLASS
,
12260 emacs_options
, XtNumber (emacs_options
),
12263 #ifdef HAVE_X11XTR6
12264 /* I think this is to compensate for XtSetLanguageProc. */
12269 #else /* not USE_X_TOOLKIT */
12271 XSetLocaleModifiers ("");
12273 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
12274 #endif /* not USE_X_TOOLKIT */
12276 /* Detect failure. */
12283 /* We have definitely succeeded. Record the new connection. */
12285 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
12287 #ifdef MULTI_KBOARD
12289 struct x_display_info
*share
;
12292 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
12293 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
12294 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
12295 XSTRING (display_name
)->data
))
12298 dpyinfo
->kboard
= share
->kboard
;
12301 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
12302 init_kboard (dpyinfo
->kboard
);
12303 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
12305 char *vendor
= ServerVendor (dpy
);
12306 dpyinfo
->kboard
->Vsystem_key_alist
12307 = call1 (Qvendor_specific_keysyms
,
12308 build_string (vendor
? vendor
: ""));
12311 dpyinfo
->kboard
->next_kboard
= all_kboards
;
12312 all_kboards
= dpyinfo
->kboard
;
12313 /* Don't let the initial kboard remain current longer than necessary.
12314 That would cause problems if a file loaded on startup tries to
12315 prompt in the mini-buffer. */
12316 if (current_kboard
== initial_kboard
)
12317 current_kboard
= dpyinfo
->kboard
;
12319 dpyinfo
->kboard
->reference_count
++;
12323 /* Put this display on the chain. */
12324 dpyinfo
->next
= x_display_list
;
12325 x_display_list
= dpyinfo
;
12327 /* Put it on x_display_name_list as well, to keep them parallel. */
12328 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
12329 x_display_name_list
);
12330 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
12332 dpyinfo
->display
= dpy
;
12335 XSetAfterFunction (x_current_display
, x_trace_wire
);
12339 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
12340 + STRING_BYTES (XSTRING (Vsystem_name
))
12342 sprintf (dpyinfo
->x_id_name
, "%s@%s",
12343 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
12345 /* Figure out which modifier bits mean what. */
12346 x_find_modifier_meanings (dpyinfo
);
12348 /* Get the scroll bar cursor. */
12349 dpyinfo
->vertical_scroll_bar_cursor
12350 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
12352 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
12353 resource_name
, EMACS_CLASS
);
12354 #ifdef HAVE_XRMSETDATABASE
12355 XrmSetDatabase (dpyinfo
->display
, xrdb
);
12357 dpyinfo
->display
->db
= xrdb
;
12359 /* Put the rdb where we can find it in a way that works on
12361 dpyinfo
->xrdb
= xrdb
;
12363 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
12364 DefaultScreen (dpyinfo
->display
));
12365 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
12366 &dpyinfo
->n_planes
);
12367 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
12368 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
12369 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
12370 dpyinfo
->grabbed
= 0;
12371 dpyinfo
->reference_count
= 0;
12372 dpyinfo
->icon_bitmap_id
= -1;
12373 dpyinfo
->font_table
= NULL
;
12374 dpyinfo
->n_fonts
= 0;
12375 dpyinfo
->font_table_size
= 0;
12376 dpyinfo
->bitmaps
= 0;
12377 dpyinfo
->bitmaps_size
= 0;
12378 dpyinfo
->bitmaps_last
= 0;
12379 dpyinfo
->scratch_cursor_gc
= 0;
12380 dpyinfo
->mouse_face_mouse_frame
= 0;
12381 dpyinfo
->mouse_face_deferred_gc
= 0;
12382 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12383 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12384 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12385 dpyinfo
->mouse_face_window
= Qnil
;
12386 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
12387 dpyinfo
->mouse_face_defer
= 0;
12388 dpyinfo
->x_focus_frame
= 0;
12389 dpyinfo
->x_focus_event_frame
= 0;
12390 dpyinfo
->x_highlight_frame
= 0;
12391 dpyinfo
->image_cache
= make_image_cache ();
12394 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
12395 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
12396 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
12397 dpyinfo
->resy
= pixels
* 25.4 / mm
;
12398 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
12399 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
12400 dpyinfo
->resx
= pixels
* 25.4 / mm
;
12403 dpyinfo
->Xatom_wm_protocols
12404 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
12405 dpyinfo
->Xatom_wm_take_focus
12406 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
12407 dpyinfo
->Xatom_wm_save_yourself
12408 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
12409 dpyinfo
->Xatom_wm_delete_window
12410 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
12411 dpyinfo
->Xatom_wm_change_state
12412 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
12413 dpyinfo
->Xatom_wm_configure_denied
12414 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
12415 dpyinfo
->Xatom_wm_window_moved
12416 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
12417 dpyinfo
->Xatom_editres
12418 = XInternAtom (dpyinfo
->display
, "Editres", False
);
12419 dpyinfo
->Xatom_CLIPBOARD
12420 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
12421 dpyinfo
->Xatom_TIMESTAMP
12422 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
12423 dpyinfo
->Xatom_TEXT
12424 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
12425 dpyinfo
->Xatom_COMPOUND_TEXT
12426 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
12427 dpyinfo
->Xatom_DELETE
12428 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
12429 dpyinfo
->Xatom_MULTIPLE
12430 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
12431 dpyinfo
->Xatom_INCR
12432 = XInternAtom (dpyinfo
->display
, "INCR", False
);
12433 dpyinfo
->Xatom_EMACS_TMP
12434 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
12435 dpyinfo
->Xatom_TARGETS
12436 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
12437 dpyinfo
->Xatom_NULL
12438 = XInternAtom (dpyinfo
->display
, "NULL", False
);
12439 dpyinfo
->Xatom_ATOM_PAIR
12440 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
12441 /* For properties of font. */
12442 dpyinfo
->Xatom_PIXEL_SIZE
12443 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
12444 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
12445 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
12446 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
12447 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
12448 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
12449 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
12451 /* Ghostscript support. */
12452 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
12453 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
12455 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
12458 dpyinfo
->cut_buffers_initialized
= 0;
12460 connection
= ConnectionNumber (dpyinfo
->display
);
12461 dpyinfo
->connection
= connection
;
12466 null_bits
[0] = 0x00;
12468 dpyinfo
->null_pixel
12469 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12470 null_bits
, 1, 1, (long) 0, (long) 0,
12475 extern int gray_bitmap_width
, gray_bitmap_height
;
12476 extern unsigned char *gray_bitmap_bits
;
12478 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12480 gray_bitmap_width
, gray_bitmap_height
,
12481 (unsigned long) 1, (unsigned long) 0, 1);
12484 #ifdef subprocesses
12485 /* This is only needed for distinguishing keyboard and process input. */
12486 if (connection
!= 0)
12487 add_keyboard_wait_descriptor (connection
);
12490 #ifndef F_SETOWN_BUG
12492 #ifdef F_SETOWN_SOCK_NEG
12493 /* stdin is a socket here */
12494 fcntl (connection
, F_SETOWN
, -getpid ());
12495 #else /* ! defined (F_SETOWN_SOCK_NEG) */
12496 fcntl (connection
, F_SETOWN
, getpid ());
12497 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
12498 #endif /* ! defined (F_SETOWN) */
12499 #endif /* F_SETOWN_BUG */
12502 if (interrupt_input
)
12503 init_sigio (connection
);
12504 #endif /* ! defined (SIGIO) */
12507 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
12508 /* Make sure that we have a valid font for dialog boxes
12509 so that Xt does not crash. */
12511 Display
*dpy
= dpyinfo
->display
;
12512 XrmValue d
, fr
, to
;
12516 d
.addr
= (XPointer
)&dpy
;
12517 d
.size
= sizeof (Display
*);
12518 fr
.addr
= XtDefaultFont
;
12519 fr
.size
= sizeof (XtDefaultFont
);
12520 to
.size
= sizeof (Font
*);
12521 to
.addr
= (XPointer
)&font
;
12522 count
= x_catch_errors (dpy
);
12523 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
12525 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
12526 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
12527 x_uncatch_errors (dpy
, count
);
12537 /* Get rid of display DPYINFO, assuming all frames are already gone,
12538 and without sending any more commands to the X server. */
12541 x_delete_display (dpyinfo
)
12542 struct x_display_info
*dpyinfo
;
12544 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
12546 /* Discard this display from x_display_name_list and x_display_list.
12547 We can't use Fdelq because that can quit. */
12548 if (! NILP (x_display_name_list
)
12549 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
12550 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
12555 tail
= x_display_name_list
;
12556 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
12558 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
12559 dpyinfo
->name_list_element
))
12561 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
12564 tail
= XCONS (tail
)->cdr
;
12568 if (x_display_list
== dpyinfo
)
12569 x_display_list
= dpyinfo
->next
;
12572 struct x_display_info
*tail
;
12574 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12575 if (tail
->next
== dpyinfo
)
12576 tail
->next
= tail
->next
->next
;
12579 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12580 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
12581 XrmDestroyDatabase (dpyinfo
->xrdb
);
12584 #ifdef MULTI_KBOARD
12585 if (--dpyinfo
->kboard
->reference_count
== 0)
12586 delete_kboard (dpyinfo
->kboard
);
12588 xfree (dpyinfo
->font_table
);
12589 xfree (dpyinfo
->x_id_name
);
12593 /* Set up use of X before we make the first connection. */
12595 static struct redisplay_interface x_redisplay_interface
=
12600 x_clear_end_of_line
,
12602 x_after_update_window_line
,
12603 x_update_window_begin
,
12604 x_update_window_end
,
12607 x_get_glyph_overhangs
12613 rif
= &x_redisplay_interface
;
12615 clear_frame_hook
= x_clear_frame
;
12616 ins_del_lines_hook
= x_ins_del_lines
;
12617 change_line_highlight_hook
= x_change_line_highlight
;
12618 delete_glyphs_hook
= x_delete_glyphs
;
12619 ring_bell_hook
= XTring_bell
;
12620 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12621 set_terminal_modes_hook
= XTset_terminal_modes
;
12622 update_begin_hook
= x_update_begin
;
12623 update_end_hook
= x_update_end
;
12624 set_terminal_window_hook
= XTset_terminal_window
;
12625 read_socket_hook
= XTread_socket
;
12626 frame_up_to_date_hook
= XTframe_up_to_date
;
12627 reassert_line_highlight_hook
= XTreassert_line_highlight
;
12628 mouse_position_hook
= XTmouse_position
;
12629 frame_rehighlight_hook
= XTframe_rehighlight
;
12630 frame_raise_lower_hook
= XTframe_raise_lower
;
12631 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12632 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12633 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12634 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12635 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
12637 scroll_region_ok
= 1; /* we'll scroll partial frames */
12638 char_ins_del_ok
= 0; /* just as fast to write the line */
12639 line_ins_del_ok
= 1; /* we'll just blt 'em */
12640 fast_clear_end_of_line
= 1; /* X does this well */
12641 memory_below_frame
= 0; /* we don't remember what scrolls
12646 last_toolbar_item
= -1;
12647 any_help_event_p
= 0;
12649 /* Try to use interrupt input; if we can't, then start polling. */
12650 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12652 #ifdef USE_X_TOOLKIT
12653 XtToolkitInitialize ();
12654 Xt_app_con
= XtCreateApplicationContext ();
12655 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
12658 /* Note that there is no real way portable across R3/R4 to get the
12659 original error handler. */
12660 XSetErrorHandler (x_error_handler
);
12661 XSetIOErrorHandler (x_io_error_quitter
);
12663 /* Disable Window Change signals; they are handled by X events. */
12665 signal (SIGWINCH
, SIG_DFL
);
12666 #endif /* ! defined (SIGWINCH) */
12668 signal (SIGPIPE
, x_connection_signal
);
12675 staticpro (&x_error_message_string
);
12676 x_error_message_string
= Qnil
;
12678 staticpro (&x_display_name_list
);
12679 x_display_name_list
= Qnil
;
12681 staticpro (&last_mouse_scroll_bar
);
12682 last_mouse_scroll_bar
= Qnil
;
12684 staticpro (&Qvendor_specific_keysyms
);
12685 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
12687 staticpro (&last_mouse_press_frame
);
12688 last_mouse_press_frame
= Qnil
;
12690 staticpro (&help_echo
);
12692 staticpro (&previous_help_echo
);
12693 previous_help_echo
= Qnil
;
12695 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
12696 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
12697 For example, if a block cursor is over a tab, it will be drawn as\n\
12698 wide as that tab on the display.");
12699 x_stretch_cursor_p
= 0;
12701 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p
,
12702 "If not nil, Emacs uses toolkit scroll bars.");
12703 #if USE_TOOLKIT_SCROLL_BARS
12704 x_toolkit_scroll_bars_p
= 1;
12706 x_toolkit_scroll_bars_p
= 0;
12709 defsubr (&Sxt_process_timeouts
);
12710 staticpro (&last_mouse_motion_frame
);
12711 last_mouse_motion_frame
= Qnil
;
12714 #endif /* not HAVE_X_WINDOWS */