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. */
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
45 #include <X11/cursorfont.h>
48 /* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */
51 #include <sys/types.h>
56 #include <sys/ioctl.h>
57 #endif /* ! defined (BSD_SYSTEM) */
62 #ifndef INCLUDED_FCNTL
69 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
70 /* #include <sys/param.h> */
76 #include "dispextern.h"
77 #include "termhooks.h"
89 #include "intervals.h"
93 #include <X11/Shell.h>
96 #include <sys/types.h>
97 #ifdef HAVE_SYS_TIME_H
106 extern void free_frame_menubar ();
107 extern FRAME_PTR
x_menubar_window_to_frame ();
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
114 /* Include toolkit specific headers for the scroll bar widget. */
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #include <Xm/ScrollBarP.h>
121 #elif defined HAVE_XAW3D
122 #include <X11/Xaw3d/Simple.h>
123 #include <X11/Xaw3d/ThreeD.h>
124 #include <X11/Xaw3d/Scrollbar.h>
125 #define ARROW_SCROLLBAR
126 #include <X11/Xaw3d/ScrollbarP.h>
127 #endif /* HAVE_XAW3D */
128 #endif /* USE_TOOLKIT_SCROLL_BARS */
130 #endif /* USE_X_TOOLKIT */
132 #ifndef USE_X_TOOLKIT
133 #define x_any_window_to_frame x_window_to_frame
134 #define x_top_window_to_frame x_window_to_frame
139 #ifndef XtNinitialState
140 #define XtNinitialState "initialState"
145 /* memmove will be defined as a macro in Xfuncs.h unless
146 <string.h> is included beforehand. The declaration for memmove in
147 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
152 #define min(a,b) ((a) < (b) ? (a) : (b))
155 #define max(a,b) ((a) > (b) ? (a) : (b))
158 #define abs(x) ((x) < 0 ? -(x) : (x))
160 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
163 /* Bitmaps for truncated lines. */
168 LEFT_TRUNCATION_BITMAP
,
169 RIGHT_TRUNCATION_BITMAP
,
170 OVERLAY_ARROW_BITMAP
,
171 CONTINUED_LINE_BITMAP
,
172 CONTINUATION_LINE_BITMAP
,
176 /* Bitmap drawn to indicate lines not displaying text if
177 `indicate-empty-lines' is non-nil. */
181 static unsigned char zv_bits
[] = {
182 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
184 /* An arrow like this: `<-'. */
187 #define left_height 8
188 static unsigned char left_bits
[] = {
189 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
191 /* Right truncation arrow bitmap `->'. */
193 #define right_width 8
194 #define right_height 8
195 static unsigned char right_bits
[] = {
196 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
198 /* Marker for continued lines. */
200 #define continued_width 8
201 #define continued_height 8
202 static unsigned char continued_bits
[] = {
203 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
205 /* Marker for continuation lines. */
207 #define continuation_width 8
208 #define continuation_height 8
209 static unsigned char continuation_bits
[] = {
210 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
212 /* Overlay arrow bitmap. */
218 static unsigned char ov_bits
[] = {
219 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
221 /* A triangular arrow. */
224 static unsigned char ov_bits
[] = {
225 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
229 extern Lisp_Object Qhelp_echo
;
232 /* Non-zero means Emacs uses toolkit scroll bars. */
234 int x_toolkit_scroll_bars_p
;
236 /* If a string, XTread_socket generates an event to display that string.
237 (The display is done in read_char.) */
239 static Lisp_Object help_echo
;
241 /* Temporary variable for XTread_socket. */
243 static Lisp_Object previous_help_echo
;
245 /* Non-zero means that a HELP_EVENT has been generated since Emacs
248 static int any_help_event_p
;
250 /* Non-zero means draw block and hollow cursor as wide as the glyph
251 under it. For example, if a block cursor is over a tab, it will be
252 drawn as wide as that tab on the display. */
254 int x_stretch_cursor_p
;
256 /* This is a chain of structures for all the X displays currently in
259 struct x_display_info
*x_display_list
;
261 /* This is a list of cons cells, each of the form (NAME
262 . FONT-LIST-CACHE), one for each element of x_display_list and in
263 the same order. NAME is the name of the frame. FONT-LIST-CACHE
264 records previous values returned by x-list-fonts. */
266 Lisp_Object x_display_name_list
;
268 /* Frame being updated by update_frame. This is declared in term.c.
269 This is set by update_begin and looked at by all the XT functions.
270 It is zero while not inside an update. In that case, the XT
271 functions assume that `selected_frame' is the frame to apply to. */
273 extern struct frame
*updating_frame
;
275 extern int waiting_for_input
;
277 /* This is a frame waiting to be auto-raised, within XTread_socket. */
279 struct frame
*pending_autoraise_frame
;
282 /* The application context for Xt use. */
283 XtAppContext Xt_app_con
;
284 static String Xt_default_resources
[] = {0};
285 #endif /* USE_X_TOOLKIT */
287 /* Nominal cursor position -- where to draw output.
288 HPOS and VPOS are window relative glyph matrix coordinates.
289 X and Y are window relative pixel coordinates. */
291 struct cursor_pos output_cursor
;
296 Formerly, we used PointerMotionHintMask (in standard_event_mask)
297 so that we would have to call XQueryPointer after each MotionNotify
298 event to ask for another such event. However, this made mouse tracking
299 slow, and there was a bug that made it eventually stop.
301 Simply asking for MotionNotify all the time seems to work better.
303 In order to avoid asking for motion events and then throwing most
304 of them away or busy-polling the server for mouse positions, we ask
305 the server for pointer motion hints. This means that we get only
306 one event per group of mouse movements. "Groups" are delimited by
307 other kinds of events (focus changes and button clicks, for
308 example), or by XQueryPointer calls; when one of these happens, we
309 get another MotionNotify event the next time the mouse moves. This
310 is at least as efficient as getting motion events when mouse
311 tracking is on, and I suspect only negligibly worse when tracking
314 /* Where the mouse was last time we reported a mouse event. */
316 FRAME_PTR last_mouse_frame
;
317 static XRectangle last_mouse_glyph
;
318 static Lisp_Object last_mouse_press_frame
;
320 /* The scroll bar in which the last X motion event occurred.
322 If the last X motion event occurred in a scroll bar, we set this so
323 XTmouse_position can know whether to report a scroll bar motion or
326 If the last X motion event didn't occur in a scroll bar, we set
327 this to Qnil, to tell XTmouse_position to return an ordinary motion
330 static Lisp_Object last_mouse_scroll_bar
;
332 /* This is a hack. We would really prefer that XTmouse_position would
333 return the time associated with the position it returns, but there
334 doesn't seem to be any way to wrest the time-stamp from the server
335 along with the position query. So, we just keep track of the time
336 of the last movement we received, and return that in hopes that
337 it's somewhat accurate. */
339 static Time last_mouse_movement_time
;
341 /* Incremented by XTread_socket whenever it really tries to read
345 static int volatile input_signal_count
;
347 static int input_signal_count
;
350 /* Used locally within XTread_socket. */
352 static int x_noop_count
;
354 /* Initial values of argv and argc. */
356 extern char **initial_argv
;
357 extern int initial_argc
;
359 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
361 /* Tells if a window manager is present or not. */
363 extern Lisp_Object Vx_no_window_manager
;
365 extern Lisp_Object Qface
, Qmouse_face
;
369 /* A mask of extra modifier bits to put into every keyboard char. */
371 extern int extra_keyboard_modifiers
;
373 static Lisp_Object Qvendor_specific_keysyms
;
375 extern XrmDatabase
x_load_resources ();
376 extern Lisp_Object
x_icon_type ();
379 /* Enumeration for overriding/changing the face to use for drawing
380 glyphs in x_draw_glyphs. */
382 enum draw_glyphs_face
392 static void x_update_window_end
P_ ((struct window
*, int));
393 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
394 void x_delete_display
P_ ((struct x_display_info
*));
395 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
397 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
399 static void set_output_cursor
P_ ((struct cursor_pos
*));
400 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
401 int *, int *, int *));
402 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
403 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
404 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
405 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
406 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
407 static void show_mouse_face
P_ ((struct x_display_info
*,
408 enum draw_glyphs_face
));
409 static int x_io_error_quitter
P_ ((Display
*));
410 int x_catch_errors
P_ ((Display
*));
411 void x_uncatch_errors
P_ ((Display
*, int));
412 void x_lower_frame
P_ ((struct frame
*));
413 void x_scroll_bar_clear
P_ ((struct frame
*));
414 int x_had_errors_p
P_ ((Display
*));
415 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
416 void x_raise_frame
P_ ((struct frame
*));
417 void x_set_window_size
P_ ((struct frame
*, int, int, int));
418 void x_wm_set_window_state
P_ ((struct frame
*, int));
419 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
420 void x_initialize
P_ ((void));
421 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
422 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
423 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
425 enum draw_glyphs_face
));
426 static void x_update_end
P_ ((struct frame
*));
427 static void XTframe_up_to_date
P_ ((struct frame
*));
428 static void XTreassert_line_highlight
P_ ((int, int));
429 static void x_change_line_highlight
P_ ((int, int, int, int));
430 static void XTset_terminal_modes
P_ ((void));
431 static void XTreset_terminal_modes
P_ ((void));
432 static void XTcursor_to
P_ ((int, int, int, int));
433 static void x_write_glyphs
P_ ((struct glyph
*, int));
434 static void x_clear_end_of_line
P_ ((int));
435 static void x_clear_frame
P_ ((void));
436 static void x_clear_cursor
P_ ((struct window
*));
437 static void frame_highlight
P_ ((struct frame
*));
438 static void frame_unhighlight
P_ ((struct frame
*));
439 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
440 static void XTframe_rehighlight
P_ ((struct frame
*));
441 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
442 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
443 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*));
444 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
446 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
447 static void expose_window_tree
P_ ((struct window
*, XRectangle
*));
448 static void expose_window
P_ ((struct window
*, XRectangle
*));
449 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
450 XRectangle
*, enum glyph_row_area
));
451 static void expose_line
P_ ((struct window
*, struct glyph_row
*,
453 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
454 static void x_update_window_cursor
P_ ((struct window
*, int));
455 static void x_erase_phys_cursor
P_ ((struct window
*));
456 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
457 static void x_draw_bitmap
P_ ((struct window
*, struct glyph_row
*,
460 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
462 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
463 static void x_draw_row_bitmaps
P_ ((struct window
*, struct glyph_row
*));
464 static void note_overwritten_text_cursor
P_ ((struct window
*, int, int));
465 static void x_flush
P_ ((struct frame
*f
));
468 /* Flush display of frame F, or of all frames if F is null. */
477 Lisp_Object rest
, frame
;
478 FOR_EACH_FRAME (rest
, frame
)
479 x_flush (XFRAME (frame
));
481 else if (FRAME_X_P (f
))
482 XFlush (FRAME_X_DISPLAY (f
));
487 /* Remove calls to XFlush by defining XFlush to an empty replacement.
488 Calls to XFlush should be unnecessary because the X output buffer
489 is flushed automatically as needed by calls to XPending,
490 XNextEvent, or XWindowEvent according to the XFlush man page.
491 XTread_socket calls XPending. Removing XFlush improves
494 #define XFlush(DISPLAY) (void) 0
497 /***********************************************************************
499 ***********************************************************************/
503 /* This is a function useful for recording debugging information about
504 the sequence of occurrences in this file. */
512 struct record event_record
[100];
514 int event_record_index
;
516 record_event (locus
, type
)
520 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
521 event_record_index
= 0;
523 event_record
[event_record_index
].locus
= locus
;
524 event_record
[event_record_index
].type
= type
;
525 event_record_index
++;
532 /* Return the struct x_display_info corresponding to DPY. */
534 struct x_display_info
*
535 x_display_info_for_display (dpy
)
538 struct x_display_info
*dpyinfo
;
540 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
541 if (dpyinfo
->display
== dpy
)
549 /***********************************************************************
550 Starting and ending an update
551 ***********************************************************************/
553 /* Start an update of frame F. This function is installed as a hook
554 for update_begin, i.e. it is called when update_begin is called.
555 This function is called prior to calls to x_update_window_begin for
556 each window being updated. Currently, there is nothing to do here
557 because all interesting stuff is done on a window basis. */
567 /* Start update of window W. Set the global variable updated_window
568 to the window being updated and set output_cursor to the cursor
572 x_update_window_begin (w
)
575 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
576 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
579 set_output_cursor (&w
->cursor
);
583 if (f
== display_info
->mouse_face_mouse_frame
)
585 /* Don't do highlighting for mouse motion during the update. */
586 display_info
->mouse_face_defer
= 1;
588 /* If F needs to be redrawn, simply forget about any prior mouse
590 if (FRAME_GARBAGED_P (f
))
591 display_info
->mouse_face_window
= Qnil
;
593 /* Can we tell that this update does not affect the window
594 where the mouse highlight is? If so, no need to turn off.
595 Likewise, don't do anything if the frame is garbaged;
596 in that case, the frame's current matrix that we would use
597 is all wrong, and we will redisplay that line anyway. */
598 if (!NILP (display_info
->mouse_face_window
)
599 && w
== XWINDOW (display_info
->mouse_face_window
))
603 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
604 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
607 if (i
< w
->desired_matrix
->nrows
)
608 clear_mouse_face (display_info
);
616 /* Draw a vertical window border to the right of window W if W doesn't
617 have vertical scroll bars. */
620 x_draw_vertical_border (w
)
623 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
625 /* Redraw borders between horizontally adjacent windows. Don't
626 do it for frames with vertical scroll bars because either the
627 right scroll bar of a window, or the left scroll bar of its
628 neighbor will suffice as a border. */
629 if (!WINDOW_RIGHTMOST_P (w
)
630 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
634 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
635 x1
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
);
638 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
639 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
644 /* End update of window W (which is equal to updated_window). Draw
645 vertical borders between horizontally adjacent windows, and display
646 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
647 pseudo-window in case we don't have X toolkit support. Such
648 windows don't have a cursor, so don't display it here. */
651 x_update_window_end (w
, cursor_on_p
)
655 if (!w
->pseudo_window_p
)
659 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
661 output_cursor
.x
, output_cursor
.y
);
662 x_draw_vertical_border (w
);
666 updated_window
= NULL
;
670 /* End update of frame F. This function is installed as a hook in
677 /* Mouse highlight may be displayed again. */
678 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
681 XFlush (FRAME_X_DISPLAY (f
));
686 /* This function is called from various places in xdisp.c whenever a
687 complete update has been performed. The global variable
688 updated_window is not available here. */
691 XTframe_up_to_date (f
)
696 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
697 if (dpyinfo
->mouse_face_deferred_gc
698 || f
== dpyinfo
->mouse_face_mouse_frame
)
701 if (dpyinfo
->mouse_face_mouse_frame
)
702 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
703 dpyinfo
->mouse_face_mouse_x
,
704 dpyinfo
->mouse_face_mouse_y
);
705 dpyinfo
->mouse_face_deferred_gc
= 0;
712 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
713 arrow bitmaps, or clear the areas where they would be displayed
714 before DESIRED_ROW is made current. The window being updated is
715 found in updated_window. This function It is called from
716 update_window_line only if it is known that there are differences
717 between bitmaps to be drawn between current row and DESIRED_ROW. */
720 x_after_update_window_line (desired_row
)
721 struct glyph_row
*desired_row
;
723 struct window
*w
= updated_window
;
727 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
730 x_draw_row_bitmaps (w
, desired_row
);
732 /* When a window has disappeared, make sure that no rest of
733 full-width rows stays visible in the internal border. */
734 if (windows_or_buffers_changed
)
736 struct frame
*f
= XFRAME (w
->frame
);
737 int width
= FRAME_INTERNAL_BORDER_WIDTH (f
);
738 int height
= desired_row
->visible_height
;
739 int x
= (window_box_right (w
, -1)
740 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
));
741 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
743 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
744 x
, y
, width
, height
, False
);
752 /* Draw the bitmap WHICH in one of the areas to the left or right of
753 window W. ROW is the glyph row for which to display the bitmap; it
754 determines the vertical position at which the bitmap has to be
758 x_draw_bitmap (w
, row
, which
)
760 struct glyph_row
*row
;
761 enum bitmap_type which
;
763 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
764 Display
*display
= FRAME_X_DISPLAY (f
);
765 Window window
= FRAME_X_WINDOW (f
);
769 GC gc
= f
->output_data
.x
->normal_gc
;
771 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
773 /* Must clip because of partially visible lines. */
774 x_clip_to_row (w
, row
, gc
, 1);
778 case LEFT_TRUNCATION_BITMAP
:
782 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
784 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
787 case OVERLAY_ARROW_BITMAP
:
791 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
793 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
796 case RIGHT_TRUNCATION_BITMAP
:
800 x
= window_box_right (w
, -1);
801 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
804 case CONTINUED_LINE_BITMAP
:
807 bits
= continued_bits
;
808 x
= window_box_right (w
, -1);
809 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
812 case CONTINUATION_LINE_BITMAP
:
813 wd
= continuation_width
;
814 h
= continuation_height
;
815 bits
= continuation_bits
;
816 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
818 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
825 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
827 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
834 /* Convert to frame coordinates. Set dy to the offset in the row to
835 start drawing the bitmap. */
836 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
837 dy
= (row
->height
- h
) / 2;
839 /* Draw the bitmap. I believe these small pixmaps can be cached
841 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
842 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
844 face
->background
, depth
);
845 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
846 XFreePixmap (display
, pixmap
);
847 XSetClipMask (display
, gc
, None
);
851 /* Draw flags bitmaps for glyph row ROW on window W. Call this
852 function with input blocked. */
855 x_draw_row_bitmaps (w
, row
)
857 struct glyph_row
*row
;
859 struct frame
*f
= XFRAME (w
->frame
);
860 enum bitmap_type bitmap
;
862 int header_line_height
= -1;
864 xassert (interrupt_input_blocked
);
866 /* If row is completely invisible, because of vscrolling, we
867 don't have to draw anything. */
868 if (row
->visible_height
<= 0)
871 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
872 PREPARE_FACE_FOR_DISPLAY (f
, face
);
874 /* Decide which bitmap to draw at the left side. */
875 if (row
->overlay_arrow_p
)
876 bitmap
= OVERLAY_ARROW_BITMAP
;
877 else if (row
->truncated_on_left_p
)
878 bitmap
= LEFT_TRUNCATION_BITMAP
;
879 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
880 bitmap
= CONTINUATION_LINE_BITMAP
;
881 else if (row
->indicate_empty_line_p
)
882 bitmap
= ZV_LINE_BITMAP
;
886 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
888 if (bitmap
== NO_BITMAP
889 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
890 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
892 /* If W has a vertical border to its left, don't draw over it. */
893 int border
= ((XFASTINT (w
->left
) > 0
894 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
896 int left
= window_box_left (w
, -1);
898 if (header_line_height
< 0)
899 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
901 /* In case the same realized face is used for bitmap areas and
902 for something displayed in the text (e.g. face `region' on
903 mono-displays, the fill style may have been changed to
904 FillSolid in x_draw_glyph_string_background. */
906 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
908 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
910 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
913 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
915 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
917 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - border
,
918 row
->visible_height
);
920 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
923 /* Draw the left bitmap. */
924 if (bitmap
!= NO_BITMAP
)
925 x_draw_bitmap (w
, row
, bitmap
);
927 /* Decide which bitmap to draw at the right side. */
928 if (row
->truncated_on_right_p
)
929 bitmap
= RIGHT_TRUNCATION_BITMAP
;
930 else if (row
->continued_p
)
931 bitmap
= CONTINUED_LINE_BITMAP
;
935 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
937 if (bitmap
== NO_BITMAP
938 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
)
939 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
941 int right
= window_box_right (w
, -1);
943 if (header_line_height
< 0)
944 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
946 /* In case the same realized face is used for bitmap areas and
947 for something displayed in the text (e.g. face `region' on
948 mono-displays, the fill style may have been changed to
949 FillSolid in x_draw_glyph_string_background. */
951 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
953 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
954 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
957 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
959 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
),
960 row
->visible_height
);
962 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
965 /* Draw the right bitmap. */
966 if (bitmap
!= NO_BITMAP
)
967 x_draw_bitmap (w
, row
, bitmap
);
971 /***********************************************************************
973 ***********************************************************************/
975 /* External interface to control of standout mode. Not used for X
976 frames. Aborts when called. */
979 XTreassert_line_highlight (new, vpos
)
986 /* Call this when about to modify line at position VPOS and change
987 whether it is highlighted. Not used for X frames. Aborts when
991 x_change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
992 int new_highlight
, vpos
, y
, first_unused_hpos
;
998 /* This is called when starting Emacs and when restarting after
999 suspend. When starting Emacs, no X window is mapped. And nothing
1000 must be done to Emacs's own window if it is suspended (though that
1004 XTset_terminal_modes ()
1008 /* This is called when exiting or suspending Emacs. Exiting will make
1009 the X-windows go away, and suspending requires no action. */
1012 XTreset_terminal_modes ()
1018 /***********************************************************************
1020 ***********************************************************************/
1022 /* Set the global variable output_cursor to CURSOR. All cursor
1023 positions are relative to updated_window. */
1026 set_output_cursor (cursor
)
1027 struct cursor_pos
*cursor
;
1029 output_cursor
.hpos
= cursor
->hpos
;
1030 output_cursor
.vpos
= cursor
->vpos
;
1031 output_cursor
.x
= cursor
->x
;
1032 output_cursor
.y
= cursor
->y
;
1036 /* Set a nominal cursor position.
1038 HPOS and VPOS are column/row positions in a window glyph matrix. X
1039 and Y are window text area relative pixel positions.
1041 If this is done during an update, updated_window will contain the
1042 window that is being updated and the position is the future output
1043 cursor position for that window. If updated_window is null, use
1044 selected_window and display the cursor at the given position. */
1047 XTcursor_to (vpos
, hpos
, y
, x
)
1048 int vpos
, hpos
, y
, x
;
1052 /* If updated_window is not set, work on selected_window. */
1056 w
= XWINDOW (selected_window
);
1058 /* Set the output cursor. */
1059 output_cursor
.hpos
= hpos
;
1060 output_cursor
.vpos
= vpos
;
1061 output_cursor
.x
= x
;
1062 output_cursor
.y
= y
;
1064 /* If not called as part of an update, really display the cursor.
1065 This will also set the cursor position of W. */
1066 if (updated_window
== NULL
)
1069 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1070 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1077 /***********************************************************************
1079 ***********************************************************************/
1081 /* Function prototypes of this page. */
1083 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1086 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1087 int, XChar2b
*, int));
1088 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1089 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1090 static void x_append_glyph
P_ ((struct it
*));
1091 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1093 static void x_produce_glyphs
P_ ((struct it
*));
1094 static void x_produce_image_glyph
P_ ((struct it
*it
));
1097 /* Return a pointer to per-char metric information in FONT of a
1098 character pointed by B which is a pointer to an XChar2b. */
1100 #define PER_CHAR_METRIC(font, b) \
1102 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1103 + (((font)->min_byte1 || (font)->max_byte1) \
1104 ? (((b)->byte1 - (font)->min_byte1) \
1105 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1107 : &((font)->max_bounds))
1110 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1111 If CHAR2B is not contained in FONT, the font's default character
1112 metric is returned. */
1114 static INLINE XCharStruct
*
1115 x_per_char_metric (font
, char2b
)
1119 /* The result metric information. */
1120 XCharStruct
*pcm
= NULL
;
1122 xassert (font
&& char2b
);
1124 if (font
->per_char
!= NULL
)
1126 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1128 /* min_char_or_byte2 specifies the linear character index
1129 corresponding to the first element of the per_char array,
1130 max_char_or_byte2 is the index of the last character. A
1131 character with non-zero CHAR2B->byte1 is not in the font.
1132 A character with byte2 less than min_char_or_byte2 or
1133 greater max_char_or_byte2 is not in the font. */
1134 if (char2b
->byte1
== 0
1135 && char2b
->byte2
>= font
->min_char_or_byte2
1136 && char2b
->byte2
<= font
->max_char_or_byte2
)
1137 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1141 /* If either min_byte1 or max_byte1 are nonzero, both
1142 min_char_or_byte2 and max_char_or_byte2 are less than
1143 256, and the 2-byte character index values corresponding
1144 to the per_char array element N (counting from 0) are:
1146 byte1 = N/D + min_byte1
1147 byte2 = N\D + min_char_or_byte2
1151 D = max_char_or_byte2 - min_char_or_byte2 + 1
1152 / = integer division
1153 \ = integer modulus */
1154 if (char2b
->byte1
>= font
->min_byte1
1155 && char2b
->byte1
<= font
->max_byte1
1156 && char2b
->byte2
>= font
->min_char_or_byte2
1157 && char2b
->byte2
<= font
->max_char_or_byte2
)
1159 pcm
= (font
->per_char
1160 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1161 * (char2b
->byte1
- font
->min_byte1
))
1162 + (char2b
->byte2
- font
->min_char_or_byte2
));
1168 /* If the per_char pointer is null, all glyphs between the first
1169 and last character indexes inclusive have the same
1170 information, as given by both min_bounds and max_bounds. */
1171 if (char2b
->byte2
>= font
->min_char_or_byte2
1172 && char2b
->byte2
<= font
->max_char_or_byte2
)
1173 pcm
= &font
->max_bounds
;
1177 if (pcm
== NULL
|| pcm
->width
== 0)
1179 /* Character not contained in the font. FONT->default_char
1180 gives the character that will be printed. FONT->default_char
1181 is a 16-bit character code with byte1 in the most significant
1182 byte and byte2 in the least significant byte. */
1183 XChar2b default_char
;
1184 default_char
.byte1
= (font
->default_char
>> BITS_PER_CHAR
) & 0xff;
1185 default_char
.byte2
= font
->default_char
& 0xff;
1187 /* Avoid an endless recursion if FONT->default_char itself
1188 hasn't per char metrics. handa@etl.go.jp reports that some
1189 fonts have this problem. */
1190 if (default_char
.byte1
!= char2b
->byte1
1191 || default_char
.byte2
!= char2b
->byte2
)
1192 pcm
= x_per_char_metric (font
, &default_char
);
1194 pcm
= &font
->max_bounds
;
1201 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1202 the two-byte form of C. Encoding is returned in *CHAR2B. */
1205 x_encode_char (c
, char2b
, font_info
)
1208 struct font_info
*font_info
;
1210 int charset
= CHAR_CHARSET (c
);
1211 XFontStruct
*font
= font_info
->font
;
1213 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1214 This may be either a program in a special encoder language or a
1216 if (font_info
->font_encoder
)
1218 /* It's a program. */
1219 struct ccl_program
*ccl
= font_info
->font_encoder
;
1221 if (CHARSET_DIMENSION (charset
) == 1)
1223 ccl
->reg
[0] = charset
;
1224 ccl
->reg
[1] = char2b
->byte2
;
1228 ccl
->reg
[0] = charset
;
1229 ccl
->reg
[1] = char2b
->byte1
;
1230 ccl
->reg
[2] = char2b
->byte2
;
1233 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1235 /* We assume that MSBs are appropriately set/reset by CCL
1237 if (font
->max_byte1
== 0) /* 1-byte font */
1238 char2b
->byte2
= ccl
->reg
[1];
1240 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1242 else if (font_info
->encoding
[charset
])
1244 /* Fixed encoding scheme. See fontset.h for the meaning of the
1245 encoding numbers. */
1246 int enc
= font_info
->encoding
[charset
];
1248 if ((enc
== 1 || enc
== 2)
1249 && CHARSET_DIMENSION (charset
) == 2)
1250 char2b
->byte1
|= 0x80;
1252 if (enc
== 1 || enc
== 3)
1253 char2b
->byte2
|= 0x80;
1258 /* Get face and two-byte form of character C in face FACE_ID on frame
1259 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1260 means we want to display multibyte text. Value is a pointer to a
1261 realized face that is ready for display. */
1263 static INLINE
struct face
*
1264 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1270 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1274 /* Unibyte case. We don't have to encode, but we have to make
1275 sure to use a face suitable for unibyte. */
1279 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, -1))
1281 face_id
= FACE_FOR_CHARSET (f
, face_id
, -1);
1282 face
= FACE_FROM_ID (f
, face_id
);
1285 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1287 /* Case of ASCII in a face known to fit ASCII. */
1293 int c1
, c2
, charset
;
1295 /* Split characters into bytes. If c2 is -1 afterwards, C is
1296 really a one-byte character so that byte1 is zero. */
1297 SPLIT_CHAR (c
, charset
, c1
, c2
);
1299 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1301 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1303 /* Get the face for displaying C. If `face' is not suitable for
1304 charset, get the one that fits. (This can happen for the
1305 translations of composite characters where the glyph
1306 specifies a face for ASCII, but translations have a different
1308 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, charset
))
1310 face_id
= FACE_FOR_CHARSET (f
, face_id
, charset
);
1311 face
= FACE_FROM_ID (f
, face_id
);
1314 /* Maybe encode the character in *CHAR2B. */
1315 if (charset
!= CHARSET_ASCII
)
1317 struct font_info
*font_info
1318 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1321 x_encode_char (c
, char2b
, font_info
);
1322 if (charset
== charset_latin_iso8859_1
)
1324 xassert (((XFontStruct
*) font_info
->font
)->max_char_or_byte2
1326 char2b
->byte2
|= 0x80;
1332 /* Make sure X resources of the face are allocated. */
1333 xassert (face
!= NULL
);
1334 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1340 /* Get face and two-byte form of character glyph GLYPH on frame F.
1341 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1342 a pointer to a realized face that is ready for display. */
1344 static INLINE
struct face
*
1345 x_get_glyph_face_and_encoding (f
, glyph
, char2b
)
1347 struct glyph
*glyph
;
1352 xassert (glyph
->type
== CHAR_GLYPH
);
1353 face
= FACE_FROM_ID (f
, glyph
->u
.ch
.face_id
);
1355 if (!glyph
->multibyte_p
)
1357 /* Unibyte case. We don't have to encode, but we have to make
1358 sure to use a face suitable for unibyte. */
1360 char2b
->byte2
= glyph
->u
.ch
.code
;
1362 else if (glyph
->u
.ch
.code
< 128
1363 && glyph
->u
.ch
.face_id
< BASIC_FACE_ID_SENTINEL
)
1365 /* Case of ASCII in a face known to fit ASCII. */
1367 char2b
->byte2
= glyph
->u
.ch
.code
;
1371 int c1
, c2
, charset
;
1373 /* Split characters into bytes. If c2 is -1 afterwards, C is
1374 really a one-byte character so that byte1 is zero. */
1375 SPLIT_CHAR (glyph
->u
.ch
.code
, charset
, c1
, c2
);
1377 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1379 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1381 /* Maybe encode the character in *CHAR2B. */
1382 if (charset
!= CHARSET_ASCII
)
1384 struct font_info
*font_info
1385 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1388 x_encode_char (glyph
->u
.ch
.code
, char2b
, font_info
);
1389 if (charset
== charset_latin_iso8859_1
)
1390 char2b
->byte2
|= 0x80;
1395 /* Make sure X resources of the face are allocated. */
1396 xassert (face
!= NULL
);
1397 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1402 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1403 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1409 struct glyph
*glyph
;
1410 enum glyph_row_area area
= it
->area
;
1412 xassert (it
->glyph_row
);
1413 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1415 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1416 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1418 /* Play it safe. If sub-structures of the glyph are not all the
1419 same size, it otherwise be that some bits stay set. This
1420 would prevent a comparison with GLYPH_EQUAL_P. */
1423 glyph
->type
= CHAR_GLYPH
;
1424 glyph
->pixel_width
= it
->pixel_width
;
1425 glyph
->u
.ch
.code
= it
->char_to_display
;
1426 glyph
->u
.ch
.face_id
= it
->face_id
;
1427 glyph
->charpos
= CHARPOS (it
->position
);
1428 glyph
->object
= it
->object
;
1429 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1430 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1431 glyph
->voffset
= it
->voffset
;
1432 glyph
->multibyte_p
= it
->multibyte_p
;
1433 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1434 || it
->phys_descent
> it
->descent
);
1435 ++it
->glyph_row
->used
[area
];
1440 /* Change IT->ascent and IT->height according to the setting of
1444 take_vertical_position_into_account (it
)
1449 if (it
->voffset
< 0)
1450 /* Increase the ascent so that we can display the text higher
1452 it
->ascent
+= abs (it
->voffset
);
1454 /* Increase the descent so that we can display the text lower
1456 it
->descent
+= it
->voffset
;
1461 /* Produce glyphs/get display metrics for the image IT is loaded with.
1462 See the description of struct display_iterator in dispextern.h for
1463 an overview of struct display_iterator. */
1466 x_produce_image_glyph (it
)
1472 xassert (it
->what
== IT_IMAGE
);
1474 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1475 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1478 /* Make sure X resources of the face and image are loaded. */
1479 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1480 prepare_image_for_display (it
->f
, img
);
1482 it
->ascent
= it
->phys_ascent
= IMAGE_ASCENT (img
);
1483 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->margin
- it
->ascent
;
1484 it
->pixel_width
= img
->width
+ 2 * img
->margin
;
1488 if (face
->box
!= FACE_NO_BOX
)
1490 it
->ascent
+= face
->box_line_width
;
1491 it
->descent
+= face
->box_line_width
;
1493 if (it
->start_of_box_run_p
)
1494 it
->pixel_width
+= face
->box_line_width
;
1495 if (it
->end_of_box_run_p
)
1496 it
->pixel_width
+= face
->box_line_width
;
1499 take_vertical_position_into_account (it
);
1503 struct glyph
*glyph
;
1504 enum glyph_row_area area
= it
->area
;
1506 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1507 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1509 glyph
->type
= IMAGE_GLYPH
;
1510 glyph
->u
.img
.id
= img
->id
;
1511 glyph
->u
.img
.face_id
= it
->face_id
;
1512 glyph
->pixel_width
= it
->pixel_width
;
1513 glyph
->charpos
= CHARPOS (it
->position
);
1514 glyph
->object
= it
->object
;
1515 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1516 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1517 glyph
->voffset
= it
->voffset
;
1518 glyph
->multibyte_p
= it
->multibyte_p
;
1519 ++it
->glyph_row
->used
[area
];
1525 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1526 of the glyph, WIDTH and HEIGHT are the width and height of the
1527 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1528 ascent of the glyph (0 <= ASCENT <= 1). */
1531 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1537 struct glyph
*glyph
;
1538 enum glyph_row_area area
= it
->area
;
1540 xassert (ascent
>= 0 && ascent
<= 1);
1542 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1543 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1545 glyph
->type
= STRETCH_GLYPH
;
1546 glyph
->u
.stretch
.ascent
= height
* ascent
;
1547 glyph
->u
.stretch
.height
= height
;
1548 glyph
->u
.stretch
.face_id
= it
->face_id
;
1549 glyph
->pixel_width
= width
;
1550 glyph
->charpos
= CHARPOS (it
->position
);
1551 glyph
->object
= object
;
1552 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1553 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1554 glyph
->voffset
= it
->voffset
;
1555 glyph
->multibyte_p
= it
->multibyte_p
;
1556 ++it
->glyph_row
->used
[area
];
1561 /* Produce a stretch glyph for iterator IT. IT->object is the value
1562 of the glyph property displayed. The value must be a list
1563 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1566 1. `:width WIDTH' specifies that the space should be WIDTH *
1567 canonical char width wide. WIDTH may be an integer or floating
1570 2. `:relative-width FACTOR' specifies that the width of the stretch
1571 should be computed from the width of the first character having the
1572 `glyph' property, and should be FACTOR times that width.
1574 3. `:align-to HPOS' specifies that the space should be wide enough
1575 to reach HPOS, a value in canonical character units.
1577 Exactly one of the above pairs must be present.
1579 4. `:height HEIGHT' specifies that the height of the stretch produced
1580 should be HEIGHT, measured in canonical character units.
1582 5. `:relative-height FACTOR' specifies that the height of the the
1583 stretch should be FACTOR times the height of the characters having
1586 Either none or exactly one of 4 or 5 must be present.
1588 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1589 of the stretch should be used for the ascent of the stretch.
1590 ASCENT must be in the range 0 <= ASCENT <= 100. */
1593 ((INTEGERP (X) || FLOATP (X)) \
1599 x_produce_stretch_glyph (it
)
1602 /* (space :width WIDTH :height HEIGHT. */
1603 extern Lisp_Object QCwidth
, QCheight
, QCascent
, Qspace
;
1604 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1605 extern Lisp_Object QCalign_to
;
1606 Lisp_Object prop
, plist
;
1607 double width
= 0, height
= 0, ascent
= 0;
1608 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1609 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1611 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1613 /* List should start with `space'. */
1614 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1615 plist
= XCDR (it
->object
);
1617 /* Compute the width of the stretch. */
1618 if (prop
= Fplist_get (plist
, QCwidth
),
1620 /* Absolute width `:width WIDTH' specified and valid. */
1621 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1622 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1625 /* Relative width `:relative-width FACTOR' specified and valid.
1626 Compute the width of the characters having the `glyph'
1629 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1632 if (it
->multibyte_p
)
1634 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1635 - IT_BYTEPOS (*it
));
1636 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1639 it2
.c
= *p
, it2
.len
= 1;
1641 it2
.glyph_row
= NULL
;
1642 it2
.what
= IT_CHARACTER
;
1643 x_produce_glyphs (&it2
);
1644 width
= NUMVAL (prop
) * it2
.pixel_width
;
1646 else if (prop
= Fplist_get (plist
, QCalign_to
),
1648 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1650 /* Nothing specified -> width defaults to canonical char width. */
1651 width
= CANON_X_UNIT (it
->f
);
1653 /* Compute height. */
1654 if (prop
= Fplist_get (plist
, QCheight
),
1656 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1657 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1659 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1661 height
= FONT_HEIGHT (font
);
1663 /* Compute percentage of height used for ascent. If
1664 `:ascent ASCENT' is present and valid, use that. Otherwise,
1665 derive the ascent from the font in use. */
1666 if (prop
= Fplist_get (plist
, QCascent
),
1667 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1668 ascent
= NUMVAL (prop
) / 100.0;
1670 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1679 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1680 if (!STRINGP (object
))
1681 object
= it
->w
->buffer
;
1682 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1685 it
->pixel_width
= width
;
1686 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1687 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1690 if (face
->box
!= FACE_NO_BOX
)
1692 it
->ascent
+= face
->box_line_width
;
1693 it
->descent
+= face
->box_line_width
;
1695 if (it
->start_of_box_run_p
)
1696 it
->pixel_width
+= face
->box_line_width
;
1697 if (it
->end_of_box_run_p
)
1698 it
->pixel_width
+= face
->box_line_width
;
1701 take_vertical_position_into_account (it
);
1705 /* Produce glyphs/get display metrics for the display element IT is
1706 loaded with. See the description of struct display_iterator in
1707 dispextern.h for an overview of struct display_iterator. */
1710 x_produce_glyphs (it
)
1713 if (it
->what
== IT_CHARACTER
)
1719 int font_not_found_p
;
1721 /* Maybe translate single-byte characters to multibyte. */
1722 it
->char_to_display
= it
->c
;
1723 if (unibyte_display_via_language_environment
1724 && SINGLE_BYTE_CHAR_P (it
->c
)
1727 && !NILP (Vnonascii_translation_table
))))
1729 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1730 it
->charset
= CHAR_CHARSET (it
->char_to_display
);
1733 /* Get face and font to use. Encode IT->char_to_display. */
1734 face
= x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1735 it
->face_id
, &char2b
,
1739 /* When no suitable font found, use the default font. */
1740 font_not_found_p
= font
== NULL
;
1741 if (font_not_found_p
)
1742 font
= FRAME_FONT (it
->f
);
1744 if (it
->char_to_display
>= ' '
1745 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1747 /* Either unibyte or ASCII. */
1752 pcm
= x_per_char_metric (font
, &char2b
);
1753 it
->ascent
= font
->ascent
;
1754 it
->descent
= font
->descent
;
1755 it
->phys_ascent
= pcm
->ascent
;
1756 it
->phys_descent
= pcm
->descent
;
1757 it
->pixel_width
= pcm
->width
;
1759 /* If this is a space inside a region of text with
1760 `space-width' property, change its width. */
1761 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1763 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1765 /* If face has a box, add the box thickness to the character
1766 height. If character has a box line to the left and/or
1767 right, add the box line width to the character's width. */
1768 if (face
->box
!= FACE_NO_BOX
)
1770 int thick
= face
->box_line_width
;
1772 it
->ascent
+= thick
;
1773 it
->descent
+= thick
;
1775 if (it
->start_of_box_run_p
)
1776 it
->pixel_width
+= thick
;
1777 if (it
->end_of_box_run_p
)
1778 it
->pixel_width
+= thick
;
1781 /* If face has an overline, add the height of the overline
1782 (1 pixel) and a 1 pixel margin to the character height. */
1783 if (face
->overline_p
)
1786 take_vertical_position_into_account (it
);
1788 /* If we have to actually produce glyphs, do it. */
1793 /* Translate a space with a `space-width' property
1794 into a stretch glyph. */
1795 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1796 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1797 it
->ascent
+ it
->descent
, ascent
);
1800 x_append_glyph (it
);
1802 /* If characters with lbearing or rbearing are displayed
1803 in this line, record that fact in a flag of the
1804 glyph row. This is used to optimize X output code. */
1805 if (pcm
->lbearing
< 0
1806 || pcm
->rbearing
> pcm
->width
)
1807 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1810 else if (it
->char_to_display
== '\n')
1812 /* A newline has no width but we need the height of the line. */
1813 it
->pixel_width
= 0;
1815 it
->ascent
= it
->phys_ascent
= font
->ascent
;
1816 it
->descent
= it
->phys_descent
= font
->descent
;
1818 if (face
->box
!= FACE_NO_BOX
)
1820 int thick
= face
->box_line_width
;
1821 it
->ascent
+= thick
;
1822 it
->descent
+= thick
;
1825 else if (it
->char_to_display
== '\t')
1827 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1828 int x
= (it
->current_x
1830 + it
->continuation_lines_width
);
1831 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1833 it
->pixel_width
= next_tab_x
- x
;
1835 it
->ascent
= it
->phys_ascent
= font
->ascent
;
1836 it
->descent
= it
->phys_descent
= font
->descent
;
1840 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1841 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1842 it
->ascent
+ it
->descent
, ascent
);
1847 /* A multi-byte character. Assume that the display width of the
1848 character is the width of the character multiplied by the
1849 width of the font. There has to be better support for
1850 variable sizes in cmpchar_info to do anything better than
1853 Note: composite characters are represented as one glyph in
1854 the glyph matrix. There are no padding glyphs. */
1855 if (it
->charset
== CHARSET_COMPOSITION
)
1857 struct cmpchar_info
*cmpcharp
;
1860 idx
= COMPOSITE_CHAR_ID (it
->char_to_display
);
1861 cmpcharp
= cmpchar_table
[idx
];
1862 it
->pixel_width
= font
->max_bounds
.width
* cmpcharp
->width
;
1864 /* There are no padding glyphs, so there is only one glyph
1865 to produce for the composite char. Important is that
1866 pixel_width, ascent and descent are the values of what is
1867 drawn by draw_glyphs. */
1870 /* These settings may not be correct. We must have more
1871 information in cmpcharp to do the correct setting. */
1872 it
->ascent
= font
->ascent
;
1873 it
->descent
= font
->descent
;
1874 it
->phys_ascent
= font
->max_bounds
.ascent
;
1875 it
->phys_descent
= font
->max_bounds
.descent
;
1879 /* If we found a font, this font should give us the right
1880 metrics. If we didn't find a font, use the frame's
1881 default font and calculate the width of the character
1882 from the charset width; this is what old redisplay code
1884 pcm
= x_per_char_metric (font
, &char2b
);
1885 it
->pixel_width
= pcm
->width
;
1886 if (font_not_found_p
)
1887 it
->pixel_width
*= CHARSET_WIDTH (it
->charset
);
1889 it
->ascent
= font
->ascent
;
1890 it
->descent
= font
->descent
;
1891 it
->phys_ascent
= pcm
->ascent
;
1892 it
->phys_descent
= pcm
->descent
;
1894 && (pcm
->lbearing
< 0
1895 || pcm
->rbearing
> pcm
->width
))
1896 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1899 if (face
->box
!= FACE_NO_BOX
)
1901 int thick
= face
->box_line_width
;
1902 it
->ascent
+= thick
;
1903 it
->descent
+= thick
;
1905 if (it
->start_of_box_run_p
)
1906 it
->pixel_width
+= thick
;
1907 if (it
->end_of_box_run_p
)
1908 it
->pixel_width
+= thick
;
1911 /* If face has an overline, add the height of the overline
1912 (1 pixel) and a 1 pixel margin to the character height. */
1913 if (face
->overline_p
)
1916 take_vertical_position_into_account (it
);
1919 x_append_glyph (it
);
1922 else if (it
->what
== IT_IMAGE
)
1923 x_produce_image_glyph (it
);
1924 else if (it
->what
== IT_STRETCH
)
1925 x_produce_stretch_glyph (it
);
1927 /* Accumulate dimensions. */
1928 xassert (it
->ascent
>= 0 && it
->descent
> 0);
1929 if (it
->area
== TEXT_AREA
)
1930 it
->current_x
+= it
->pixel_width
;
1932 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
1933 it
->max_descent
= max (it
->max_descent
, it
->descent
);
1934 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
1935 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
1939 /* Estimate the pixel height of the mode or top line on frame F.
1940 FACE_ID specifies what line's height to estimate. */
1943 x_estimate_mode_line_height (f
, face_id
)
1945 enum face_id face_id
;
1949 /* This function is called so early when Emacs starts that the face
1950 cache and mode line face are not yet initialized. */
1951 if (FRAME_FACE_CACHE (f
))
1953 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1955 height
= FONT_HEIGHT (face
->font
) + 2 * face
->box_line_width
;
1962 /***********************************************************************
1964 ***********************************************************************/
1966 /* A sequence of glyphs to be drawn in the same face.
1968 This data structure is not really completely X specific, so it
1969 could possibly, at least partially, be useful for other systems. It
1970 is currently not part of the external redisplay interface because
1971 it's not clear what other systems will need. */
1975 /* X-origin of the string. */
1978 /* Y-origin and y-position of the base line of this string. */
1981 /* The width of the string, not including a face extension. */
1984 /* The width of the string, including a face extension. */
1985 int background_width
;
1987 /* The height of this string. This is the height of the line this
1988 string is drawn in, and can be different from the height of the
1989 font the string is drawn in. */
1992 /* Number of pixels this string overwrites in front of its x-origin.
1993 This number is zero if the string has an lbearing >= 0; it is
1994 -lbearing, if the string has an lbearing < 0. */
1997 /* Number of pixels this string overwrites past its right-most
1998 nominal x-position, i.e. x + width. Zero if the string's
1999 rbearing is <= its nominal width, rbearing - width otherwise. */
2002 /* The frame on which the glyph string is drawn. */
2005 /* The window on which the glyph string is drawn. */
2008 /* X display and window for convenience. */
2012 /* The glyph row for which this string was built. It determines the
2013 y-origin and height of the string. */
2014 struct glyph_row
*row
;
2016 /* The area within row. */
2017 enum glyph_row_area area
;
2019 /* Characters to be drawn, and number of characters. */
2023 /* Character set of this glyph string. */
2026 /* A face-override for drawing cursors, mouse face and similar. */
2027 enum draw_glyphs_face hl
;
2029 /* Face in which this string is to be drawn. */
2032 /* Font in which this string is to be drawn. */
2035 /* Font info for this string. */
2036 struct font_info
*font_info
;
2038 /* Non-null means this string describes (part of) a composite
2039 character. All characters from char2b are drawn at the same
2040 x-origin in that case. */
2041 struct cmpchar_info
*cmpcharp
;
2043 /* Index of this glyph string's first character in the glyph
2044 definition of cmpcharp. If this is zero, this glyph string
2045 describes the first character of a composite character. */
2048 /* 1 means this glyph strings face has to be drawn to the right end
2049 of the window's drawing area. */
2050 unsigned extends_to_end_of_line_p
: 1;
2052 /* 1 means the background of this string has been drawn. */
2053 unsigned background_filled_p
: 1;
2055 /* 1 means glyph string must be drawn with 16-bit functions. */
2056 unsigned two_byte_p
: 1;
2058 /* 1 means that the original font determined for drawing this glyph
2059 string could not be loaded. The member `font' has been set to
2060 the frame's default font in this case. */
2061 unsigned font_not_found_p
: 1;
2063 /* 1 means that the face in which this glyph string is drawn has a
2065 unsigned stippled_p
: 1;
2067 /* 1 means only the foreground of this glyph string must be drawn,
2068 and we should use the physical height of the line this glyph
2069 string appears in as clip rect. */
2070 unsigned for_overlaps_p
: 1;
2072 /* The GC to use for drawing this glyph string. */
2075 /* A pointer to the first glyph in the string. This glyph
2076 corresponds to char2b[0]. Needed to draw rectangles if
2077 font_not_found_p is 1. */
2078 struct glyph
*first_glyph
;
2080 /* Image, if any. */
2083 struct glyph_string
*next
, *prev
;
2090 x_dump_glyph_string (s
)
2091 struct glyph_string
*s
;
2093 fprintf (stderr
, "glyph string\n");
2094 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2095 s
->x
, s
->y
, s
->width
, s
->height
);
2096 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2097 fprintf (stderr
, " hl = %d\n", s
->hl
);
2098 fprintf (stderr
, " left overhang = %d, right = %d\n",
2099 s
->left_overhang
, s
->right_overhang
);
2100 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2101 fprintf (stderr
, " extends to end of line = %d\n",
2102 s
->extends_to_end_of_line_p
);
2103 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2104 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2107 #endif /* GLYPH_DEBUG */
2111 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2112 struct glyph_string
**,
2113 struct glyph_string
*,
2114 struct glyph_string
*));
2115 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2116 struct glyph_string
**,
2117 struct glyph_string
*,
2118 struct glyph_string
*));
2119 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2120 struct glyph_string
**,
2121 struct glyph_string
*));
2122 static int x_left_overwritten
P_ ((struct glyph_string
*));
2123 static int x_left_overwriting
P_ ((struct glyph_string
*));
2124 static int x_right_overwritten
P_ ((struct glyph_string
*));
2125 static int x_right_overwriting
P_ ((struct glyph_string
*));
2126 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2128 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2129 XChar2b
*, struct window
*,
2131 enum glyph_row_area
, int,
2132 enum draw_glyphs_face
));
2133 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2134 enum glyph_row_area
, int, int,
2135 enum draw_glyphs_face
, int *, int *, int));
2136 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2137 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2138 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2140 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2141 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2142 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2143 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2144 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2145 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2146 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2147 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2149 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2150 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2151 unsigned long *, double, int));
2152 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2153 double, int, unsigned long));
2154 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2155 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2156 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2157 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2158 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2159 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2160 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2162 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2163 int, int, int, int, XRectangle
*));
2164 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2165 int, int, int, XRectangle
*));
2166 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2167 enum glyph_row_area
));
2170 /* Append the list of glyph strings with head H and tail T to the list
2171 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2174 x_append_glyph_string_lists (head
, tail
, h
, t
)
2175 struct glyph_string
**head
, **tail
;
2176 struct glyph_string
*h
, *t
;
2190 /* Prepend the list of glyph strings with head H and tail T to the
2191 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2195 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2196 struct glyph_string
**head
, **tail
;
2197 struct glyph_string
*h
, *t
;
2211 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2212 Set *HEAD and *TAIL to the resulting list. */
2215 x_append_glyph_string (head
, tail
, s
)
2216 struct glyph_string
**head
, **tail
;
2217 struct glyph_string
*s
;
2219 s
->next
= s
->prev
= NULL
;
2220 x_append_glyph_string_lists (head
, tail
, s
, s
);
2224 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2229 struct glyph_string
*s
;
2231 if (s
->font
== FRAME_FONT (s
->f
)
2232 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2233 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2235 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2238 /* Cursor on non-default face: must merge. */
2242 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2243 xgcv
.foreground
= s
->face
->background
;
2245 /* If the glyph would be invisible, try a different foreground. */
2246 if (xgcv
.foreground
== xgcv
.background
)
2247 xgcv
.foreground
= s
->face
->foreground
;
2248 if (xgcv
.foreground
== xgcv
.background
)
2249 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2250 if (xgcv
.foreground
== xgcv
.background
)
2251 xgcv
.foreground
= s
->face
->foreground
;
2253 /* Make sure the cursor is distinct from text in this face. */
2254 if (xgcv
.background
== s
->face
->background
2255 && xgcv
.foreground
== s
->face
->foreground
)
2257 xgcv
.background
= s
->face
->foreground
;
2258 xgcv
.foreground
= s
->face
->background
;
2261 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2262 xgcv
.font
= s
->font
->fid
;
2263 xgcv
.graphics_exposures
= False
;
2264 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2266 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2267 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2270 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2271 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2273 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2278 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2281 x_set_mouse_face_gc (s
)
2282 struct glyph_string
*s
;
2286 /* What face has to be used for the mouse face? */
2287 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2288 face_id
= FACE_FOR_CHARSET (s
->f
, face_id
, s
->charset
);
2289 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2290 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2292 /* If font in this face is same as S->font, use it. */
2293 if (s
->font
== s
->face
->font
)
2294 s
->gc
= s
->face
->gc
;
2297 /* Otherwise construct scratch_cursor_gc with values from FACE
2302 xgcv
.background
= s
->face
->background
;
2303 xgcv
.foreground
= s
->face
->foreground
;
2304 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2305 xgcv
.font
= s
->font
->fid
;
2306 xgcv
.graphics_exposures
= False
;
2307 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2309 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2310 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2313 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2314 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2316 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2319 xassert (s
->gc
!= 0);
2323 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2324 Faces to use in the mode line have already been computed when the
2325 matrix was built, so there isn't much to do, here. */
2328 x_set_mode_line_face_gc (s
)
2329 struct glyph_string
*s
;
2331 s
->gc
= s
->face
->gc
;
2332 xassert (s
->gc
!= 0);
2336 /* Set S->gc of glyph string S for drawing that glyph string. Set
2337 S->stippled_p to a non-zero value if the face of S has a stipple
2341 x_set_glyph_string_gc (s
)
2342 struct glyph_string
*s
;
2344 if (s
->hl
== DRAW_NORMAL_TEXT
)
2346 s
->gc
= s
->face
->gc
;
2347 s
->stippled_p
= s
->face
->stipple
!= 0;
2349 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2351 x_set_mode_line_face_gc (s
);
2352 s
->stippled_p
= s
->face
->stipple
!= 0;
2354 else if (s
->hl
== DRAW_CURSOR
)
2356 x_set_cursor_gc (s
);
2359 else if (s
->hl
== DRAW_MOUSE_FACE
)
2361 x_set_mouse_face_gc (s
);
2362 s
->stippled_p
= s
->face
->stipple
!= 0;
2364 else if (s
->hl
== DRAW_IMAGE_RAISED
2365 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2367 s
->gc
= s
->face
->gc
;
2368 s
->stippled_p
= s
->face
->stipple
!= 0;
2372 s
->gc
= s
->face
->gc
;
2373 s
->stippled_p
= s
->face
->stipple
!= 0;
2376 /* GC must have been set. */
2377 xassert (s
->gc
!= 0);
2381 /* Return in *R the clipping rectangle for glyph string S. */
2384 x_get_glyph_string_clip_rect (s
, r
)
2385 struct glyph_string
*s
;
2388 if (s
->row
->full_width_p
)
2390 /* Draw full-width. X coordinates are relative to S->w->left. */
2391 int canon_x
= CANON_X_UNIT (s
->f
);
2393 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2394 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2396 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2398 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2399 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2403 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2405 /* Unless displaying a mode or menu bar line, which are always
2406 fully visible, clip to the visible part of the row. */
2407 if (s
->w
->pseudo_window_p
)
2408 r
->height
= s
->row
->visible_height
;
2410 r
->height
= s
->height
;
2414 /* This is a text line that may be partially visible. */
2415 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2416 r
->width
= window_box_width (s
->w
, s
->area
);
2417 r
->height
= s
->row
->visible_height
;
2420 /* Don't use S->y for clipping because it doesn't take partially
2421 visible lines into account. For example, it can be negative for
2422 partially visible lines at the top of a window. */
2423 if (!s
->row
->full_width_p
2424 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2425 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2427 r
->y
= max (0, s
->row
->y
);
2429 /* If drawing a tool-bar window, draw it over the internal border
2430 at the top of the window. */
2431 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2432 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2434 /* If S draws overlapping rows, it's sufficient to use the top and
2435 bottom of the window for clipping because this glyph string
2436 intentionally draws over other lines. */
2437 if (s
->for_overlaps_p
)
2439 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2440 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2443 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2447 /* Set clipping for output of glyph string S. S may be part of a mode
2448 line or menu if we don't have X toolkit support. */
2451 x_set_glyph_string_clipping (s
)
2452 struct glyph_string
*s
;
2455 x_get_glyph_string_clip_rect (s
, &r
);
2456 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2460 /* Compute left and right overhang of glyph string S. If S is a glyph
2461 string for a composite character, assume overhangs don't exist. */
2464 x_compute_glyph_string_overhangs (s
)
2465 struct glyph_string
*s
;
2467 if (s
->cmpcharp
== NULL
2468 && s
->first_glyph
->type
== CHAR_GLYPH
)
2471 int direction
, font_ascent
, font_descent
;
2472 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2473 &font_ascent
, &font_descent
, &cs
);
2474 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2475 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2480 /* Compute overhangs and x-positions for glyph string S and its
2481 predecessors, or successors. X is the starting x-position for S.
2482 BACKWARD_P non-zero means process predecessors. */
2485 x_compute_overhangs_and_x (s
, x
, backward_p
)
2486 struct glyph_string
*s
;
2494 x_compute_glyph_string_overhangs (s
);
2504 x_compute_glyph_string_overhangs (s
);
2513 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2514 frame F. Overhangs of glyphs other than type CHAR_GLYPH or of
2515 character glyphs for composite characters are assumed to be zero. */
2518 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2519 struct glyph
*glyph
;
2527 if (glyph
->type
== CHAR_GLYPH
2528 && (c
= glyph
->u
.ch
.code
,
2529 CHAR_CHARSET (c
) != CHARSET_COMPOSITION
))
2533 struct font_info
*font_info
;
2536 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
);
2538 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2541 XCharStruct
*pcm
= x_per_char_metric (font
, &char2b
);
2543 if (pcm
->rbearing
> pcm
->width
)
2544 *right
= pcm
->rbearing
- pcm
->width
;
2545 if (pcm
->lbearing
< 0)
2546 *left
= -pcm
->lbearing
;
2552 /* Return the index of the first glyph preceding glyph string S that
2553 is overwritten by S because of S's left overhang. Value is -1
2554 if no glyphs are overwritten. */
2557 x_left_overwritten (s
)
2558 struct glyph_string
*s
;
2562 if (s
->left_overhang
)
2565 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2566 int first
= s
->first_glyph
- glyphs
;
2568 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2569 x
-= glyphs
[i
].pixel_width
;
2580 /* Return the index of the first glyph preceding glyph string S that
2581 is overwriting S because of its right overhang. Value is -1 if no
2582 glyph in front of S overwrites S. */
2585 x_left_overwriting (s
)
2586 struct glyph_string
*s
;
2589 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2590 int first
= s
->first_glyph
- glyphs
;
2594 for (i
= first
- 1; i
>= 0; --i
)
2597 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2600 x
-= glyphs
[i
].pixel_width
;
2607 /* Return the index of the last glyph following glyph string S that is
2608 not overwritten by S because of S's right overhang. Value is -1 if
2609 no such glyph is found. */
2612 x_right_overwritten (s
)
2613 struct glyph_string
*s
;
2617 if (s
->right_overhang
)
2620 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2621 int first
= (s
->first_glyph
- glyphs
) + (s
->cmpcharp
? 1 : s
->nchars
);
2622 int end
= s
->row
->used
[s
->area
];
2624 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
2625 x
+= glyphs
[i
].pixel_width
;
2634 /* Return the index of the last glyph following glyph string S that
2635 overwrites S because of its left overhang. Value is negative
2636 if no such glyph is found. */
2639 x_right_overwriting (s
)
2640 struct glyph_string
*s
;
2643 int end
= s
->row
->used
[s
->area
];
2644 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2645 int first
= (s
->first_glyph
- glyphs
) + (s
->cmpcharp
? 1 : s
->nchars
);
2649 for (i
= first
; i
< end
; ++i
)
2652 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2655 x
+= glyphs
[i
].pixel_width
;
2662 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2665 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2666 struct glyph_string
*s
;
2670 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
2671 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2672 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2673 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2677 /* Draw the background of glyph_string S. If S->background_filled_p
2678 is non-zero don't draw it. FORCE_P non-zero means draw the
2679 background even if it wouldn't be drawn normally. This is used
2680 when a string preceding S draws into the background of S. */
2683 x_draw_glyph_string_background (s
, force_p
)
2684 struct glyph_string
*s
;
2687 /* Nothing to do if background has already been drawn or if it
2688 shouldn't be drawn in the first place. */
2689 if (!s
->background_filled_p
)
2693 && !s
->font_not_found_p
2694 && !s
->extends_to_end_of_line_p
)
2696 /* Don't draw background for glyphs of a composite
2697 characters, except for the first one. */
2698 s
->background_filled_p
= 1;
2700 else if (s
->stippled_p
)
2702 /* Fill background with a stipple pattern. */
2703 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2704 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2705 s
->y
+ s
->face
->box_line_width
,
2706 s
->background_width
,
2707 s
->height
- 2 * s
->face
->box_line_width
);
2708 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2709 s
->background_filled_p
= 1;
2711 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * s
->face
->box_line_width
2712 || s
->font_not_found_p
2713 || s
->extends_to_end_of_line_p
2717 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ s
->face
->box_line_width
,
2718 s
->background_width
,
2719 s
->height
- 2 * s
->face
->box_line_width
);
2720 s
->background_filled_p
= 1;
2726 /* Draw the foreground of glyph string S. */
2729 x_draw_glyph_string_foreground (s
)
2730 struct glyph_string
*s
;
2734 /* If first glyph of S has a left box line, start drawing the text
2735 of S to the right of that box line. */
2736 if (s
->face
->box
!= FACE_NO_BOX
2737 && s
->first_glyph
->left_box_line_p
)
2738 x
= s
->x
+ s
->face
->box_line_width
;
2742 if (s
->cmpcharp
== NULL
)
2744 /* Not a composite character. Draw characters of S as
2745 rectangles if S's font could not be loaded. */
2746 if (s
->font_not_found_p
)
2748 for (i
= 0; i
< s
->nchars
; ++i
)
2750 struct glyph
*g
= s
->first_glyph
+ i
;
2751 XDrawRectangle (s
->display
, s
->window
,
2752 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2754 x
+= g
->pixel_width
;
2759 char *char1b
= (char *) s
->char2b
;
2761 /* If we can use 8-bit functions, condense S->char2b. */
2763 for (i
= 0; i
< s
->nchars
; ++i
)
2764 char1b
[i
] = s
->char2b
[i
].byte2
;
2766 /* Draw text with XDrawString if background has already been
2767 filled. Otherwise, use XDrawImageString. (Note that
2768 XDrawImageString is usually faster than XDrawString.)
2769 Always use XDrawImageString when drawing the cursor so
2770 that there is no chance that characters under a box
2771 cursor are invisible. */
2772 if (s
->for_overlaps_p
2773 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2775 /* Draw characters with 16-bit or 8-bit functions. */
2777 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
, s
->ybase
,
2778 s
->char2b
, s
->nchars
);
2780 XDrawString (s
->display
, s
->window
, s
->gc
, x
, s
->ybase
,
2786 XDrawImageString16 (s
->display
, s
->window
, s
->gc
,
2787 x
, s
->ybase
, s
->char2b
, s
->nchars
);
2789 XDrawImageString (s
->display
, s
->window
, s
->gc
,
2790 x
, s
->ybase
, char1b
, s
->nchars
);
2796 /* S is a glyph string for a composite character. S->gidx is the
2797 index of the first character drawn in the vector
2798 S->cmpcharp->glyph. S->gidx == 0 means we are drawing the
2799 very first component character of a composite char. */
2801 /* Draw a single rectangle for the composite character if S's
2802 font could not be loaded. */
2803 if (s
->font_not_found_p
&& s
->gidx
== 0)
2804 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2805 s
->width
- 1, s
->height
- 1);
2809 int relative_compose
, default_ascent
, i
;
2810 int highest
= 0, lowest
= 0;
2812 /* The value of font_info my be null if we couldn't find it
2813 in x_get_char_face_and_encoding. */
2814 if (s
->cmpcharp
->cmp_rule
== NULL
&& s
->font_info
)
2816 relative_compose
= s
->font_info
->relative_compose
;
2817 default_ascent
= s
->font_info
->default_ascent
;
2820 relative_compose
= default_ascent
= 0;
2822 if ((s
->cmpcharp
->cmp_rule
|| relative_compose
)
2825 /* This is the first character. Initialize variables.
2826 Highest is the highest position of glyphs ever
2827 written, lowest the lowest position. */
2829 int first_ch
= s
->first_glyph
->u
.ch
.code
;
2832 && CHAR_TABLE_P (Vuse_default_ascent
)
2833 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
2835 highest
= default_ascent
;
2840 pcm
= PER_CHAR_METRIC (s
->font
, s
->char2b
);
2841 highest
= pcm
->ascent
+ 1;
2842 lowest
= - pcm
->descent
;
2845 if (s
->cmpcharp
->cmp_rule
)
2846 x_offset
= (s
->cmpcharp
->col_offset
[0]
2847 * FONT_WIDTH (s
->f
->output_data
.x
->font
));
2849 /* Draw the first character at the normal position. */
2850 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2852 s
->ybase
, s
->char2b
, 1);
2859 for (; i
< s
->nchars
; i
++, ++s
->gidx
)
2861 int x_offset
= 0, y_offset
= 0;
2863 if (relative_compose
)
2865 pcm
= PER_CHAR_METRIC (s
->font
, s
->char2b
+ i
);
2866 if (NILP (Vignore_relative_composition
)
2867 || NILP (Faref (Vignore_relative_composition
,
2868 make_number (s
->cmpcharp
->glyph
[s
->gidx
]))))
2870 if (- pcm
->descent
>= relative_compose
)
2872 /* Draw above the current glyphs. */
2873 y_offset
= highest
+ pcm
->descent
;
2874 highest
+= pcm
->ascent
+ pcm
->descent
;
2876 else if (pcm
->ascent
<= 0)
2878 /* Draw beneath the current glyphs. */
2879 y_offset
= lowest
- pcm
->ascent
;
2880 lowest
-= pcm
->ascent
+ pcm
->descent
;
2885 /* Draw the glyph at normal position. If
2886 it sticks out of HIGHEST or LOWEST,
2887 update them appropriately. */
2888 if (pcm
->ascent
> highest
)
2889 highest
= pcm
->ascent
;
2890 else if (- pcm
->descent
< lowest
)
2891 lowest
= - pcm
->descent
;
2894 else if (s
->cmpcharp
->cmp_rule
)
2896 int gref
= (s
->cmpcharp
->cmp_rule
[s
->gidx
] - 0xA0) / 9;
2897 int nref
= (s
->cmpcharp
->cmp_rule
[s
->gidx
] - 0xA0) % 9;
2900 /* Re-encode GREF and NREF so that they specify
2901 only Y-axis information:
2902 0:top, 1:base, 2:bottom, 3:center */
2903 gref
= gref
/ 3 + (gref
== 4) * 2;
2904 nref
= nref
/ 3 + (nref
== 4) * 2;
2906 pcm
= PER_CHAR_METRIC (s
->font
, s
->char2b
+ i
);
2907 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
2908 : gref
== 2 ? lowest
2909 : (highest
+ lowest
) / 2)
2910 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
2911 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
2912 : (pcm
->ascent
+ pcm
->descent
) / 2));
2913 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
2916 if (bottom
< lowest
)
2918 y_offset
= bottom
+ pcm
->descent
;
2919 x_offset
= (s
->cmpcharp
->col_offset
[s
->gidx
]
2920 * FONT_WIDTH (FRAME_FONT (s
->f
)));
2923 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2924 x
+ x_offset
, s
->ybase
- y_offset
,
2932 #ifdef USE_X_TOOLKIT
2934 /* Allocate the color COLOR->pixel on the screen and display of
2935 widget WIDGET in colormap CMAP. If an exact match cannot be
2936 allocated, try the nearest color available. Value is non-zero
2937 if successful. This is called from lwlib. */
2940 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2946 struct x_display_info
*dpyinfo
;
2949 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2951 /* Find the top-level shell of the widget. Note that this function
2952 can be called when the widget is not yet realized, so XtWindow
2953 (widget) == 0. That's the reason we can't simply use
2954 x_any_window_to_frame. */
2955 while (!XtIsTopLevelShell (widget
))
2956 widget
= XtParent (widget
);
2958 /* Look for a frame with that top-level widget. Allocate the color
2959 on that frame to get the right gamma correction value. */
2960 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2961 if (GC_FRAMEP (XCAR (tail
))
2962 && (f
= XFRAME (XCAR (tail
)),
2963 (f
->output_data
.nothing
!= 1
2964 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2965 && f
->output_data
.x
->widget
== widget
)
2966 return x_alloc_nearest_color (f
, cmap
, color
);
2971 #endif /* USE_X_TOOLKIT */
2974 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2975 CMAP. If an exact match can't be allocated, try the nearest color
2976 available. Value is non-zero if successful. Set *COLOR to the
2980 x_alloc_nearest_color (f
, cmap
, color
)
2985 Display
*display
= FRAME_X_DISPLAY (f
);
2986 Screen
*screen
= FRAME_X_SCREEN (f
);
2989 gamma_correct (f
, color
);
2990 rc
= XAllocColor (display
, cmap
, color
);
2993 /* If we got to this point, the colormap is full, so we're going
2994 to try to get the next closest color. The algorithm used is
2995 a least-squares matching, which is what X uses for closest
2996 color matching with StaticColor visuals. */
2998 unsigned long nearest_delta
= ~0;
2999 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3000 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3002 for (i
= 0; i
< ncells
; ++i
)
3004 XQueryColors (display
, cmap
, cells
, ncells
);
3006 for (nearest
= i
= 0; i
< ncells
; ++i
)
3008 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3009 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3010 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3011 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3013 if (delta
< nearest_delta
)
3016 nearest_delta
= delta
;
3020 color
->red
= cells
[nearest
].red
;
3021 color
->green
= cells
[nearest
].green
;
3022 color
->blue
= cells
[nearest
].blue
;
3023 rc
= XAllocColor (display
, cmap
, color
);
3030 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3031 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3032 If this produces the same color as PIXEL, try a color where all RGB
3033 values have DELTA added. Return the allocated color in *PIXEL.
3034 DISPLAY is the X display, CMAP is the colormap to operate on.
3035 Value is non-zero if successful. */
3038 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3042 unsigned long *pixel
;
3049 /* Get RGB color values. */
3050 color
.pixel
= *pixel
;
3051 XQueryColor (display
, cmap
, &color
);
3053 /* Change RGB values by specified FACTOR. Avoid overflow! */
3054 xassert (factor
>= 0);
3055 new.red
= min (0xffff, factor
* color
.red
);
3056 new.green
= min (0xffff, factor
* color
.green
);
3057 new.blue
= min (0xffff, factor
* color
.blue
);
3059 /* Try to allocate the color. */
3060 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3063 if (new.pixel
== *pixel
)
3065 /* If we end up with the same color as before, try adding
3066 delta to the RGB values. */
3067 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
3069 /* If display has an immutable color map, freeing colors is
3070 not necessary and some servers don't allow it. So don't
3072 if (class != StaticColor
3073 && class != StaticGray
3074 && class != TrueColor
)
3075 XFreeColors (display
, cmap
, &new.pixel
, 1, 0);
3077 new.red
= min (0xffff, delta
+ color
.red
);
3078 new.green
= min (0xffff, delta
+ color
.green
);
3079 new.blue
= min (0xffff, delta
+ color
.blue
);
3080 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3091 /* Set up the foreground color for drawing relief lines of glyph
3092 string S. RELIEF is a pointer to a struct relief containing the GC
3093 with which lines will be drawn. Use a color that is FACTOR or
3094 DELTA lighter or darker than the relief's background which is found
3095 in S->f->output_data.x->relief_background. If such a color cannot
3096 be allocated, use DEFAULT_PIXEL, instead. */
3099 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3101 struct relief
*relief
;
3104 unsigned long default_pixel
;
3107 struct x_output
*di
= f
->output_data
.x
;
3108 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3109 unsigned long pixel
;
3110 unsigned long background
= di
->relief_background
;
3111 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3112 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3113 Display
*dpy
= FRAME_X_DISPLAY (f
);
3115 xgcv
.graphics_exposures
= False
;
3116 xgcv
.line_width
= 1;
3118 /* Free previously allocated color. The color cell will be reused
3119 when it has been freed as many times as it was allocated, so this
3120 doesn't affect faces using the same colors. */
3122 && relief
->allocated_p
)
3124 /* If display has an immutable color map, freeing colors is not
3125 necessary and some servers don't allow it. So don't do it. */
3126 int class = dpyinfo
->visual
->class;
3127 if (class != StaticColor
3128 && class != StaticGray
3129 && class != TrueColor
)
3130 XFreeColors (dpy
, cmap
, &relief
->pixel
, 1, 0);
3131 relief
->allocated_p
= 0;
3134 /* Allocate new color. */
3135 xgcv
.foreground
= default_pixel
;
3137 if (dpyinfo
->n_planes
!= 1
3138 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3140 relief
->allocated_p
= 1;
3141 xgcv
.foreground
= relief
->pixel
= pixel
;
3144 if (relief
->gc
== 0)
3146 xgcv
.stipple
= dpyinfo
->gray
;
3148 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3151 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3155 /* Set up colors for the relief lines around glyph string S. */
3158 x_setup_relief_colors (s
)
3159 struct glyph_string
*s
;
3161 struct x_output
*di
= s
->f
->output_data
.x
;
3162 unsigned long color
;
3164 if (s
->face
->use_box_color_for_shadows_p
)
3165 color
= s
->face
->box_color
;
3170 /* Get the background color of the face. */
3171 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3172 color
= xgcv
.background
;
3175 if (di
->white_relief
.gc
== 0
3176 || color
!= di
->relief_background
)
3178 di
->relief_background
= color
;
3179 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3180 WHITE_PIX_DEFAULT (s
->f
));
3181 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3182 BLACK_PIX_DEFAULT (s
->f
));
3187 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3188 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3189 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3190 relief. LEFT_P non-zero means draw a relief on the left side of
3191 the rectangle. RIGHT_P non-zero means draw a relief on the right
3192 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3196 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3197 raised_p
, left_p
, right_p
, clip_rect
)
3199 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3200 XRectangle
*clip_rect
;
3206 gc
= f
->output_data
.x
->white_relief
.gc
;
3208 gc
= f
->output_data
.x
->black_relief
.gc
;
3209 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3212 for (i
= 0; i
< width
; ++i
)
3213 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3214 left_x
+ i
* left_p
, top_y
+ i
,
3215 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3219 for (i
= 0; i
< width
; ++i
)
3220 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3221 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3223 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3225 gc
= f
->output_data
.x
->black_relief
.gc
;
3227 gc
= f
->output_data
.x
->white_relief
.gc
;
3228 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3231 for (i
= 0; i
< width
; ++i
)
3232 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3233 left_x
+ i
* left_p
, bottom_y
- i
,
3234 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3238 for (i
= 0; i
< width
; ++i
)
3239 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3240 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3242 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3246 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3247 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3248 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3249 left side of the rectangle. RIGHT_P non-zero means draw a line
3250 on the right side of the rectangle. CLIP_RECT is the clipping
3251 rectangle to use when drawing. */
3254 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3255 left_p
, right_p
, clip_rect
)
3256 struct glyph_string
*s
;
3257 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3258 XRectangle
*clip_rect
;
3262 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3263 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3264 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3267 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3268 left_x
, top_y
, right_x
- left_x
, width
);
3272 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3273 left_x
, top_y
, width
, bottom_y
- top_y
);
3276 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3277 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
3281 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3282 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
3284 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3285 XSetClipMask (s
->display
, s
->gc
, None
);
3289 /* Draw a box around glyph string S. */
3292 x_draw_glyph_string_box (s
)
3293 struct glyph_string
*s
;
3295 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3296 int left_p
, right_p
;
3297 struct glyph
*last_glyph
;
3298 XRectangle clip_rect
;
3300 last_x
= window_box_right (s
->w
, s
->area
);
3301 if (s
->row
->full_width_p
3302 && !s
->w
->pseudo_window_p
)
3304 last_x
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s
->f
);
3305 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3306 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3309 /* The glyph that may have a right box line. */
3310 last_glyph
= (s
->cmpcharp
|| s
->img
3312 : s
->first_glyph
+ s
->nchars
- 1);
3314 width
= s
->face
->box_line_width
;
3315 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3317 right_x
= ((s
->row
->full_width_p
3319 : min (last_x
, s
->x
+ s
->background_width
) - 1));
3321 bottom_y
= top_y
+ s
->height
- 1;
3323 left_p
= (s
->first_glyph
->left_box_line_p
3324 || (s
->hl
== DRAW_MOUSE_FACE
3326 || s
->prev
->hl
!= s
->hl
)));
3327 right_p
= (last_glyph
->right_box_line_p
3328 || (s
->hl
== DRAW_MOUSE_FACE
3330 || s
->next
->hl
!= s
->hl
)));
3332 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3334 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3335 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3336 left_p
, right_p
, &clip_rect
);
3339 x_setup_relief_colors (s
);
3340 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3341 width
, raised_p
, left_p
, right_p
, &clip_rect
);
3346 /* Draw foreground of image glyph string S. */
3349 x_draw_image_foreground (s
)
3350 struct glyph_string
*s
;
3353 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3355 /* If first glyph of S has a left box line, start drawing it to the
3356 right of that line. */
3357 if (s
->face
->box
!= FACE_NO_BOX
3358 && s
->first_glyph
->left_box_line_p
)
3359 x
= s
->x
+ s
->face
->box_line_width
;
3363 /* If there is a margin around the image, adjust x- and y-position
3367 x
+= s
->img
->margin
;
3368 y
+= s
->img
->margin
;
3375 /* We can't set both a clip mask and use XSetClipRectangles
3376 because the latter also sets a clip mask. We also can't
3377 trust on the shape extension to be available
3378 (XShapeCombineRegion). So, compute the rectangle to draw
3380 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3383 XRectangle clip_rect
, image_rect
, r
;
3385 xgcv
.clip_mask
= s
->img
->mask
;
3386 xgcv
.clip_x_origin
= x
;
3387 xgcv
.clip_y_origin
= y
;
3388 xgcv
.function
= GXcopy
;
3389 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3391 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3394 image_rect
.width
= s
->img
->width
;
3395 image_rect
.height
= s
->img
->height
;
3396 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3397 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3398 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3402 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3403 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3405 /* When the image has a mask, we can expect that at
3406 least part of a mouse highlight or a block cursor will
3407 be visible. If the image doesn't have a mask, make
3408 a block cursor visible by drawing a rectangle around
3409 the image. I believe it's looking better if we do
3410 nothing here for mouse-face. */
3411 if (s
->hl
== DRAW_CURSOR
)
3412 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3413 s
->img
->width
- 1, s
->img
->height
- 1);
3417 /* Draw a rectangle if image could not be loaded. */
3418 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3419 s
->img
->width
- 1, s
->img
->height
- 1);
3423 /* Draw a relief around the image glyph string S. */
3426 x_draw_image_relief (s
)
3427 struct glyph_string
*s
;
3429 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3432 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3434 /* If first glyph of S has a left box line, start drawing it to the
3435 right of that line. */
3436 if (s
->face
->box
!= FACE_NO_BOX
3437 && s
->first_glyph
->left_box_line_p
)
3438 x
= s
->x
+ s
->face
->box_line_width
;
3442 /* If there is a margin around the image, adjust x- and y-position
3446 x
+= s
->img
->margin
;
3447 y
+= s
->img
->margin
;
3450 if (s
->hl
== DRAW_IMAGE_SUNKEN
3451 || s
->hl
== DRAW_IMAGE_RAISED
)
3453 thick
= tool_bar_button_relief
> 0 ? tool_bar_button_relief
: 3;
3454 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3458 thick
= abs (s
->img
->relief
);
3459 raised_p
= s
->img
->relief
> 0;
3464 x1
= x
+ s
->img
->width
+ thick
- 1;
3465 y1
= y
+ s
->img
->height
+ thick
- 1;
3467 x_setup_relief_colors (s
);
3468 x_get_glyph_string_clip_rect (s
, &r
);
3469 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
3473 /* Draw the foreground of image glyph string S to PIXMAP. */
3476 x_draw_image_foreground_1 (s
, pixmap
)
3477 struct glyph_string
*s
;
3481 int y
= s
->ybase
- s
->y
- IMAGE_ASCENT (s
->img
);
3483 /* If first glyph of S has a left box line, start drawing it to the
3484 right of that line. */
3485 if (s
->face
->box
!= FACE_NO_BOX
3486 && s
->first_glyph
->left_box_line_p
)
3487 x
= s
->face
->box_line_width
;
3491 /* If there is a margin around the image, adjust x- and y-position
3495 x
+= s
->img
->margin
;
3496 y
+= s
->img
->margin
;
3503 /* We can't set both a clip mask and use XSetClipRectangles
3504 because the latter also sets a clip mask. We also can't
3505 trust on the shape extension to be available
3506 (XShapeCombineRegion). So, compute the rectangle to draw
3508 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3512 xgcv
.clip_mask
= s
->img
->mask
;
3513 xgcv
.clip_x_origin
= x
;
3514 xgcv
.clip_y_origin
= y
;
3515 xgcv
.function
= GXcopy
;
3516 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3518 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3519 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3520 XSetClipMask (s
->display
, s
->gc
, None
);
3524 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3525 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3527 /* When the image has a mask, we can expect that at
3528 least part of a mouse highlight or a block cursor will
3529 be visible. If the image doesn't have a mask, make
3530 a block cursor visible by drawing a rectangle around
3531 the image. I believe it's looking better if we do
3532 nothing here for mouse-face. */
3533 if (s
->hl
== DRAW_CURSOR
)
3534 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3535 s
->img
->width
- 1, s
->img
->height
- 1);
3539 /* Draw a rectangle if image could not be loaded. */
3540 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3541 s
->img
->width
- 1, s
->img
->height
- 1);
3545 /* Draw part of the background of glyph string S. X, Y, W, and H
3546 give the rectangle to draw. */
3549 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3550 struct glyph_string
*s
;
3555 /* Fill background with a stipple pattern. */
3556 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3557 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3558 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3561 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3565 /* Draw image glyph string S.
3568 s->x +-------------------------
3571 | +-------------------------
3574 | | +-------------------
3580 x_draw_image_glyph_string (s
)
3581 struct glyph_string
*s
;
3584 int box_line_width
= s
->face
->box_line_width
;
3585 int margin
= s
->img
->margin
;
3587 Pixmap pixmap
= None
;
3589 height
= s
->height
- 2 * box_line_width
;
3591 /* Fill background with face under the image. Do it only if row is
3592 taller than image or if image has a clip mask to reduce
3594 s
->stippled_p
= s
->face
->stipple
!= 0;
3595 if (height
> s
->img
->height
3598 || s
->img
->pixmap
== 0
3599 || s
->width
!= s
->background_width
)
3601 if (box_line_width
&& s
->first_glyph
->left_box_line_p
)
3602 x
= s
->x
+ box_line_width
;
3606 y
= s
->y
+ box_line_width
;
3610 /* Create a pixmap as large as the glyph string Fill it with
3611 the background color. Copy the image to it, using its
3612 mask. Copy the temporary pixmap to the display. */
3613 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
3614 int depth
= DefaultDepthOfScreen (screen
);
3616 /* Create a pixmap as large as the glyph string. */
3617 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3618 s
->background_width
,
3621 /* Don't clip in the following because we're working on the
3623 XSetClipMask (s
->display
, s
->gc
, None
);
3625 /* Fill the pixmap with the background color/stipple. */
3628 /* Fill background with a stipple pattern. */
3629 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3630 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3631 0, 0, s
->background_width
, s
->height
);
3632 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3637 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3639 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3640 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3641 0, 0, s
->background_width
, s
->height
);
3642 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3646 /* Implementation idea: Is it possible to construct a mask?
3647 We could look at the color at the margins of the image, and
3648 say that this color is probably the background color of the
3650 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3652 s
->background_filled_p
= 1;
3655 /* Draw the foreground. */
3658 x_draw_image_foreground_1 (s
, pixmap
);
3659 x_set_glyph_string_clipping (s
);
3660 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
3661 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3662 XFreePixmap (s
->display
, pixmap
);
3665 x_draw_image_foreground (s
);
3667 /* If we must draw a relief around the image, do it. */
3669 || s
->hl
== DRAW_IMAGE_RAISED
3670 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3671 x_draw_image_relief (s
);
3675 /* Draw stretch glyph string S. */
3678 x_draw_stretch_glyph_string (s
)
3679 struct glyph_string
*s
;
3681 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3682 s
->stippled_p
= s
->face
->stipple
!= 0;
3684 if (s
->hl
== DRAW_CURSOR
3685 && !x_stretch_cursor_p
)
3687 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3688 as wide as the stretch glyph. */
3689 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
3692 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3694 /* Clear rest using the GC of the original non-cursor face. */
3695 if (width
< s
->background_width
)
3697 GC gc
= s
->face
->gc
;
3698 int x
= s
->x
+ width
, y
= s
->y
;
3699 int w
= s
->background_width
- width
, h
= s
->height
;
3702 x_get_glyph_string_clip_rect (s
, &r
);
3703 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
3705 if (s
->face
->stipple
)
3707 /* Fill background with a stipple pattern. */
3708 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3709 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3710 XSetFillStyle (s
->display
, gc
, FillSolid
);
3715 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3716 XSetForeground (s
->display
, gc
, xgcv
.background
);
3717 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3718 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3723 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3726 s
->background_filled_p
= 1;
3730 /* Draw glyph string S. */
3733 x_draw_glyph_string (s
)
3734 struct glyph_string
*s
;
3736 /* If S draws into the background of its successor, draw the
3737 background of the successor first so that S can draw into it.
3738 This makes S->next use XDrawString instead of XDrawImageString. */
3739 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3741 xassert (s
->next
->img
== NULL
);
3742 x_set_glyph_string_gc (s
->next
);
3743 x_set_glyph_string_clipping (s
->next
);
3744 x_draw_glyph_string_background (s
->next
, 1);
3747 /* Set up S->gc, set clipping and draw S. */
3748 x_set_glyph_string_gc (s
);
3749 x_set_glyph_string_clipping (s
);
3751 switch (s
->first_glyph
->type
)
3754 x_draw_image_glyph_string (s
);
3758 x_draw_stretch_glyph_string (s
);
3762 if (s
->for_overlaps_p
)
3763 s
->background_filled_p
= 1;
3765 x_draw_glyph_string_background (s
, 0);
3766 x_draw_glyph_string_foreground (s
);
3773 if (!s
->for_overlaps_p
)
3775 /* Draw underline. */
3776 if (s
->face
->underline_p
)
3778 unsigned long dy
, h
;
3780 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3782 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &dy
))
3785 if (s
->face
->underline_defaulted_p
)
3786 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3791 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3792 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3793 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3795 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3799 /* Draw overline. */
3800 if (s
->face
->overline_p
)
3802 unsigned long dy
= 0, h
= 1;
3804 if (s
->face
->overline_color_defaulted_p
)
3805 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3810 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3811 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3812 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3814 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3818 /* Draw strike-through. */
3819 if (s
->face
->strike_through_p
)
3821 unsigned long h
= 1;
3822 unsigned long dy
= (s
->height
- h
) / 2;
3824 if (s
->face
->strike_through_color_defaulted_p
)
3825 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3830 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3831 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3832 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3834 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3839 if (s
->face
->box
!= FACE_NO_BOX
)
3840 x_draw_glyph_string_box (s
);
3843 /* Reset clipping. */
3844 XSetClipMask (s
->display
, s
->gc
, None
);
3848 /* A work-list entry used during the construction of glyph_string
3849 structures for a composite character. */
3853 /* Pointer to composite char info defining has the composite
3854 character is drawn. */
3855 struct cmpchar_info
*cmpcharp
;
3857 /* Start index in compcharp->glyph[]. */
3860 /* Next in stack. */
3865 static void x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
3866 int, struct work
**,
3867 struct work
**, int));
3870 /* Load glyph string S with information from the top of *STACK for a
3871 composite character. FACE_ID is the id of the face in which S is
3872 drawn. *NEW is a pointer to a struct work not on the stack, that
3873 can be used if this function needs to push a new structure on the
3874 stack. If it uses it, *NEW is set to null. OVERLAPS_P non-zero
3875 means S should draw the foreground only, and use its lines physical
3876 height for clipping. */
3879 x_fill_composite_glyph_string (s
, face_id
, stack
, new, overlaps_p
)
3880 struct glyph_string
*s
;
3882 struct work
**stack
, **new;
3888 xassert (s
&& *new && *stack
);
3890 s
->for_overlaps_p
= 1;
3892 /* Pop the work stack. */
3894 *stack
= work
->next
;
3896 /* For all glyphs of cmpcharp->glyph, starting at the offset
3897 work->offset, until we reach the end of the definition or
3898 encounter another composite char, get the font and face to use,
3900 for (i
= work
->gidx
; i
< work
->cmpcharp
->glyph_len
; ++i
)
3902 c
= FAST_GLYPH_CHAR (work
->cmpcharp
->glyph
[i
]);
3903 if (CHAR_CHARSET (c
) == CHARSET_COMPOSITION
)
3905 s
->face
= x_get_char_face_and_encoding (s
->f
, c
, face_id
,
3906 s
->char2b
+ s
->nchars
, 1);
3907 s
->font
= s
->face
->font
;
3908 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
3912 /* If we find another composite char in the glyph definition of
3913 work->cmpcharp, put back the rest of the glyphs on the work
3914 stack, and make a new entry for the composite char. */
3915 if (i
< work
->cmpcharp
->glyph_len
)
3917 /* Push back an unprocessed rest of this glyph spec. */
3918 if (i
< work
->cmpcharp
->glyph_len
- 1)
3921 work
->next
= *stack
;
3927 /* Make an entry for the composite char on the work stack. */
3928 work
->cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (c
)];
3930 work
->next
= *stack
;
3934 /* The width of this glyph string equals the width of the first
3935 glyph. All characters are drawn at the same x-position. */
3936 s
->width
= s
->first_glyph
->pixel_width
;
3938 /* If the specified font could not be loaded, use the frame's
3939 default font, but record the fact that we couldn't load it in
3940 the glyph string so that we can draw rectangles for the
3941 characters of the glyph string. */
3942 if (s
->font
== NULL
)
3944 s
->font_not_found_p
= 1;
3945 s
->font
= FRAME_FONT (s
->f
);
3948 /* Adjust base line for subscript/superscript text. */
3949 s
->ybase
+= s
->first_glyph
->voffset
;
3951 xassert (s
->face
&& s
->face
->gc
);
3953 /* This glyph string must always be drawn with 16-bit functions. */
3958 /* Load glyph string S with a sequence of non-composite characters.
3959 FACE_ID is the face id of the string. START is the index of the
3960 first glyph to consider, END is the index of the last + 1.
3961 OVERLAPS_P non-zero means S should draw the foreground only, and
3962 use its lines physical height for clipping.
3964 Value is the index of the first glyph not in S. */
3967 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
3968 struct glyph_string
*s
;
3970 int start
, end
, overlaps_p
;
3972 struct glyph
*glyph
, *last
;
3975 xassert (s
->charset
!= CHARSET_COMPOSITION
);
3976 xassert (s
->f
== XFRAME (s
->w
->frame
));
3977 xassert (s
->nchars
== 0);
3978 xassert (start
>= 0 && end
> start
);
3980 s
->for_overlaps_p
= overlaps_p
,
3981 glyph
= s
->row
->glyphs
[s
->area
] + start
;
3982 last
= s
->row
->glyphs
[s
->area
] + end
;
3983 voffset
= glyph
->voffset
;
3986 && glyph
->type
== CHAR_GLYPH
3987 && glyph
->voffset
== voffset
3988 /* Same face id implies same charset, nowadays. */
3989 && glyph
->u
.ch
.face_id
== face_id
)
3991 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
3992 s
->char2b
+ s
->nchars
);
3993 if (s
->char2b
[s
->nchars
].byte2
!= 0)
3997 xassert (s
->nchars
<= end
- start
);
3998 s
->width
+= glyph
->pixel_width
;
4002 s
->font
= s
->face
->font
;
4003 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4005 /* If the specified font could not be loaded, use the frame's font,
4006 but record the fact that we couldn't load it in
4007 S->font_not_found_p so that we can draw rectangles for the
4008 characters of the glyph string. */
4009 if (s
->font
== NULL
)
4011 s
->font_not_found_p
= 1;
4012 s
->font
= FRAME_FONT (s
->f
);
4015 /* Adjust base line for subscript/superscript text. */
4016 s
->ybase
+= voffset
;
4018 xassert (s
->face
&& s
->face
->gc
);
4019 return glyph
- s
->row
->glyphs
[s
->area
];
4023 /* Fill glyph string S from image glyph S->first_glyph. */
4026 x_fill_image_glyph_string (s
)
4027 struct glyph_string
*s
;
4029 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4030 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.id
);
4032 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.face_id
);
4033 s
->font
= s
->face
->font
;
4034 s
->width
= s
->first_glyph
->pixel_width
;
4036 /* Adjust base line for subscript/superscript text. */
4037 s
->ybase
+= s
->first_glyph
->voffset
;
4041 /* Fill glyph string S from stretch glyph S->first_glyph. */
4044 x_fill_stretch_glyph_string (s
)
4045 struct glyph_string
*s
;
4047 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4048 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.stretch
.face_id
);
4049 s
->font
= s
->face
->font
;
4050 s
->width
= s
->first_glyph
->pixel_width
;
4052 /* Adjust base line for subscript/superscript text. */
4053 s
->ybase
+= s
->first_glyph
->voffset
;
4057 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4058 of XChar2b structures for S; it can't be allocated in
4059 x_init_glyph_string because it must be allocated via `alloca'. W
4060 is the window on which S is drawn. ROW and AREA are the glyph row
4061 and area within the row from which S is constructed. START is the
4062 index of the first glyph structure covered by S. HL is a
4063 face-override for drawing S. */
4066 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4067 struct glyph_string
*s
;
4070 struct glyph_row
*row
;
4071 enum glyph_row_area area
;
4073 enum draw_glyphs_face hl
;
4075 bzero (s
, sizeof *s
);
4077 s
->f
= XFRAME (w
->frame
);
4078 s
->display
= FRAME_X_DISPLAY (s
->f
);
4079 s
->window
= FRAME_X_WINDOW (s
->f
);
4084 s
->first_glyph
= row
->glyphs
[area
] + start
;
4085 s
->height
= row
->height
;
4086 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4088 /* Display the internal border below the tool-bar window. */
4089 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4090 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4092 s
->ybase
= s
->y
+ row
->ascent
;
4096 /* Set background width of glyph string S. START is the index of the
4097 first glyph following S. LAST_X is the right-most x-position + 1
4098 in the drawing area. */
4101 x_set_glyph_string_background_width (s
, start
, last_x
)
4102 struct glyph_string
*s
;
4106 /* If the face of this glyph string has to be drawn to the end of
4107 the drawing area, set S->extends_to_end_of_line_p. */
4108 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4110 if (start
== s
->row
->used
[s
->area
]
4111 && s
->hl
== DRAW_NORMAL_TEXT
4112 && ((s
->area
== TEXT_AREA
&& s
->row
->fill_line_p
)
4113 || s
->face
->background
!= default_face
->background
4114 || s
->face
->stipple
!= default_face
->stipple
))
4115 s
->extends_to_end_of_line_p
= 1;
4117 /* If S extends its face to the end of the line, set its
4118 background_width to the distance to the right edge of the drawing
4120 if (s
->extends_to_end_of_line_p
)
4121 s
->background_width
= last_x
- s
->x
+ 1;
4123 s
->background_width
= s
->width
;
4127 /* Add a glyph string for a stretch glyph to the list of strings
4128 between HEAD and TAIL. START is the index of the stretch glyph in
4129 row area AREA of glyph row ROW. END is the index of the last glyph
4130 in that glyph row area. X is the current output position assigned
4131 to the new glyph string constructed. HL overrides that face of the
4132 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4133 is the right-most x-position of the drawing area. */
4135 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4136 and below -- keep them on one line. */
4137 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4140 s = (struct glyph_string *) alloca (sizeof *s); \
4141 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4142 x_fill_stretch_glyph_string (s); \
4143 x_append_glyph_string (&HEAD, &TAIL, s); \
4150 /* Add a glyph string for an image glyph to the list of strings
4151 between HEAD and TAIL. START is the index of the image glyph in
4152 row area AREA of glyph row ROW. END is the index of the last glyph
4153 in that glyph row area. X is the current output position assigned
4154 to the new glyph string constructed. HL overrides that face of the
4155 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4156 is the right-most x-position of the drawing area. */
4158 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4161 s = (struct glyph_string *) alloca (sizeof *s); \
4162 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4163 x_fill_image_glyph_string (s); \
4164 x_append_glyph_string (&HEAD, &TAIL, s); \
4171 /* Add a glyph string for a sequence of character glyphs to the list
4172 of strings between HEAD and TAIL. START is the index of the first
4173 glyph in row area AREA of glyph row ROW that is part of the new
4174 glyph string. END is the index of the last glyph in that glyph row
4175 area. X is the current output position assigned to the new glyph
4176 string constructed. HL overrides that face of the glyph; e.g. it
4177 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4178 right-most x-position of the drawing area. */
4180 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4183 int c, charset, face_id; \
4186 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4187 charset = CHAR_CHARSET (c); \
4188 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4190 if (charset == CHARSET_COMPOSITION) \
4192 struct work *stack, *work, *new = NULL; \
4194 struct glyph_string *first_s = NULL; \
4196 /* Push an initial entry for character c on the stack. */ \
4198 work = (struct work *) alloca (sizeof *work); \
4199 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; \
4201 work->next = stack; \
4204 /* While the stack is not empty, append glyph_strings \
4205 to head/tail for glyphs to draw. */ \
4208 s = (struct glyph_string *) alloca (sizeof *s); \
4209 char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len \
4210 * sizeof (XChar2b)); \
4211 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4212 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4213 s->cmpcharp = stack->cmpcharp; \
4214 s->gidx = stack->gidx; \
4215 s->charset = charset; \
4220 /* Don't draw the background except for the \
4221 first glyph string. */ \
4222 s->background_filled_p = n > 0; \
4228 new = (struct work *) alloca (sizeof *new); \
4229 x_fill_composite_glyph_string (s, face_id, &stack, \
4230 &new, OVERLAPS_P); \
4238 s = (struct glyph_string *) alloca (sizeof *s); \
4239 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4240 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4241 x_append_glyph_string (&HEAD, &TAIL, s); \
4242 s->charset = charset; \
4244 START = x_fill_glyph_string (s, face_id, START, END, \
4251 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4252 of AREA of glyph row ROW on window W between indices START and END.
4253 HL overrides the face for drawing glyph strings, e.g. it is
4254 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4255 x-positions of the drawing area.
4257 This is an ugly monster macro construct because we must use alloca
4258 to allocate glyph strings (because x_draw_glyphs can be called
4261 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4264 HEAD = TAIL = NULL; \
4265 while (START < END) \
4267 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4268 switch (first_glyph->type) \
4271 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4272 TAIL, HL, X, LAST_X, \
4276 case STRETCH_GLYPH: \
4277 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4278 HEAD, TAIL, HL, X, LAST_X); \
4282 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4283 TAIL, HL, X, LAST_X); \
4290 x_set_glyph_string_background_width (s, START, LAST_X); \
4297 /* Draw glyphs between START and END in AREA of ROW on window W,
4298 starting at x-position X. X is relative to AREA in W. HL is a
4299 face-override with the following meaning:
4301 DRAW_NORMAL_TEXT draw normally
4302 DRAW_CURSOR draw in cursor face
4303 DRAW_MOUSE_FACE draw in mouse face.
4304 DRAW_INVERSE_VIDEO draw in mode line face
4305 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4306 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4308 If REAL_START is non-null, return in *REAL_START the real starting
4309 position for display. This can be different from START in case
4310 overlapping glyphs must be displayed. If REAL_END is non-null,
4311 return in *REAL_END the real end position for display. This can be
4312 different from END in case overlapping glyphs must be displayed.
4314 If OVERLAPS_P is non-zero, draw only the foreground of characters
4315 and clip to the physical height of ROW.
4317 Value is the x-position reached, relative to AREA of W. */
4320 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, real_start
, real_end
,
4324 struct glyph_row
*row
;
4325 enum glyph_row_area area
;
4327 enum draw_glyphs_face hl
;
4328 int *real_start
, *real_end
;
4331 struct glyph_string
*head
, *tail
;
4332 struct glyph_string
*s
;
4333 int last_x
, area_width
;
4337 /* Let's rather be paranoid than getting a SEGV. */
4338 start
= max (0, start
);
4339 end
= min (end
, row
->used
[area
]);
4341 *real_start
= start
;
4345 /* Translate X to frame coordinates. Set last_x to the right
4346 end of the drawing area. */
4347 if (row
->full_width_p
)
4349 /* X is relative to the left edge of W, without scroll bars
4351 struct frame
*f
= XFRAME (w
->frame
);
4352 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4353 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
4356 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4357 last_x
= window_left_x
+ area_width
;
4359 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4361 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4362 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4368 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
4369 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
4373 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
4374 area_width
= window_box_width (w
, area
);
4375 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
4378 /* Build a doubly-linked list of glyph_string structures between
4379 head and tail from what we have to draw. Note that the macro
4380 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4381 the reason we use a separate variable `i'. */
4383 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
4386 x_reached
= tail
->x
+ tail
->background_width
;
4390 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4391 the row, redraw some glyphs in front or following the glyph
4392 strings built above. */
4393 if (!overlaps_p
&& row
->contains_overlapping_glyphs_p
)
4396 struct glyph_string
*h
, *t
;
4398 /* Compute overhangs for all glyph strings. */
4399 for (s
= head
; s
; s
= s
->next
)
4400 x_compute_glyph_string_overhangs (s
);
4402 /* Prepend glyph strings for glyphs in front of the first glyph
4403 string that are overwritten because of the first glyph
4404 string's left overhang. The background of all strings
4405 prepended must be drawn because the first glyph string
4407 i
= x_left_overwritten (head
);
4411 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
4412 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4416 *real_start
= start
;
4417 x_compute_overhangs_and_x (t
, head
->x
, 1);
4418 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4421 /* Prepend glyph strings for glyphs in front of the first glyph
4422 string that overwrite that glyph string because of their
4423 right overhang. For these strings, only the foreground must
4424 be drawn, because it draws over the glyph string at `head'.
4425 The background must not be drawn because this would overwrite
4426 right overhangs of preceding glyphs for which no glyph
4428 i
= x_left_overwriting (head
);
4431 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
4432 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4434 for (s
= h
; s
; s
= s
->next
)
4435 s
->background_filled_p
= 1;
4438 x_compute_overhangs_and_x (t
, head
->x
, 1);
4439 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4442 /* Append glyphs strings for glyphs following the last glyph
4443 string tail that are overwritten by tail. The background of
4444 these strings has to be drawn because tail's foreground draws
4446 i
= x_right_overwritten (tail
);
4449 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4450 DRAW_NORMAL_TEXT
, x
, last_x
,
4452 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4453 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4458 /* Append glyph strings for glyphs following the last glyph
4459 string tail that overwrite tail. The foreground of such
4460 glyphs has to be drawn because it writes into the background
4461 of tail. The background must not be drawn because it could
4462 paint over the foreground of following glyphs. */
4463 i
= x_right_overwriting (tail
);
4466 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4467 DRAW_NORMAL_TEXT
, x
, last_x
,
4469 for (s
= h
; s
; s
= s
->next
)
4470 s
->background_filled_p
= 1;
4471 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4472 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4478 /* Draw all strings. */
4479 for (s
= head
; s
; s
= s
->next
)
4480 x_draw_glyph_string (s
);
4482 /* Value is the x-position up to which drawn, relative to AREA of W.
4483 This doesn't include parts drawn because of overhangs. */
4484 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
4485 if (!row
->full_width_p
)
4487 if (area
> LEFT_MARGIN_AREA
)
4488 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
4489 if (area
> TEXT_AREA
)
4490 x_reached
-= window_box_width (w
, TEXT_AREA
);
4496 /* Fix the display of area AREA of overlapping row ROW in window W. */
4499 x_fix_overlapping_area (w
, row
, area
)
4501 struct glyph_row
*row
;
4502 enum glyph_row_area area
;
4508 if (area
== LEFT_MARGIN_AREA
)
4510 else if (area
== TEXT_AREA
)
4511 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
4513 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
4514 + window_box_width (w
, TEXT_AREA
));
4516 for (i
= 0; i
< row
->used
[area
];)
4518 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
4520 int start
= i
, start_x
= x
;
4524 x
+= row
->glyphs
[area
][i
].pixel_width
;
4527 while (i
< row
->used
[area
]
4528 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
4530 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
4532 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4537 x
+= row
->glyphs
[area
][i
].pixel_width
;
4546 /* Output LEN glyphs starting at START at the nominal cursor position.
4547 Advance the nominal cursor over the text. The global variable
4548 updated_window contains the window being updated, updated_row is
4549 the glyph row being updated, and updated_area is the area of that
4550 row being updated. */
4553 x_write_glyphs (start
, len
)
4554 struct glyph
*start
;
4557 int x
, hpos
, real_start
, real_end
;
4559 xassert (updated_window
&& updated_row
);
4564 hpos
= start
- updated_row
->glyphs
[updated_area
];
4565 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
4566 updated_row
, updated_area
,
4568 (updated_row
->inverse_p
4569 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4570 &real_start
, &real_end
, 0);
4572 /* If we drew over the cursor, note that it is not visible any more. */
4573 note_overwritten_text_cursor (updated_window
, real_start
,
4574 real_end
- real_start
);
4578 /* Advance the output cursor. */
4579 output_cursor
.hpos
+= len
;
4580 output_cursor
.x
= x
;
4584 /* Insert LEN glyphs from START at the nominal cursor position. */
4587 x_insert_glyphs (start
, len
)
4588 struct glyph
*start
;
4593 int line_height
, shift_by_width
, shifted_region_width
;
4594 struct glyph_row
*row
;
4595 struct glyph
*glyph
;
4596 int frame_x
, frame_y
, hpos
, real_start
, real_end
;
4598 xassert (updated_window
&& updated_row
);
4601 f
= XFRAME (WINDOW_FRAME (w
));
4603 /* Get the height of the line we are in. */
4605 line_height
= row
->height
;
4607 /* Get the width of the glyphs to insert. */
4609 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
4610 shift_by_width
+= glyph
->pixel_width
;
4612 /* Get the width of the region to shift right. */
4613 shifted_region_width
= (window_box_width (w
, updated_area
)
4618 frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, output_cursor
.x
);
4619 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
4620 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4621 f
->output_data
.x
->normal_gc
,
4623 shifted_region_width
, line_height
,
4624 frame_x
+ shift_by_width
, frame_y
);
4626 /* Write the glyphs. */
4627 hpos
= start
- row
->glyphs
[updated_area
];
4628 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
4629 DRAW_NORMAL_TEXT
, &real_start
, &real_end
, 0);
4630 note_overwritten_text_cursor (w
, real_start
, real_end
- real_start
);
4632 /* Advance the output cursor. */
4633 output_cursor
.hpos
+= len
;
4634 output_cursor
.x
+= shift_by_width
;
4639 /* Delete N glyphs at the nominal cursor position. Not implemented
4650 /* Erase the current text line from the nominal cursor position
4651 (inclusive) to pixel column TO_X (exclusive). The idea is that
4652 everything from TO_X onward is already erased.
4654 TO_X is a pixel position relative to updated_area of
4655 updated_window. TO_X == -1 means clear to the end of this area. */
4658 x_clear_end_of_line (to_x
)
4662 struct window
*w
= updated_window
;
4663 int max_x
, min_y
, max_y
;
4664 int from_x
, from_y
, to_y
;
4666 xassert (updated_window
&& updated_row
);
4667 f
= XFRAME (w
->frame
);
4669 if (updated_row
->full_width_p
)
4671 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4672 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4673 && !w
->pseudo_window_p
)
4674 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4677 max_x
= window_box_width (w
, updated_area
);
4678 max_y
= window_text_bottom_y (w
);
4680 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4681 of window. For TO_X > 0, truncate to end of drawing area. */
4687 to_x
= min (to_x
, max_x
);
4689 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
4691 /* Notice if the cursor will be cleared by this operation. */
4692 if (!updated_row
->full_width_p
)
4693 note_overwritten_text_cursor (w
, output_cursor
.hpos
, -1);
4695 from_x
= output_cursor
.x
;
4697 /* Translate to frame coordinates. */
4698 if (updated_row
->full_width_p
)
4700 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
4701 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
4705 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
4706 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
4709 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
4710 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
4711 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
4713 /* Prevent inadvertently clearing to end of the X window. */
4714 if (to_x
> from_x
&& to_y
> from_y
)
4717 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4718 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
4725 /* Clear entire frame. If updating_frame is non-null, clear that
4726 frame. Otherwise clear the selected frame. */
4736 f
= SELECTED_FRAME ();
4738 /* Clearing the frame will erase any cursor, so mark them all as no
4740 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4741 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4742 output_cursor
.x
= -1;
4744 /* We don't set the output cursor here because there will always
4745 follow an explicit cursor_to. */
4747 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4749 /* We have to clear the scroll bars, too. If we have changed
4750 colors or something like that, then they should be notified. */
4751 x_scroll_bar_clear (f
);
4753 XFlush (FRAME_X_DISPLAY (f
));
4759 /* Invert the middle quarter of the frame for .15 sec. */
4761 /* We use the select system call to do the waiting, so we have to make
4762 sure it's available. If it isn't, we just won't do visual bells. */
4764 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4767 /* Subtract the `struct timeval' values X and Y, storing the result in
4768 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4771 timeval_subtract (result
, x
, y
)
4772 struct timeval
*result
, x
, y
;
4774 /* Perform the carry for the later subtraction by updating y. This
4775 is safer because on some systems the tv_sec member is unsigned. */
4776 if (x
.tv_usec
< y
.tv_usec
)
4778 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4779 y
.tv_usec
-= 1000000 * nsec
;
4783 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4785 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4786 y
.tv_usec
+= 1000000 * nsec
;
4790 /* Compute the time remaining to wait. tv_usec is certainly
4792 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4793 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4795 /* Return indication of whether the result should be considered
4797 return x
.tv_sec
< y
.tv_sec
;
4809 /* Create a GC that will use the GXxor function to flip foreground
4810 pixels into background pixels. */
4814 values
.function
= GXxor
;
4815 values
.foreground
= (f
->output_data
.x
->foreground_pixel
4816 ^ f
->output_data
.x
->background_pixel
);
4818 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4819 GCFunction
| GCForeground
, &values
);
4823 /* Get the height not including a menu bar widget. */
4824 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
4825 /* Height of each line to flash. */
4826 int flash_height
= FRAME_LINE_HEIGHT (f
);
4827 /* These will be the left and right margins of the rectangles. */
4828 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4829 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4833 /* Don't flash the area between a scroll bar and the frame
4834 edge it is next to. */
4835 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4837 case vertical_scroll_bar_left
:
4838 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4841 case vertical_scroll_bar_right
:
4842 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
4849 width
= flash_right
- flash_left
;
4851 /* If window is tall, flash top and bottom line. */
4852 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4854 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4856 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4857 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
4858 width
, flash_height
);
4859 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4861 (height
- flash_height
4862 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4863 width
, flash_height
);
4866 /* If it is short, flash it all. */
4867 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4868 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4869 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4874 struct timeval wakeup
;
4876 EMACS_GET_TIME (wakeup
);
4878 /* Compute time to wait until, propagating carry from usecs. */
4879 wakeup
.tv_usec
+= 150000;
4880 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
4881 wakeup
.tv_usec
%= 1000000;
4883 /* Keep waiting until past the time wakeup. */
4886 struct timeval timeout
;
4888 EMACS_GET_TIME (timeout
);
4890 /* In effect, timeout = wakeup - timeout.
4891 Break if result would be negative. */
4892 if (timeval_subtract (&timeout
, wakeup
, timeout
))
4895 /* Try to wait that long--but we might wake up sooner. */
4896 select (0, NULL
, NULL
, NULL
, &timeout
);
4900 /* If window is tall, flash top and bottom line. */
4901 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
4903 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4905 (FRAME_INTERNAL_BORDER_WIDTH (f
)
4906 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
4907 width
, flash_height
);
4908 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4910 (height
- flash_height
4911 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
4912 width
, flash_height
);
4915 /* If it is short, flash it all. */
4916 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
4917 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
4918 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
4920 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
4928 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4931 /* Make audible bell. */
4936 struct frame
*f
= SELECTED_FRAME ();
4938 if (FRAME_X_DISPLAY (f
))
4940 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4947 XBell (FRAME_X_DISPLAY (f
), 0);
4948 XFlush (FRAME_X_DISPLAY (f
));
4955 /* Specify how many text lines, from the top of the window,
4956 should be affected by insert-lines and delete-lines operations.
4957 This, and those operations, are used only within an update
4958 that is bounded by calls to x_update_begin and x_update_end. */
4961 XTset_terminal_window (n
)
4964 /* This function intentionally left blank. */
4969 /***********************************************************************
4971 ***********************************************************************/
4973 /* Perform an insert-lines or delete-lines operation, inserting N
4974 lines or deleting -N lines at vertical position VPOS. */
4977 x_ins_del_lines (vpos
, n
)
4984 /* Scroll part of the display as described by RUN. */
4987 x_scroll_run (w
, run
)
4991 struct frame
*f
= XFRAME (w
->frame
);
4992 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
4994 /* Get frame-relative bounding box of the text display area of W,
4995 without mode lines. Include in this box the flags areas to the
4996 left and right of W. */
4997 window_box (w
, -1, &x
, &y
, &width
, &height
);
4998 width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
4999 x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
5001 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5002 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5003 bottom_y
= y
+ height
;
5007 /* Scrolling up. Make sure we don't copy part of the mode
5008 line at the bottom. */
5009 if (from_y
+ run
->height
> bottom_y
)
5010 height
= bottom_y
- from_y
;
5012 height
= run
->height
;
5016 /* Scolling down. Make sure we don't copy over the mode line.
5018 if (to_y
+ run
->height
> bottom_y
)
5019 height
= bottom_y
- to_y
;
5021 height
= run
->height
;
5026 /* Cursor off. Will be switched on again in x_update_window_end. */
5030 XCopyArea (FRAME_X_DISPLAY (f
),
5031 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5032 f
->output_data
.x
->normal_gc
,
5042 /***********************************************************************
5044 ***********************************************************************/
5046 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5047 corner of the exposed rectangle. W and H are width and height of
5048 the exposed area. All are pixel values. W or H zero means redraw
5049 the entire frame. */
5052 expose_frame (f
, x
, y
, w
, h
)
5058 TRACE ((stderr
, "expose_frame "));
5060 /* No need to redraw if frame will be redrawn soon. */
5061 if (FRAME_GARBAGED_P (f
))
5063 TRACE ((stderr
, " garbaged\n"));
5067 /* If basic faces haven't been realized yet, there is no point in
5068 trying to redraw anything. This can happen when we get an expose
5069 event while Emacs is starting, e.g. by moving another window. */
5070 if (FRAME_FACE_CACHE (f
) == NULL
5071 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5073 TRACE ((stderr
, " no faces\n"));
5077 if (w
== 0 || h
== 0)
5080 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5081 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5091 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5092 expose_window_tree (XWINDOW (f
->root_window
), &r
);
5094 if (WINDOWP (f
->tool_bar_window
))
5096 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5097 XRectangle window_rect
;
5098 XRectangle intersection_rect
;
5099 int window_x
, window_y
, window_width
, window_height
;
5102 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5103 window_rect
.x
= window_x
;
5104 window_rect
.y
= window_y
;
5105 window_rect
.width
= window_width
;
5106 window_rect
.height
= window_height
;
5108 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5109 expose_window (w
, &intersection_rect
);
5112 #ifndef USE_X_TOOLKIT
5113 if (WINDOWP (f
->menu_bar_window
))
5115 struct window
*w
= XWINDOW (f
->menu_bar_window
);
5116 XRectangle window_rect
;
5117 XRectangle intersection_rect
;
5118 int window_x
, window_y
, window_width
, window_height
;
5121 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5122 window_rect
.x
= window_x
;
5123 window_rect
.y
= window_y
;
5124 window_rect
.width
= window_width
;
5125 window_rect
.height
= window_height
;
5127 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5128 expose_window (w
, &intersection_rect
);
5130 #endif /* not USE_X_TOOLKIT */
5134 /* Redraw (parts) of all windows in the window tree rooted at W that
5135 intersect R. R contains frame pixel coordinates. */
5138 expose_window_tree (w
, r
)
5144 if (!NILP (w
->hchild
))
5145 expose_window_tree (XWINDOW (w
->hchild
), r
);
5146 else if (!NILP (w
->vchild
))
5147 expose_window_tree (XWINDOW (w
->vchild
), r
);
5150 XRectangle window_rect
;
5151 XRectangle intersection_rect
;
5152 struct frame
*f
= XFRAME (w
->frame
);
5153 int window_x
, window_y
, window_width
, window_height
;
5155 /* Frame-relative pixel rectangle of W. */
5156 window_box (w
, -1, &window_x
, &window_y
, &window_width
,
5160 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
5161 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5162 window_rect
.y
= window_y
;
5165 + FRAME_X_FLAGS_AREA_WIDTH (f
)
5166 + FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5168 = window_height
+ CURRENT_MODE_LINE_HEIGHT (w
);
5170 if (x_intersect_rectangles (r
, &window_rect
, &intersection_rect
))
5171 expose_window (w
, &intersection_rect
);
5174 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5179 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5180 which intersects rectangle R. R is in window-relative coordinates. */
5183 expose_area (w
, row
, r
, area
)
5185 struct glyph_row
*row
;
5187 enum glyph_row_area area
;
5190 struct glyph
*first
= row
->glyphs
[area
];
5191 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5195 /* Set x to the window-relative start position for drawing glyphs of
5196 AREA. The first glyph of the text area can be partially visible.
5197 The first glyphs of other areas cannot. */
5198 if (area
== LEFT_MARGIN_AREA
)
5200 else if (area
== TEXT_AREA
)
5201 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5203 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5204 + window_box_width (w
, TEXT_AREA
));
5206 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5207 /* If row extends face to end of line write the whole line. */
5208 x_draw_glyphs (w
, x
, row
, area
,
5210 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5214 /* Find the first glyph that must be redrawn. */
5216 && x
+ first
->pixel_width
< r
->x
)
5218 x
+= first
->pixel_width
;
5222 /* Find the last one. */
5226 && x
< r
->x
+ r
->width
)
5228 x
+= last
->pixel_width
;
5234 x_draw_glyphs (w
, first_x
, row
, area
,
5235 first
- row
->glyphs
[area
],
5236 last
- row
->glyphs
[area
],
5237 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5243 /* Redraw the parts of the glyph row ROW on window W intersecting
5244 rectangle R. R is in window-relative coordinates. */
5247 expose_line (w
, row
, r
)
5249 struct glyph_row
*row
;
5252 xassert (row
->enabled_p
);
5254 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5255 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5256 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5260 if (row
->used
[LEFT_MARGIN_AREA
])
5261 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5262 if (row
->used
[TEXT_AREA
])
5263 expose_area (w
, row
, r
, TEXT_AREA
);
5264 if (row
->used
[RIGHT_MARGIN_AREA
])
5265 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5266 x_draw_row_bitmaps (w
, row
);
5271 /* Return non-zero if W's cursor intersects rectangle R. */
5274 x_phys_cursor_in_rect_p (w
, r
)
5278 XRectangle cr
, result
;
5279 struct glyph
*cursor_glyph
;
5281 cursor_glyph
= get_phys_cursor_glyph (w
);
5284 cr
.x
= w
->phys_cursor
.x
;
5285 cr
.y
= w
->phys_cursor
.y
;
5286 cr
.width
= cursor_glyph
->pixel_width
;
5287 cr
.height
= w
->phys_cursor_height
;
5288 return x_intersect_rectangles (&cr
, r
, &result
);
5295 /* Redraw a rectangle of window W. R is a rectangle in window
5296 relative coordinates. Call this function with input blocked. */
5299 expose_window (w
, r
)
5303 struct glyph_row
*row
;
5305 int yb
= window_text_bottom_y (w
);
5306 int cursor_cleared_p
;
5308 /* If window is not yet fully initialized, do nothing. This can
5309 happen when toolkit scroll bars are used and a window is split.
5310 Reconfiguring the scroll bar will generate an expose for a newly
5312 if (w
->current_matrix
== NULL
)
5315 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
5316 r
->x
, r
->y
, r
->width
, r
->height
));
5318 /* Convert to window coordinates. */
5319 r
->x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
->x
);
5320 r
->y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
->y
);
5322 /* Turn off the cursor. */
5323 if (!w
->pseudo_window_p
5324 && x_phys_cursor_in_rect_p (w
, r
))
5327 cursor_cleared_p
= 1;
5330 cursor_cleared_p
= 0;
5332 /* Find the first row intersecting the rectangle R. */
5333 row
= w
->current_matrix
->rows
;
5335 while (row
->enabled_p
5337 && y
+ row
->height
< r
->y
)
5343 /* Display the text in the rectangle, one text line at a time. */
5344 while (row
->enabled_p
5346 && y
< r
->y
+ r
->height
)
5348 expose_line (w
, row
, r
);
5353 /* Display the mode line if there is one. */
5354 if (WINDOW_WANTS_MODELINE_P (w
)
5355 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
5357 && row
->y
< r
->y
+ r
->height
)
5358 expose_line (w
, row
, r
);
5360 if (!w
->pseudo_window_p
)
5362 /* Draw border between windows. */
5363 x_draw_vertical_border (w
);
5365 /* Turn the cursor on again. */
5366 if (cursor_cleared_p
)
5367 x_update_window_cursor (w
, 1);
5372 /* Determine the intersection of two rectangles R1 and R2. Return
5373 the intersection in *RESULT. Value is non-zero if RESULT is not
5377 x_intersect_rectangles (r1
, r2
, result
)
5378 XRectangle
*r1
, *r2
, *result
;
5380 XRectangle
*left
, *right
;
5381 XRectangle
*upper
, *lower
;
5382 int intersection_p
= 0;
5384 /* Rearrange so that R1 is the left-most rectangle. */
5386 left
= r1
, right
= r2
;
5388 left
= r2
, right
= r1
;
5390 /* X0 of the intersection is right.x0, if this is inside R1,
5391 otherwise there is no intersection. */
5392 if (right
->x
<= left
->x
+ left
->width
)
5394 result
->x
= right
->x
;
5396 /* The right end of the intersection is the minimum of the
5397 the right ends of left and right. */
5398 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
5401 /* Same game for Y. */
5403 upper
= r1
, lower
= r2
;
5405 upper
= r2
, lower
= r1
;
5407 /* The upper end of the intersection is lower.y0, if this is inside
5408 of upper. Otherwise, there is no intersection. */
5409 if (lower
->y
<= upper
->y
+ upper
->height
)
5411 result
->y
= lower
->y
;
5413 /* The lower end of the intersection is the minimum of the lower
5414 ends of upper and lower. */
5415 result
->height
= (min (lower
->y
+ lower
->height
,
5416 upper
->y
+ upper
->height
)
5422 return intersection_p
;
5433 /* We used to only do this if Vx_no_window_manager was non-nil, but
5434 the ICCCM (section 4.1.6) says that the window's border pixmap
5435 and border pixel are window attributes which are "private to the
5436 client", so we can always change it to whatever we want. */
5438 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5439 f
->output_data
.x
->border_pixel
);
5441 x_update_cursor (f
, 1);
5445 frame_unhighlight (f
)
5448 /* We used to only do this if Vx_no_window_manager was non-nil, but
5449 the ICCCM (section 4.1.6) says that the window's border pixmap
5450 and border pixel are window attributes which are "private to the
5451 client", so we can always change it to whatever we want. */
5453 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5454 f
->output_data
.x
->border_tile
);
5456 x_update_cursor (f
, 1);
5459 /* The focus has changed. Update the frames as necessary to reflect
5460 the new situation. Note that we can't change the selected frame
5461 here, because the Lisp code we are interrupting might become confused.
5462 Each event gets marked with the frame in which it occurred, so the
5463 Lisp code can tell when the switch took place by examining the events. */
5466 x_new_focus_frame (dpyinfo
, frame
)
5467 struct x_display_info
*dpyinfo
;
5468 struct frame
*frame
;
5470 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5472 if (frame
!= dpyinfo
->x_focus_frame
)
5474 /* Set this before calling other routines, so that they see
5475 the correct value of x_focus_frame. */
5476 dpyinfo
->x_focus_frame
= frame
;
5478 if (old_focus
&& old_focus
->auto_lower
)
5479 x_lower_frame (old_focus
);
5482 selected_frame
= frame
;
5483 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
5485 Fselect_window (selected_frame
->selected_window
);
5486 choose_minibuf_frame ();
5489 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
5490 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
5492 pending_autoraise_frame
= 0;
5495 x_frame_rehighlight (dpyinfo
);
5498 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5501 x_mouse_leave (dpyinfo
)
5502 struct x_display_info
*dpyinfo
;
5504 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
5507 /* The focus has changed, or we have redirected a frame's focus to
5508 another frame (this happens when a frame uses a surrogate
5509 mini-buffer frame). Shift the highlight as appropriate.
5511 The FRAME argument doesn't necessarily have anything to do with which
5512 frame is being highlighted or un-highlighted; we only use it to find
5513 the appropriate X display info. */
5516 XTframe_rehighlight (frame
)
5517 struct frame
*frame
;
5519 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
5523 x_frame_rehighlight (dpyinfo
)
5524 struct x_display_info
*dpyinfo
;
5526 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
5528 if (dpyinfo
->x_focus_frame
)
5530 dpyinfo
->x_highlight_frame
5531 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
5532 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
5533 : dpyinfo
->x_focus_frame
);
5534 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
5536 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
5537 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
5541 dpyinfo
->x_highlight_frame
= 0;
5543 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
5546 frame_unhighlight (old_highlight
);
5547 if (dpyinfo
->x_highlight_frame
)
5548 frame_highlight (dpyinfo
->x_highlight_frame
);
5554 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5556 /* Initialize mode_switch_bit and modifier_meaning. */
5558 x_find_modifier_meanings (dpyinfo
)
5559 struct x_display_info
*dpyinfo
;
5561 int min_code
, max_code
;
5564 XModifierKeymap
*mods
;
5566 dpyinfo
->meta_mod_mask
= 0;
5567 dpyinfo
->shift_lock_mask
= 0;
5568 dpyinfo
->alt_mod_mask
= 0;
5569 dpyinfo
->super_mod_mask
= 0;
5570 dpyinfo
->hyper_mod_mask
= 0;
5573 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
5575 min_code
= dpyinfo
->display
->min_keycode
;
5576 max_code
= dpyinfo
->display
->max_keycode
;
5579 syms
= XGetKeyboardMapping (dpyinfo
->display
,
5580 min_code
, max_code
- min_code
+ 1,
5582 mods
= XGetModifierMapping (dpyinfo
->display
);
5584 /* Scan the modifier table to see which modifier bits the Meta and
5585 Alt keysyms are on. */
5587 int row
, col
; /* The row and column in the modifier table. */
5589 for (row
= 3; row
< 8; row
++)
5590 for (col
= 0; col
< mods
->max_keypermod
; col
++)
5593 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
5595 /* Zeroes are used for filler. Skip them. */
5599 /* Are any of this keycode's keysyms a meta key? */
5603 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
5605 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
5611 dpyinfo
->meta_mod_mask
|= (1 << row
);
5616 dpyinfo
->alt_mod_mask
|= (1 << row
);
5621 dpyinfo
->hyper_mod_mask
|= (1 << row
);
5626 dpyinfo
->super_mod_mask
|= (1 << row
);
5630 /* Ignore this if it's not on the lock modifier. */
5631 if ((1 << row
) == LockMask
)
5632 dpyinfo
->shift_lock_mask
= LockMask
;
5640 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5641 if (! dpyinfo
->meta_mod_mask
)
5643 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
5644 dpyinfo
->alt_mod_mask
= 0;
5647 /* If some keys are both alt and meta,
5648 make them just meta, not alt. */
5649 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
5651 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
5654 XFree ((char *) syms
);
5655 XFreeModifiermap (mods
);
5658 /* Convert between the modifier bits X uses and the modifier bits
5662 x_x_to_emacs_modifiers (dpyinfo
, state
)
5663 struct x_display_info
*dpyinfo
;
5666 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
5667 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
5668 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
5669 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
5670 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
5671 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
5675 x_emacs_to_x_modifiers (dpyinfo
, state
)
5676 struct x_display_info
*dpyinfo
;
5679 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
5680 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
5681 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
5682 | ((state
& shift_modifier
) ? ShiftMask
: 0)
5683 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
5684 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
5687 /* Convert a keysym to its name. */
5690 x_get_keysym_name (keysym
)
5696 value
= XKeysymToString (keysym
);
5704 /* Mouse clicks and mouse movement. Rah. */
5706 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5707 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5708 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5709 not force the value into range. */
5712 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
5714 register int pix_x
, pix_y
;
5715 register int *x
, *y
;
5719 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5720 even for negative values. */
5722 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
5724 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
5726 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
5727 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
5731 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
5732 bounds
->height
= f
->output_data
.x
->line_height
;
5733 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
5734 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
5741 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
5742 pix_x
= FRAME_WINDOW_WIDTH (f
);
5746 else if (pix_y
> f
->height
)
5755 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5756 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5757 can't tell the positions because W's display is not up to date,
5761 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
5764 int *frame_x
, *frame_y
;
5768 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
5769 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
5771 if (display_completed
)
5773 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
5774 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
5775 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
5781 *frame_x
+= glyph
->pixel_width
;
5789 *frame_y
= *frame_x
= 0;
5793 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
5794 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
5799 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5801 If the event is a button press, then note that we have grabbed
5805 construct_mouse_click (result
, event
, f
)
5806 struct input_event
*result
;
5807 XButtonEvent
*event
;
5810 /* Make the event type no_event; we'll change that when we decide
5812 result
->kind
= mouse_click
;
5813 result
->code
= event
->button
- Button1
;
5814 result
->timestamp
= event
->time
;
5815 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5817 | (event
->type
== ButtonRelease
5821 XSETINT (result
->x
, event
->x
);
5822 XSETINT (result
->y
, event
->y
);
5823 XSETFRAME (result
->frame_or_window
, f
);
5827 #if 0 /* This function isn't called. --gerd */
5829 /* Prepare a menu-event in *RESULT for placement in the input queue. */
5832 construct_menu_click (result
, event
, f
)
5833 struct input_event
*result
;
5834 XButtonEvent
*event
;
5837 /* Make the event type no_event; we'll change that when we decide
5839 result
->kind
= mouse_click
;
5840 result
->code
= event
->button
- Button1
;
5841 result
->timestamp
= event
->time
;
5842 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5844 | (event
->type
== ButtonRelease
5848 XSETINT (result
->x
, event
->x
);
5849 XSETINT (result
->y
, -1);
5850 XSETFRAME (result
->frame_or_window
, f
);
5856 /* Function to report a mouse movement to the mainstream Emacs code.
5857 The input handler calls this.
5859 We have received a mouse movement event, which is given in *event.
5860 If the mouse is over a different glyph than it was last time, tell
5861 the mainstream emacs code by setting mouse_moved. If not, ask for
5862 another motion event, so we can check again the next time it moves. */
5864 static XMotionEvent last_mouse_motion_event
;
5865 static Lisp_Object last_mouse_motion_frame
;
5868 note_mouse_movement (frame
, event
)
5870 XMotionEvent
*event
;
5872 last_mouse_movement_time
= event
->time
;
5873 last_mouse_motion_event
= *event
;
5874 XSETFRAME (last_mouse_motion_frame
, frame
);
5876 if (event
->window
!= FRAME_X_WINDOW (frame
))
5878 frame
->mouse_moved
= 1;
5879 last_mouse_scroll_bar
= Qnil
;
5880 note_mouse_highlight (frame
, -1, -1);
5883 /* Has the mouse moved off the glyph it was on at the last sighting? */
5884 else if (event
->x
< last_mouse_glyph
.x
5885 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
5886 || event
->y
< last_mouse_glyph
.y
5887 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
5889 frame
->mouse_moved
= 1;
5890 last_mouse_scroll_bar
= Qnil
;
5891 note_mouse_highlight (frame
, event
->x
, event
->y
);
5895 /* This is used for debugging, to turn off note_mouse_highlight. */
5897 int disable_mouse_highlight
;
5901 /************************************************************************
5903 ************************************************************************/
5905 /* Find the glyph under window-relative coordinates X/Y in window W.
5906 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5907 strings. Return in *HPOS and *VPOS the row and column number of
5908 the glyph found. Return in *AREA the glyph area containing X.
5909 Value is a pointer to the glyph found or null if X/Y is not on
5910 text, or we can't tell because W's current matrix is not up to
5913 static struct glyph
*
5914 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
)
5917 int *hpos
, *vpos
, *area
;
5919 struct glyph
*glyph
, *end
;
5920 struct glyph_row
*row
;
5921 int x0
, i
, left_area_width
;
5923 /* Find row containing Y. Give up if some row is not enabled. */
5924 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
5926 row
= MATRIX_ROW (w
->current_matrix
, i
);
5927 if (!row
->enabled_p
)
5929 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
5936 /* Give up if Y is not in the window. */
5937 if (i
== w
->current_matrix
->nrows
)
5940 /* Get the glyph area containing X. */
5941 if (w
->pseudo_window_p
)
5948 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
5949 if (x
< left_area_width
)
5951 *area
= LEFT_MARGIN_AREA
;
5954 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
5957 x0
= row
->x
+ left_area_width
;
5961 *area
= RIGHT_MARGIN_AREA
;
5962 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
5966 /* Find glyph containing X. */
5967 glyph
= row
->glyphs
[*area
];
5968 end
= glyph
+ row
->used
[*area
];
5971 if (x
< x0
+ glyph
->pixel_width
)
5973 if (w
->pseudo_window_p
)
5975 else if (BUFFERP (glyph
->object
))
5979 x0
+= glyph
->pixel_width
;
5986 *hpos
= glyph
- row
->glyphs
[*area
];
5991 /* Convert frame-relative x/y to coordinates relative to window W.
5992 Takes pseudo-windows into account. */
5995 frame_to_window_pixel_xy (w
, x
, y
)
5999 if (w
->pseudo_window_p
)
6001 /* A pseudo-window is always full-width, and starts at the
6002 left edge of the frame, plus a frame border. */
6003 struct frame
*f
= XFRAME (w
->frame
);
6004 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6005 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6009 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6010 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6015 /* Take proper action when mouse has moved to the mode or top line of
6016 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6017 mode line. X is relative to the start of the text display area of
6018 W, so the width of bitmap areas and scroll bars must be subtracted
6019 to get a position relative to the start of the mode line. */
6022 note_mode_line_highlight (w
, x
, mode_line_p
)
6026 struct frame
*f
= XFRAME (w
->frame
);
6027 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6028 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6029 struct glyph_row
*row
;
6032 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6034 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
6038 struct glyph
*glyph
, *end
;
6039 Lisp_Object help
, map
;
6042 /* Find the glyph under X. */
6043 glyph
= row
->glyphs
[TEXT_AREA
];
6044 end
= glyph
+ row
->used
[TEXT_AREA
];
6045 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
6046 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
));
6048 && x
>= x0
+ glyph
->pixel_width
)
6050 x0
+= glyph
->pixel_width
;
6055 && STRINGP (glyph
->object
)
6056 && XSTRING (glyph
->object
)->intervals
6057 && glyph
->charpos
>= 0
6058 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6060 /* If we're on a string with `help-echo' text property,
6061 arrange for the help to be displayed. This is done by
6062 setting the global variable help_echo to the help string. */
6063 help
= Fget_text_property (make_number (glyph
->charpos
),
6064 Qhelp_echo
, glyph
->object
);
6068 /* Change the mouse pointer according to what is under X/Y. */
6069 map
= Fget_text_property (make_number (glyph
->charpos
),
6070 Qlocal_map
, glyph
->object
);
6071 if (!NILP (Fkeymapp (map
)))
6072 cursor
= f
->output_data
.x
->nontext_cursor
;
6076 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
6080 /* Take proper action when the mouse has moved to position X, Y on
6081 frame F as regards highlighting characters that have mouse-face
6082 properties. Also de-highlighting chars where the mouse was before.
6083 X and Y can be negative or out of range. */
6086 note_mouse_highlight (f
, x
, y
)
6090 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6095 /* When a menu is active, don't highlight because this looks odd. */
6096 #ifdef USE_X_TOOLKIT
6097 if (popup_activated ())
6101 if (disable_mouse_highlight
)
6104 dpyinfo
->mouse_face_mouse_x
= x
;
6105 dpyinfo
->mouse_face_mouse_y
= y
;
6106 dpyinfo
->mouse_face_mouse_frame
= f
;
6108 if (dpyinfo
->mouse_face_defer
)
6113 dpyinfo
->mouse_face_deferred_gc
= 1;
6117 /* Which window is that in? */
6118 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
6120 /* If we were displaying active text in another window, clear that. */
6121 if (! EQ (window
, dpyinfo
->mouse_face_window
))
6122 clear_mouse_face (dpyinfo
);
6124 /* Not on a window -> return. */
6125 if (!WINDOWP (window
))
6128 /* Convert to window-relative pixel coordinates. */
6129 w
= XWINDOW (window
);
6130 frame_to_window_pixel_xy (w
, &x
, &y
);
6132 /* Handle tool-bar window differently since it doesn't display a
6134 if (EQ (window
, f
->tool_bar_window
))
6136 note_tool_bar_highlight (f
, x
, y
);
6140 if (portion
== 1 || portion
== 3)
6142 /* Mouse is on the mode or top line. */
6143 note_mode_line_highlight (w
, x
, portion
== 1);
6147 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6148 f
->output_data
.x
->text_cursor
);
6150 /* Are we in a window whose display is up to date?
6151 And verify the buffer's text has not changed. */
6152 if (/* Within text portion of the window. */
6154 && EQ (w
->window_end_valid
, w
->buffer
)
6155 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
6156 && (XFASTINT (w
->last_overlay_modified
)
6157 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
6159 int hpos
, vpos
, pos
, i
, area
;
6160 struct glyph
*glyph
;
6162 /* Find the glyph under X/Y. */
6163 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
);
6165 /* Clear mouse face if X/Y not over text. */
6167 || area
!= TEXT_AREA
6168 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6170 clear_mouse_face (dpyinfo
);
6174 pos
= glyph
->charpos
;
6175 xassert (w
->pseudo_window_p
|| BUFFERP (glyph
->object
));
6177 /* Check for mouse-face and help-echo. */
6179 Lisp_Object mouse_face
, overlay
, position
;
6180 Lisp_Object
*overlay_vec
;
6182 struct buffer
*obuf
;
6185 /* If we get an out-of-range value, return now; avoid an error. */
6186 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
6189 /* Make the window's buffer temporarily current for
6190 overlays_at and compute_char_face. */
6191 obuf
= current_buffer
;
6192 current_buffer
= XBUFFER (w
->buffer
);
6198 /* Is this char mouse-active or does it have help-echo? */
6199 XSETINT (position
, pos
);
6201 /* Put all the overlays we want in a vector in overlay_vec.
6202 Store the length in len. If there are more than 10, make
6203 enough space for all, and try again. */
6205 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6206 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6207 if (noverlays
> len
)
6210 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6211 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6214 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
6216 /* Check mouse-face highlighting. */
6217 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
6218 && vpos
>= dpyinfo
->mouse_face_beg_row
6219 && vpos
<= dpyinfo
->mouse_face_end_row
6220 && (vpos
> dpyinfo
->mouse_face_beg_row
6221 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6222 && (vpos
< dpyinfo
->mouse_face_end_row
6223 || hpos
< dpyinfo
->mouse_face_end_col
6224 || dpyinfo
->mouse_face_past_end
)))
6226 /* Clear the display of the old active region, if any. */
6227 clear_mouse_face (dpyinfo
);
6229 /* Find the highest priority overlay that has a mouse-face prop. */
6231 for (i
= 0; i
< noverlays
; i
++)
6233 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
6234 if (!NILP (mouse_face
))
6236 overlay
= overlay_vec
[i
];
6241 /* If no overlay applies, get a text property. */
6243 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
6245 /* Handle the overlay case. */
6246 if (! NILP (overlay
))
6248 /* Find the range of text around this char that
6249 should be active. */
6250 Lisp_Object before
, after
;
6253 before
= Foverlay_start (overlay
);
6254 after
= Foverlay_end (overlay
);
6255 /* Record this as the current active region. */
6256 fast_find_position (w
, XFASTINT (before
),
6257 &dpyinfo
->mouse_face_beg_col
,
6258 &dpyinfo
->mouse_face_beg_row
,
6259 &dpyinfo
->mouse_face_beg_x
,
6260 &dpyinfo
->mouse_face_beg_y
);
6261 dpyinfo
->mouse_face_past_end
6262 = !fast_find_position (w
, XFASTINT (after
),
6263 &dpyinfo
->mouse_face_end_col
,
6264 &dpyinfo
->mouse_face_end_row
,
6265 &dpyinfo
->mouse_face_end_x
,
6266 &dpyinfo
->mouse_face_end_y
);
6267 dpyinfo
->mouse_face_window
= window
;
6268 dpyinfo
->mouse_face_face_id
6269 = face_at_buffer_position (w
, pos
, 0, 0,
6270 &ignore
, pos
+ 1, 1);
6272 /* Display it as active. */
6273 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6275 /* Handle the text property case. */
6276 else if (! NILP (mouse_face
))
6278 /* Find the range of text around this char that
6279 should be active. */
6280 Lisp_Object before
, after
, beginning
, end
;
6283 beginning
= Fmarker_position (w
->start
);
6284 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
6285 - XFASTINT (w
->window_end_pos
)));
6287 = Fprevious_single_property_change (make_number (pos
+ 1),
6289 w
->buffer
, beginning
);
6291 = Fnext_single_property_change (position
, Qmouse_face
,
6293 /* Record this as the current active region. */
6294 fast_find_position (w
, XFASTINT (before
),
6295 &dpyinfo
->mouse_face_beg_col
,
6296 &dpyinfo
->mouse_face_beg_row
,
6297 &dpyinfo
->mouse_face_beg_x
,
6298 &dpyinfo
->mouse_face_beg_y
);
6299 dpyinfo
->mouse_face_past_end
6300 = !fast_find_position (w
, XFASTINT (after
),
6301 &dpyinfo
->mouse_face_end_col
,
6302 &dpyinfo
->mouse_face_end_row
,
6303 &dpyinfo
->mouse_face_end_x
,
6304 &dpyinfo
->mouse_face_end_y
);
6305 dpyinfo
->mouse_face_window
= window
;
6306 dpyinfo
->mouse_face_face_id
6307 = face_at_buffer_position (w
, pos
, 0, 0,
6308 &ignore
, pos
+ 1, 1);
6310 /* Display it as active. */
6311 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6315 /* Look for a `help-echo' property. */
6319 /* Check overlays first. */
6321 for (i
= 0; i
< noverlays
&& !STRINGP (help
); ++i
)
6322 help
= Foverlay_get (overlay_vec
[i
], Qhelp_echo
);
6324 /* Try text properties. */
6326 && ((STRINGP (glyph
->object
)
6327 && glyph
->charpos
>= 0
6328 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6329 || (BUFFERP (glyph
->object
)
6330 && glyph
->charpos
>= BEGV
6331 && glyph
->charpos
< ZV
)))
6332 help
= Fget_text_property (make_number (glyph
->charpos
),
6333 Qhelp_echo
, glyph
->object
);
6341 current_buffer
= obuf
;
6347 redo_mouse_highlight ()
6349 if (!NILP (last_mouse_motion_frame
)
6350 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
6351 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
6352 last_mouse_motion_event
.x
,
6353 last_mouse_motion_event
.y
);
6358 /***********************************************************************
6360 ***********************************************************************/
6362 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
6363 struct glyph
**, int *, int *, int *));
6365 /* Tool-bar item index of the item on which a mouse button was pressed
6368 static int last_tool_bar_item
;
6371 /* Get information about the tool-bar item at position X/Y on frame F.
6372 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6373 the current matrix of the tool-bar window of F, or NULL if not
6374 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6375 item in F->current_tool_bar_items. Value is
6377 -1 if X/Y is not on a tool-bar item
6378 0 if X/Y is on the same item that was highlighted before.
6382 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
6385 struct glyph
**glyph
;
6386 int *hpos
, *vpos
, *prop_idx
;
6388 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6389 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6392 /* Find the glyph under X/Y. */
6393 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
);
6397 /* Get the start of this tool-bar item's properties in
6398 f->current_tool_bar_items. */
6399 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
6402 /* Is mouse on the highlighted item? */
6403 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
6404 && *vpos
>= dpyinfo
->mouse_face_beg_row
6405 && *vpos
<= dpyinfo
->mouse_face_end_row
6406 && (*vpos
> dpyinfo
->mouse_face_beg_row
6407 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
6408 && (*vpos
< dpyinfo
->mouse_face_end_row
6409 || *hpos
< dpyinfo
->mouse_face_end_col
6410 || dpyinfo
->mouse_face_past_end
))
6417 /* Handle mouse button event on the tool-bar of frame F, at
6418 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6422 x_handle_tool_bar_click (f
, button_event
)
6424 XButtonEvent
*button_event
;
6426 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6427 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6428 int hpos
, vpos
, prop_idx
;
6429 struct glyph
*glyph
;
6430 Lisp_Object enabled_p
;
6431 int x
= button_event
->x
;
6432 int y
= button_event
->y
;
6434 /* If not on the highlighted tool-bar item, return. */
6435 frame_to_window_pixel_xy (w
, &x
, &y
);
6436 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
6439 /* If item is disabled, do nothing. */
6440 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6441 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6442 if (NILP (enabled_p
))
6445 if (button_event
->type
== ButtonPress
)
6447 /* Show item in pressed state. */
6448 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
6449 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
6450 last_tool_bar_item
= prop_idx
;
6454 Lisp_Object key
, frame
;
6455 struct input_event event
;
6457 /* Show item in released state. */
6458 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
6459 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
6461 key
= (XVECTOR (f
->current_tool_bar_items
)
6462 ->contents
[prop_idx
+ TOOL_BAR_ITEM_KEY
]);
6464 XSETFRAME (frame
, f
);
6465 event
.kind
= TOOL_BAR_EVENT
;
6466 event
.frame_or_window
= Fcons (frame
, Fcons (Qtool_bar
, Qnil
));
6467 kbd_buffer_store_event (&event
);
6469 event
.kind
= TOOL_BAR_EVENT
;
6470 event
.frame_or_window
= Fcons (frame
, key
);
6471 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6472 button_event
->state
);
6473 kbd_buffer_store_event (&event
);
6474 last_tool_bar_item
= -1;
6479 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6480 tool-bar window-relative coordinates X/Y. Called from
6481 note_mouse_highlight. */
6484 note_tool_bar_highlight (f
, x
, y
)
6488 Lisp_Object window
= f
->tool_bar_window
;
6489 struct window
*w
= XWINDOW (window
);
6490 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6492 struct glyph
*glyph
;
6493 struct glyph_row
*row
;
6495 Lisp_Object enabled_p
;
6497 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
6498 int mouse_down_p
, rc
;
6500 /* Function note_mouse_highlight is called with negative x(y
6501 values when mouse moves outside of the frame. */
6502 if (x
<= 0 || y
<= 0)
6504 clear_mouse_face (dpyinfo
);
6508 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
6511 /* Not on tool-bar item. */
6512 clear_mouse_face (dpyinfo
);
6516 /* On same tool-bar item as before. */
6519 clear_mouse_face (dpyinfo
);
6521 /* Mouse is down, but on different tool-bar item? */
6522 mouse_down_p
= (dpyinfo
->grabbed
6523 && f
== last_mouse_frame
6524 && FRAME_LIVE_P (f
));
6526 && last_tool_bar_item
!= prop_idx
)
6529 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
6530 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
6532 /* If tool-bar item is not enabled, don't highlight it. */
6533 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6534 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6535 if (!NILP (enabled_p
))
6537 /* Compute the x-position of the glyph. In front and past the
6538 image is a space. We include this is the highlighted area. */
6539 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6540 for (i
= x
= 0; i
< hpos
; ++i
)
6541 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
6543 /* Record this as the current active region. */
6544 dpyinfo
->mouse_face_beg_col
= hpos
;
6545 dpyinfo
->mouse_face_beg_row
= vpos
;
6546 dpyinfo
->mouse_face_beg_x
= x
;
6547 dpyinfo
->mouse_face_beg_y
= row
->y
;
6548 dpyinfo
->mouse_face_past_end
= 0;
6550 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
6551 dpyinfo
->mouse_face_end_row
= vpos
;
6552 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
6553 dpyinfo
->mouse_face_end_y
= row
->y
;
6554 dpyinfo
->mouse_face_window
= window
;
6555 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
6557 /* Display it as active. */
6558 show_mouse_face (dpyinfo
, draw
);
6559 dpyinfo
->mouse_face_image_state
= draw
;
6564 /* Set help_echo to a help string.to display for this tool-bar item.
6565 XTread_socket does the rest. */
6566 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6567 ->contents
[prop_idx
+ TOOL_BAR_ITEM_HELP
]);
6568 if (!STRINGP (help_echo
))
6569 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6570 ->contents
[prop_idx
+ TOOL_BAR_ITEM_CAPTION
]);
6575 /* Find the glyph matrix position of buffer position POS in window W.
6576 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6577 current glyphs must be up to date. If POS is above window start
6578 return (0, 0, 0, 0). If POS is after end of W, return end of
6582 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
)
6585 int *hpos
, *vpos
, *x
, *y
;
6589 int maybe_next_line_p
= 0;
6590 int line_start_position
;
6591 int yb
= window_text_bottom_y (w
);
6592 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0);
6593 struct glyph_row
*best_row
= row
;
6594 int row_vpos
= 0, best_row_vpos
= 0;
6599 if (row
->used
[TEXT_AREA
])
6600 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
6602 line_start_position
= 0;
6604 if (line_start_position
> pos
)
6606 /* If the position sought is the end of the buffer,
6607 don't include the blank lines at the bottom of the window. */
6608 else if (line_start_position
== pos
6609 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
6611 maybe_next_line_p
= 1;
6614 else if (line_start_position
> 0)
6617 best_row_vpos
= row_vpos
;
6624 /* Find the right column within BEST_ROW. */
6626 current_x
= best_row
->x
;
6627 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
6629 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
6632 charpos
= glyph
->charpos
;
6636 *vpos
= best_row_vpos
;
6641 else if (charpos
> pos
)
6643 else if (charpos
> 0)
6646 current_x
+= glyph
->pixel_width
;
6649 /* If we're looking for the end of the buffer,
6650 and we didn't find it in the line we scanned,
6651 use the start of the following line. */
6652 if (maybe_next_line_p
)
6657 current_x
= best_row
->x
;
6660 *vpos
= best_row_vpos
;
6661 *hpos
= lastcol
+ 1;
6668 /* Display the active region described by mouse_face_*
6669 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6672 show_mouse_face (dpyinfo
, draw
)
6673 struct x_display_info
*dpyinfo
;
6674 enum draw_glyphs_face draw
;
6676 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
6677 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6679 int cursor_off_p
= 0;
6680 struct cursor_pos saved_cursor
;
6682 saved_cursor
= output_cursor
;
6684 /* If window is in the process of being destroyed, don't bother
6686 if (w
->current_matrix
== NULL
)
6689 /* Recognize when we are called to operate on rows that don't exist
6690 anymore. This can happen when a window is split. */
6691 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
6694 set_output_cursor (&w
->phys_cursor
);
6696 /* Note that mouse_face_beg_row etc. are window relative. */
6697 for (i
= dpyinfo
->mouse_face_beg_row
;
6698 i
<= dpyinfo
->mouse_face_end_row
;
6701 int start_hpos
, end_hpos
, start_x
;
6702 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
6704 /* Don't do anything if row doesn't have valid contents. */
6705 if (!row
->enabled_p
)
6708 /* For all but the first row, the highlight starts at column 0. */
6709 if (i
== dpyinfo
->mouse_face_beg_row
)
6711 start_hpos
= dpyinfo
->mouse_face_beg_col
;
6712 start_x
= dpyinfo
->mouse_face_beg_x
;
6720 if (i
== dpyinfo
->mouse_face_end_row
)
6721 end_hpos
= dpyinfo
->mouse_face_end_col
;
6723 end_hpos
= row
->used
[TEXT_AREA
];
6725 /* If the cursor's in the text we are about to rewrite, turn the
6727 if (!w
->pseudo_window_p
6728 && i
== output_cursor
.vpos
6729 && output_cursor
.hpos
>= start_hpos
- 1
6730 && output_cursor
.hpos
<= end_hpos
)
6732 x_update_window_cursor (w
, 0);
6736 if (end_hpos
> start_hpos
)
6737 x_draw_glyphs (w
, start_x
, row
, updated_area
,
6738 start_hpos
, end_hpos
, draw
, NULL
, NULL
, 0);
6741 /* If we turned the cursor off, turn it back on. */
6743 x_display_cursor (w
, 1,
6744 output_cursor
.hpos
, output_cursor
.vpos
,
6745 output_cursor
.x
, output_cursor
.y
);
6747 output_cursor
= saved_cursor
;
6751 /* Change the mouse cursor. */
6752 if (draw
== DRAW_NORMAL_TEXT
)
6753 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6754 f
->output_data
.x
->text_cursor
);
6755 else if (draw
== DRAW_MOUSE_FACE
)
6756 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6757 f
->output_data
.x
->cross_cursor
);
6759 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6760 f
->output_data
.x
->nontext_cursor
);
6763 /* Clear out the mouse-highlighted active region.
6764 Redraw it un-highlighted first. */
6767 clear_mouse_face (dpyinfo
)
6768 struct x_display_info
*dpyinfo
;
6773 if (! NILP (dpyinfo
->mouse_face_window
))
6774 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
6776 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6777 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6778 dpyinfo
->mouse_face_window
= Qnil
;
6781 /* Just discard the mouse face information for frame F, if any.
6782 This is used when the size of F is changed. */
6785 cancel_mouse_face (f
)
6789 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6791 window
= dpyinfo
->mouse_face_window
;
6792 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
6794 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6795 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6796 dpyinfo
->mouse_face_window
= Qnil
;
6800 static struct scroll_bar
*x_window_to_scroll_bar ();
6801 static void x_scroll_bar_report_motion ();
6803 /* Return the current position of the mouse.
6804 *fp should be a frame which indicates which display to ask about.
6806 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6807 and *part to the frame, window, and scroll bar part that the mouse
6808 is over. Set *x and *y to the portion and whole of the mouse's
6809 position on the scroll bar.
6811 If the mouse movement started elsewhere, set *fp to the frame the
6812 mouse is on, *bar_window to nil, and *x and *y to the character cell
6815 Set *time to the server time-stamp for the time at which the mouse
6816 was at this position.
6818 Don't store anything if we don't have a valid set of values to report.
6820 This clears the mouse_moved flag, so we can wait for the next mouse
6824 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
6827 Lisp_Object
*bar_window
;
6828 enum scroll_bar_part
*part
;
6830 unsigned long *time
;
6836 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
6837 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
6843 Window dummy_window
;
6846 Lisp_Object frame
, tail
;
6848 /* Clear the mouse-moved flag for every frame on this display. */
6849 FOR_EACH_FRAME (tail
, frame
)
6850 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
6851 XFRAME (frame
)->mouse_moved
= 0;
6853 last_mouse_scroll_bar
= Qnil
;
6855 /* Figure out which root window we're on. */
6856 XQueryPointer (FRAME_X_DISPLAY (*fp
),
6857 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
6859 /* The root window which contains the pointer. */
6862 /* Trash which we can't trust if the pointer is on
6863 a different screen. */
6866 /* The position on that root window. */
6869 /* More trash we can't trust. */
6872 /* Modifier keys and pointer buttons, about which
6874 (unsigned int *) &dummy
);
6876 /* Now we have a position on the root; find the innermost window
6877 containing the pointer. */
6881 int parent_x
= 0, parent_y
= 0;
6886 /* XTranslateCoordinates can get errors if the window
6887 structure is changing at the same time this function
6888 is running. So at least we must not crash from them. */
6890 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
6892 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
6893 && FRAME_LIVE_P (last_mouse_frame
))
6895 /* If mouse was grabbed on a frame, give coords for that frame
6896 even if the mouse is now outside it. */
6897 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
6899 /* From-window, to-window. */
6900 root
, FRAME_X_WINDOW (last_mouse_frame
),
6902 /* From-position, to-position. */
6903 root_x
, root_y
, &win_x
, &win_y
,
6907 f1
= last_mouse_frame
;
6913 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
6915 /* From-window, to-window. */
6918 /* From-position, to-position. */
6919 root_x
, root_y
, &win_x
, &win_y
,
6924 if (child
== None
|| child
== win
)
6932 /* Now we know that:
6933 win is the innermost window containing the pointer
6934 (XTC says it has no child containing the pointer),
6935 win_x and win_y are the pointer's position in it
6936 (XTC did this the last time through), and
6937 parent_x and parent_y are the pointer's position in win's parent.
6938 (They are what win_x and win_y were when win was child.
6939 If win is the root window, it has no parent, and
6940 parent_{x,y} are invalid, but that's okay, because we'll
6941 never use them in that case.) */
6943 /* Is win one of our frames? */
6944 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
6947 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
6950 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
6952 /* If not, is it one of our scroll bars? */
6955 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
6959 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
6965 if (f1
== 0 && insist
> 0)
6966 f1
= SELECTED_FRAME ();
6970 /* Ok, we found a frame. Store all the values.
6971 last_mouse_glyph is a rectangle used to reduce the
6972 generation of mouse events. To not miss any motion
6973 events, we must divide the frame into rectangles of the
6974 size of the smallest character that could be displayed
6975 on it, i.e. into the same rectangles that matrices on
6976 the frame are divided into. */
6978 #if OLD_REDISPLAY_CODE
6979 int ignore1
, ignore2
;
6980 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
6982 FRAME_X_DISPLAY_INFO (f1
)->grabbed
6986 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
6987 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
6991 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6992 round down even for negative values. */
6998 last_mouse_glyph
.width
= width
;
6999 last_mouse_glyph
.height
= height
;
7000 last_mouse_glyph
.x
= (x
+ width
- 1) / width
* width
;
7001 last_mouse_glyph
.y
= (y
+ height
- 1) / height
* height
;
7008 XSETINT (*x
, win_x
);
7009 XSETINT (*y
, win_y
);
7010 *time
= last_mouse_movement_time
;
7019 DEFUN ("xt-process-timeouts", Fxt_process_timeouts
, Sxt_process_timeouts
,
7021 "Arrange for Xt timeout callbacks to be called.")
7024 #ifdef USE_X_TOOLKIT
7026 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
7027 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
7029 #endif /* USE_X_TOOLKIT */
7036 /* Scroll bar support. */
7038 /* Given an X window ID, find the struct scroll_bar which manages it.
7039 This can be called in GC, so we have to make sure to strip off mark
7041 static struct scroll_bar
*
7042 x_window_to_scroll_bar (window_id
)
7047 for (tail
= Vframe_list
;
7048 XGCTYPE (tail
) == Lisp_Cons
;
7051 Lisp_Object frame
, bar
, condemned
;
7053 frame
= XCAR (tail
);
7054 /* All elements of Vframe_list should be frames. */
7055 if (! GC_FRAMEP (frame
))
7058 /* Scan this frame's scroll bar list for a scroll bar with the
7060 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
7061 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
7062 /* This trick allows us to search both the ordinary and
7063 condemned scroll bar lists with one loop. */
7064 ! GC_NILP (bar
) || (bar
= condemned
,
7067 bar
= XSCROLL_BAR (bar
)->next
)
7068 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
7069 return XSCROLL_BAR (bar
);
7077 /************************************************************************
7079 ************************************************************************/
7081 #if USE_TOOLKIT_SCROLL_BARS
7083 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
7084 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
7085 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
7086 struct scroll_bar
*));
7087 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
7091 /* Id of action hook installed for scroll bars. */
7093 static XtActionHookId action_hook_id
;
7095 /* Lisp window being scrolled. Set when starting to interact with
7096 a toolkit scroll bar, reset to nil when ending the interaction. */
7098 static Lisp_Object window_being_scrolled
;
7100 /* Last scroll bar part sent in xm_scroll_callback. */
7102 static int last_scroll_bar_part
;
7105 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7106 bars are used.. The hoos is responsible for detecting when
7107 the user ends an interaction with the scroll bar, and generates
7108 a `end-scroll' scroll_bar_click' event if so. */
7111 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
7114 XtPointer client_data
;
7118 Cardinal
*num_params
;
7124 scroll_bar_p
= XmIsScrollBar (widget
);
7125 end_action
= "Release";
7126 #elif defined HAVE_XAW3D
7127 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
7128 end_action
= "EndScroll";
7130 #error unknown scroll bar toolkit
7131 #endif /* HAVE_XAW3D */
7133 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
7134 let Xt timeouts be processed doesn't work. */
7136 && strcmp (action_name
, end_action
) == 0
7137 && WINDOWP (window_being_scrolled
))
7141 x_send_scroll_bar_event (window_being_scrolled
,
7142 scroll_bar_end_scroll
, 0, 0);
7143 w
= XWINDOW (window_being_scrolled
);
7144 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
7145 window_being_scrolled
= Qnil
;
7146 last_scroll_bar_part
= -1;
7151 /* Send a client message with message type Xatom_Scrollbar for a
7152 scroll action to the frame of WINDOW. PART is a value identifying
7153 the part of the scroll bar that was clicked on. PORTION is the
7154 amount to scroll of a whole of WHOLE. */
7157 x_send_scroll_bar_event (window
, part
, portion
, whole
)
7159 int part
, portion
, whole
;
7162 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
7163 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7165 /* Construct a ClientMessage event to send to the frame. */
7166 ev
->type
= ClientMessage
;
7167 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
7168 ev
->display
= FRAME_X_DISPLAY (f
);
7169 ev
->window
= FRAME_X_WINDOW (f
);
7171 ev
->data
.l
[0] = (long) window
;
7172 ev
->data
.l
[1] = (long) part
;
7173 ev
->data
.l
[2] = (long) 0;
7174 ev
->data
.l
[3] = (long) portion
;
7175 ev
->data
.l
[4] = (long) whole
;
7177 /* Setting the event mask to zero means that the message will
7178 be sent to the client that created the window, and if that
7179 window no longer exists, no event will be sent. */
7181 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
7186 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7190 x_scroll_bar_to_input_event (event
, ievent
)
7192 struct input_event
*ievent
;
7194 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
7195 Lisp_Object window
= (Lisp_Object
) ev
->data
.l
[0];
7196 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7198 ievent
->kind
= scroll_bar_click
;
7199 ievent
->frame_or_window
= window
;
7200 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
7201 ievent
->part
= ev
->data
.l
[1];
7202 ievent
->code
= ev
->data
.l
[2];
7203 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
7204 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
7205 ievent
->modifiers
= 0;
7211 /* Minimum and maximum values used for Motif scroll bars. */
7214 #define XM_SB_MAX 10000000
7215 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7218 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7219 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7220 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7223 xm_scroll_callback (widget
, client_data
, call_data
)
7225 XtPointer client_data
, call_data
;
7227 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7228 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
7230 int part
= -1, whole
= 0, portion
= 0;
7234 case XmCR_DECREMENT
:
7235 bar
->dragging
= Qnil
;
7236 part
= scroll_bar_up_arrow
;
7239 case XmCR_INCREMENT
:
7240 bar
->dragging
= Qnil
;
7241 part
= scroll_bar_down_arrow
;
7244 case XmCR_PAGE_DECREMENT
:
7245 bar
->dragging
= Qnil
;
7246 part
= scroll_bar_above_handle
;
7249 case XmCR_PAGE_INCREMENT
:
7250 bar
->dragging
= Qnil
;
7251 part
= scroll_bar_below_handle
;
7255 bar
->dragging
= Qnil
;
7256 part
= scroll_bar_to_top
;
7259 case XmCR_TO_BOTTOM
:
7260 bar
->dragging
= Qnil
;
7261 part
= scroll_bar_to_bottom
;
7267 int dragging_down_p
= (INTEGERP (bar
->dragging
)
7268 && XINT (bar
->dragging
) <= cs
->value
);
7270 /* Get the slider size. */
7272 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
7275 /* At the max position of the scroll bar, do a line-wise
7276 movement. Without doing anything, the LessTif scroll bar
7277 calls us with the same cs->value again and again. If we
7278 want to make sure that we can reach the end of the buffer,
7279 we have to do something.
7281 Implementation note: setting bar->dragging always to
7282 cs->value gives a smoother movement at the max position.
7283 Setting it to nil when doing line-wise movement gives
7284 a better slider behavior. */
7286 if (cs
->value
+ slider_size
== XM_SB_MAX
7288 && last_scroll_bar_part
== scroll_bar_down_arrow
))
7290 part
= scroll_bar_down_arrow
;
7291 bar
->dragging
= Qnil
;
7295 whole
= XM_SB_RANGE
;
7296 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
7297 part
= scroll_bar_handle
;
7298 bar
->dragging
= make_number (cs
->value
);
7303 case XmCR_VALUE_CHANGED
:
7309 window_being_scrolled
= bar
->window
;
7310 last_scroll_bar_part
= part
;
7311 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7316 #else /* not USE_MOTIF, i.e. XAW3D. */
7319 /* Xaw3d scroll bar callback. Invoked when the thumb is dragged.
7320 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7321 scroll bar struct. CALL_DATA is a pointer to a float saying where
7325 xaw3d_jump_callback (widget
, client_data
, call_data
)
7327 XtPointer client_data
, call_data
;
7329 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7330 float top
= *(float *) call_data
;
7333 int dragging_down_p
, part
;
7334 double epsilon
= 0.01;
7336 /* Get the size of the thumb, a value between 0 and 1. */
7338 XtVaGetValues (widget
, XtNshown
, &shown
, NULL
);
7342 portion
= shown
< 1 ? top
* whole
: 0;
7343 dragging_down_p
= (INTEGERP (bar
->dragging
)
7344 && XINT (bar
->dragging
) < portion
);
7347 && (abs (top
+ shown
- 1) < epsilon
7349 && last_scroll_bar_part
== scroll_bar_down_arrow
)))
7350 part
= scroll_bar_down_arrow
;
7352 part
= scroll_bar_handle
;
7354 window_being_scrolled
= bar
->window
;
7355 bar
->dragging
= make_number (portion
);
7356 last_scroll_bar_part
= part
;
7357 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7361 /* Xaw3d scroll bar callback. Invoked for incremental scrolling.,
7362 i.e. line or page up or down. WIDGET is the Xaw3d scroll bar
7363 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7364 the scroll bar. CALL_DATA is an integer specifying the action that
7365 has taken place. It's magnitude is in the range 0..height of the
7366 scroll bar. Negative values mean scroll towards buffer start.
7367 Values < height of scroll bar mean line-wise movement. */
7370 xaw3d_scroll_callback (widget
, client_data
, call_data
)
7372 XtPointer client_data
, call_data
;
7374 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7375 int position
= (int) call_data
;
7379 /* Get the height of the scroll bar. */
7381 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
7386 if (abs (position
) < height
)
7387 part
= scroll_bar_up_arrow
;
7389 part
= scroll_bar_above_handle
;
7393 if (abs (position
) < height
)
7394 part
= scroll_bar_down_arrow
;
7396 part
= scroll_bar_below_handle
;
7399 window_being_scrolled
= bar
->window
;
7400 bar
->dragging
= Qnil
;
7401 last_scroll_bar_part
= part
;
7402 x_send_scroll_bar_event (bar
->window
, part
, 0, 0);
7406 #endif /* not USE_MOTIF */
7409 /* Create the widget for scroll bar BAR on frame F. Record the widget
7410 and X window of the scroll bar in BAR. */
7413 x_create_toolkit_scroll_bar (f
, bar
)
7415 struct scroll_bar
*bar
;
7421 char *scroll_bar_name
= "verticalScrollBar";
7422 unsigned long pixel
;
7427 /* LessTif 0.85, problems:
7429 1. When the mouse if over the scroll bar, the scroll bar will
7430 get keyboard events. I didn't find a way to turn this off.
7432 2. Do we have to explicitly set the cursor to get an arrow
7433 cursor (see below)? */
7435 /* Set resources. Create the widget. */
7436 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7437 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
7438 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
7439 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
7440 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
7441 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
7442 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
7444 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7447 XtSetArg (av
[ac
], XmNforeground
, pixel
);
7451 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7454 XtSetArg (av
[ac
], XmNbackground
, pixel
);
7458 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
7459 scroll_bar_name
, av
, ac
);
7461 /* Add one callback for everything that can happen. */
7462 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
7464 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
7466 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
7468 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
7470 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
7472 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
7474 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
7477 /* Realize the widget. Only after that is the X window created. */
7478 XtRealizeWidget (widget
);
7480 /* Set the cursor to an arrow. I didn't find a resource to do that.
7481 And I'm wondering why it hasn't an arrow cursor by default. */
7482 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
7483 f
->output_data
.x
->nontext_cursor
);
7485 #elif defined HAVE_XAW3D
7487 /* Set resources. Create the widget. The background of the
7488 Xaw3d scroll bar widget is a little bit light for my taste.
7489 We don't alter it here to let users change it according
7490 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7491 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7492 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
7493 XtSetArg (av
[ac
], XtNcursorName
, "left_ptr"); ++ac
;
7494 XtSetArg (av
[ac
], XtNbeNiceToColormap
, True
); ++ac
;
7496 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7499 XtSetArg (av
[ac
], XtNforeground
, pixel
);
7503 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7506 XtSetArg (av
[ac
], XtNbackground
, pixel
);
7510 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
7511 f
->output_data
.x
->edit_widget
, av
, ac
);
7513 /* Define callbacks. */
7514 XtAddCallback (widget
, XtNjumpProc
, xaw3d_jump_callback
, (XtPointer
) bar
);
7515 XtAddCallback (widget
, XtNscrollProc
, xaw3d_scroll_callback
,
7518 /* Realize the widget. Only after that is the X window created. */
7519 XtRealizeWidget (widget
);
7521 #endif /* HAVE_XAW3D */
7523 /* Install an action hook that let's us detect when the user
7524 finishes interacting with a scroll bar. */
7525 if (action_hook_id
== 0)
7526 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
7528 /* Remember X window and widget in the scroll bar vector. */
7529 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
7530 xwindow
= XtWindow (widget
);
7531 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
7537 /* Set the thumb size and position of scroll bar BAR. We are currently
7538 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7541 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
7542 struct scroll_bar
*bar
;
7543 int portion
, position
, whole
;
7546 Widget widget
= SCROLL_BAR_X_WIDGET (bar
);
7552 top
= (float) position
/ whole
;
7553 shown
= (float) portion
/ whole
;
7561 Boolean arrow1_selected
, arrow2_selected
;
7562 unsigned char flags
;
7563 XmScrollBarWidget sb
;
7565 /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX
7566 is the scroll bar's maximum and MIN is the scroll bar's minimum
7568 size
= shown
* XM_SB_RANGE
;
7569 size
= min (size
, XM_SB_RANGE
);
7570 size
= max (size
, 1);
7572 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7573 value
= top
* XM_SB_RANGE
;
7574 value
= min (value
, XM_SB_MAX
- size
);
7575 value
= max (value
, XM_SB_MIN
);
7577 /* LessTif: Calling XmScrollBarSetValues after an increment or
7578 decrement turns off auto-repeat LessTif-internally. This can
7579 be seen in ScrollBar.c which resets Arrow1Selected and
7580 Arrow2Selected. It also sets internal flags so that LessTif
7581 believes the mouse is in the slider. We either have to change
7582 our code, or work around that by accessing private data. */
7584 sb
= (XmScrollBarWidget
) widget
;
7585 arrow1_selected
= sb
->scrollBar
.arrow1_selected
;
7586 arrow2_selected
= sb
->scrollBar
.arrow2_selected
;
7587 flags
= sb
->scrollBar
.flags
;
7589 if (NILP (bar
->dragging
))
7590 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
7591 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7592 /* This has the negative side effect that the slider value is
7593 not would it would be if we scrolled here using line-wise or
7594 page-wise movement. */
7595 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
7598 /* If currently dragging, only update the slider size.
7599 This reduces flicker effects. */
7600 int old_value
, old_size
, increment
, page_increment
;
7602 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
7603 &increment
, &page_increment
);
7604 XmScrollBarSetValues (widget
, old_value
,
7605 min (size
, XM_SB_RANGE
- old_value
),
7609 sb
->scrollBar
.arrow1_selected
= arrow1_selected
;
7610 sb
->scrollBar
.arrow2_selected
= arrow2_selected
;
7611 sb
->scrollBar
.flags
= flags
;
7613 #elif defined HAVE_XAW3D
7615 /* Restrict to [0 1]. */
7616 top
= max (0, min (1, top
));
7617 shown
= max (0, min (1, shown
));
7619 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7620 check that your system's configuration file contains a define
7621 for `NARROWPROTO'. See s/freebsd.h for an example. */
7622 if (NILP (bar
->dragging
))
7624 float old_top
, old_shown
;
7625 XtVaGetValues (widget
, XtNtopOfThumb
, &old_top
, XtNshown
, &old_shown
,
7627 if (top
!= old_top
|| shown
!= old_shown
)
7628 XawScrollbarSetThumb (widget
, top
, shown
);
7632 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
7633 int scroll_mode
= sb
->scrollbar
.scroll_mode
;
7635 sb
->scrollbar
.scroll_mode
= 0;
7637 if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7638 XawScrollbarSetThumb (widget
, top
, 1 - top
);
7642 XtVaGetValues (widget
, XtNtopOfThumb
, &old_top
, NULL
);
7643 XawScrollbarSetThumb (widget
, old_top
, min (shown
, 1 - old_top
));
7646 sb
->scrollbar
.scroll_mode
= scroll_mode
;
7649 #endif /* HAVE_XAW3D */
7654 #endif /* USE_TOOLKIT_SCROLL_BARS */
7658 /************************************************************************
7659 Scroll bars, general
7660 ************************************************************************/
7662 /* Create a scroll bar and return the scroll bar vector for it. W is
7663 the Emacs window on which to create the scroll bar. TOP, LEFT,
7664 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7667 static struct scroll_bar
*
7668 x_scroll_bar_create (w
, top
, left
, width
, height
)
7670 int top
, left
, width
, height
;
7672 struct frame
*f
= XFRAME (w
->frame
);
7673 struct scroll_bar
*bar
7674 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
7678 #if USE_TOOLKIT_SCROLL_BARS
7679 x_create_toolkit_scroll_bar (f
, bar
);
7680 #else /* not USE_TOOLKIT_SCROLL_BARS */
7682 XSetWindowAttributes a
;
7686 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7687 if (a
.background_pixel
== -1)
7688 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
7690 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
7691 | ButtonMotionMask
| PointerMotionHintMask
7693 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
7695 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
7697 /* Clear the area of W that will serve as a scroll bar. This is
7698 for the case that a window has been split horizontally. In
7699 this case, no clear_frame is generated to reduce flickering. */
7700 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7702 window_box_height (w
), False
);
7704 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7705 /* Position and size of scroll bar. */
7706 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7708 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7710 /* Border width, depth, class, and visual. */
7717 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
7719 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7721 XSETWINDOW (bar
->window
, w
);
7722 XSETINT (bar
->top
, top
);
7723 XSETINT (bar
->left
, left
);
7724 XSETINT (bar
->width
, width
);
7725 XSETINT (bar
->height
, height
);
7726 XSETINT (bar
->start
, 0);
7727 XSETINT (bar
->end
, 0);
7728 bar
->dragging
= Qnil
;
7730 /* Add bar to its frame's list of scroll bars. */
7731 bar
->next
= FRAME_SCROLL_BARS (f
);
7733 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
7734 if (!NILP (bar
->next
))
7735 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
7737 /* Map the window/widget. */
7738 #if USE_TOOLKIT_SCROLL_BARS
7739 XtMapWidget (SCROLL_BAR_X_WIDGET (bar
));
7740 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
7741 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7743 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7745 #else /* not USE_TOOLKIT_SCROLL_BARS */
7746 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
7747 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7754 /* Draw BAR's handle in the proper position.
7756 If the handle is already drawn from START to END, don't bother
7757 redrawing it, unless REBUILD is non-zero; in that case, always
7758 redraw it. (REBUILD is handy for drawing the handle after expose
7761 Normally, we want to constrain the start and end of the handle to
7762 fit inside its rectangle, but if the user is dragging the scroll
7763 bar handle, we want to let them drag it down all the way, so that
7764 the bar's top is as far down as it goes; otherwise, there's no way
7765 to move to the very end of the buffer. */
7767 #ifndef USE_TOOLKIT_SCROLL_BARS
7770 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
7771 struct scroll_bar
*bar
;
7775 int dragging
= ! NILP (bar
->dragging
);
7776 Window w
= SCROLL_BAR_X_WINDOW (bar
);
7777 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7778 GC gc
= f
->output_data
.x
->normal_gc
;
7780 /* If the display is already accurate, do nothing. */
7782 && start
== XINT (bar
->start
)
7783 && end
== XINT (bar
->end
))
7789 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
7790 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
7791 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
7793 /* Make sure the values are reasonable, and try to preserve
7794 the distance between start and end. */
7796 int length
= end
- start
;
7800 else if (start
> top_range
)
7802 end
= start
+ length
;
7806 else if (end
> top_range
&& ! dragging
)
7810 /* Store the adjusted setting in the scroll bar. */
7811 XSETINT (bar
->start
, start
);
7812 XSETINT (bar
->end
, end
);
7814 /* Clip the end position, just for display. */
7815 if (end
> top_range
)
7818 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
7819 below top positions, to make sure the handle is always at least
7820 that many pixels tall. */
7821 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
7823 /* Draw the empty space above the handle. Note that we can't clear
7824 zero-height areas; that means "clear to end of window." */
7826 XClearArea (FRAME_X_DISPLAY (f
), w
,
7828 /* x, y, width, height, and exposures. */
7829 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
7830 VERTICAL_SCROLL_BAR_TOP_BORDER
,
7831 inside_width
, start
,
7834 /* Change to proper foreground color if one is specified. */
7835 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
7836 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
7837 f
->output_data
.x
->scroll_bar_foreground_pixel
);
7839 /* Draw the handle itself. */
7840 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
7842 /* x, y, width, height */
7843 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
7844 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
7845 inside_width
, end
- start
);
7847 /* Restore the foreground color of the GC if we changed it above. */
7848 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
7849 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
7850 f
->output_data
.x
->foreground_pixel
);
7852 /* Draw the empty space below the handle. Note that we can't
7853 clear zero-height areas; that means "clear to end of window." */
7854 if (end
< inside_height
)
7855 XClearArea (FRAME_X_DISPLAY (f
), w
,
7857 /* x, y, width, height, and exposures. */
7858 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
7859 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
7860 inside_width
, inside_height
- end
,
7868 #endif /* !USE_TOOLKIT_SCROLL_BARS */
7870 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7874 x_scroll_bar_remove (bar
)
7875 struct scroll_bar
*bar
;
7879 #if USE_TOOLKIT_SCROLL_BARS
7880 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar
));
7881 #else /* not USE_TOOLKIT_SCROLL_BARS */
7883 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7884 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
7886 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7888 /* Disassociate this scroll bar from its window. */
7889 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
7895 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7896 that we are displaying PORTION characters out of a total of WHOLE
7897 characters, starting at POSITION. If WINDOW has no scroll bar,
7901 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
7903 int portion
, whole
, position
;
7905 struct frame
*f
= XFRAME (w
->frame
);
7906 struct scroll_bar
*bar
;
7907 int top
, height
, left
, sb_left
, width
, sb_width
;
7908 int window_x
, window_y
, window_width
, window_height
;
7910 /* Get window dimensions. */
7911 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
7913 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
7914 height
= window_height
;
7916 /* Compute the left edge of the scroll bar area. */
7917 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
7918 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
7920 left
= XFASTINT (w
->left
);
7921 left
*= CANON_X_UNIT (f
);
7922 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
7924 /* Compute the width of the scroll bar which might be less than
7925 the width of the area reserved for the scroll bar. */
7926 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
7927 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
7931 /* Compute the left edge of the scroll bar. */
7932 #ifdef USE_TOOLKIT_SCROLL_BARS
7933 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
7934 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
7936 sb_left
= left
+ (width
- sb_width
) / 2;
7938 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
7939 sb_left
= left
+ width
- sb_width
;
7944 /* Does the scroll bar exist yet? */
7945 if (NILP (w
->vertical_scroll_bar
))
7948 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7949 left
, top
, width
, height
, False
);
7951 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
7955 /* It may just need to be moved and resized. */
7956 unsigned int mask
= 0;
7958 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
7962 if (sb_left
!= XINT (bar
->left
))
7964 if (top
!= XINT (bar
->top
))
7966 if (sb_width
!= XINT (bar
->width
))
7968 if (height
!= XINT (bar
->height
))
7971 #ifdef USE_TOOLKIT_SCROLL_BARS
7973 /* Since toolkit scroll bars are smaller than the space reserved
7974 for them on the frame, we have to clear "under" them. */
7975 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7976 left
, top
, width
, height
, False
);
7978 /* Move/size the scroll bar widget. */
7980 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
7981 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7983 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7986 #else /* not USE_TOOLKIT_SCROLL_BARS */
7988 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
7990 /* Clear areas not covered by the scroll bar. This makes sure a
7991 previous mode line display is cleared after C-x 2 C-x 1, for
7992 example. Non-toolkit scroll bars are as wide as the area
7993 reserved for scroll bars - trim at both sides. */
7994 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7995 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7997 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7998 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7999 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8003 /* Move/size the scroll bar window. */
8008 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8010 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
8012 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
8016 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8018 /* Remember new settings. */
8019 XSETINT (bar
->left
, sb_left
);
8020 XSETINT (bar
->top
, top
);
8021 XSETINT (bar
->width
, sb_width
);
8022 XSETINT (bar
->height
, height
);
8027 #if USE_TOOLKIT_SCROLL_BARS
8028 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
8029 #else /* not USE_TOOLKIT_SCROLL_BARS */
8030 /* Set the scroll bar's current state, unless we're currently being
8032 if (NILP (bar
->dragging
))
8034 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8037 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8040 int start
= ((double) position
* top_range
) / whole
;
8041 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8042 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8045 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8047 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8051 /* The following three hooks are used when we're doing a thorough
8052 redisplay of the frame. We don't explicitly know which scroll bars
8053 are going to be deleted, because keeping track of when windows go
8054 away is a real pain - "Can you say set-window-configuration, boys
8055 and girls?" Instead, we just assert at the beginning of redisplay
8056 that *all* scroll bars are to be removed, and then save a scroll bar
8057 from the fiery pit when we actually redisplay its window. */
8059 /* Arrange for all scroll bars on FRAME to be removed at the next call
8060 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8061 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8064 XTcondemn_scroll_bars (frame
)
8067 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8068 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8071 bar
= FRAME_SCROLL_BARS (frame
);
8072 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8073 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8074 XSCROLL_BAR (bar
)->prev
= Qnil
;
8075 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8076 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8077 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8081 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8082 Note that WINDOW isn't necessarily condemned at all. */
8084 XTredeem_scroll_bar (window
)
8085 struct window
*window
;
8087 struct scroll_bar
*bar
;
8089 /* We can't redeem this window's scroll bar if it doesn't have one. */
8090 if (NILP (window
->vertical_scroll_bar
))
8093 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8095 /* Unlink it from the condemned list. */
8097 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
8099 if (NILP (bar
->prev
))
8101 /* If the prev pointer is nil, it must be the first in one of
8103 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8104 /* It's not condemned. Everything's fine. */
8106 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8107 window
->vertical_scroll_bar
))
8108 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8110 /* If its prev pointer is nil, it must be at the front of
8111 one or the other! */
8115 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8117 if (! NILP (bar
->next
))
8118 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8120 bar
->next
= FRAME_SCROLL_BARS (f
);
8122 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8123 if (! NILP (bar
->next
))
8124 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8128 /* Remove all scroll bars on FRAME that haven't been saved since the
8129 last call to `*condemn_scroll_bars_hook'. */
8132 XTjudge_scroll_bars (f
)
8135 Lisp_Object bar
, next
;
8137 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8139 /* Clear out the condemned list now so we won't try to process any
8140 more events on the hapless scroll bars. */
8141 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8143 for (; ! NILP (bar
); bar
= next
)
8145 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8147 x_scroll_bar_remove (b
);
8150 b
->next
= b
->prev
= Qnil
;
8153 /* Now there should be no references to the condemned scroll bars,
8154 and they should get garbage-collected. */
8158 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8159 is a no-op when using toolkit scroll bars.
8161 This may be called from a signal handler, so we have to ignore GC
8165 x_scroll_bar_expose (bar
, event
)
8166 struct scroll_bar
*bar
;
8169 #ifndef USE_TOOLKIT_SCROLL_BARS
8171 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8172 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8173 GC gc
= f
->output_data
.x
->normal_gc
;
8174 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8178 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
8180 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8181 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8183 /* x, y, width, height */
8185 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
8186 XINT (bar
->height
) - 1);
8190 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8193 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8194 is set to something other than no_event, it is enqueued.
8196 This may be called from a signal handler, so we have to ignore GC
8199 #ifndef USE_TOOLKIT_SCROLL_BARS
8202 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
8203 struct scroll_bar
*bar
;
8205 struct input_event
*emacs_event
;
8207 if (! GC_WINDOWP (bar
->window
))
8210 emacs_event
->kind
= scroll_bar_click
;
8211 emacs_event
->code
= event
->xbutton
.button
- Button1
;
8212 emacs_event
->modifiers
8213 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8214 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
8215 event
->xbutton
.state
)
8216 | (event
->type
== ButtonRelease
8219 emacs_event
->frame_or_window
= bar
->window
;
8220 emacs_event
->timestamp
= event
->xbutton
.time
;
8223 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8225 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8228 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8229 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
8232 if (y
> top_range
) y
= top_range
;
8234 if (y
< XINT (bar
->start
))
8235 emacs_event
->part
= scroll_bar_above_handle
;
8236 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8237 emacs_event
->part
= scroll_bar_handle
;
8239 emacs_event
->part
= scroll_bar_below_handle
;
8241 /* Just because the user has clicked on the handle doesn't mean
8242 they want to drag it. Lisp code needs to be able to decide
8243 whether or not we're dragging. */
8245 /* If the user has just clicked on the handle, record where they're
8247 if (event
->type
== ButtonPress
8248 && emacs_event
->part
== scroll_bar_handle
)
8249 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
8252 /* If the user has released the handle, set it to its final position. */
8253 if (event
->type
== ButtonRelease
8254 && ! NILP (bar
->dragging
))
8256 int new_start
= y
- XINT (bar
->dragging
);
8257 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8259 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8260 bar
->dragging
= Qnil
;
8263 /* Same deal here as the other #if 0. */
8265 /* Clicks on the handle are always reported as occurring at the top of
8267 if (emacs_event
->part
== scroll_bar_handle
)
8268 emacs_event
->x
= bar
->start
;
8270 XSETINT (emacs_event
->x
, y
);
8272 XSETINT (emacs_event
->x
, y
);
8275 XSETINT (emacs_event
->y
, top_range
);
8279 /* Handle some mouse motion while someone is dragging the scroll bar.
8281 This may be called from a signal handler, so we have to ignore GC
8285 x_scroll_bar_note_movement (bar
, event
)
8286 struct scroll_bar
*bar
;
8289 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8291 last_mouse_movement_time
= event
->xmotion
.time
;
8294 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8296 /* If we're dragging the bar, display it. */
8297 if (! GC_NILP (bar
->dragging
))
8299 /* Where should the handle be now? */
8300 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
8302 if (new_start
!= XINT (bar
->start
))
8304 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8306 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8311 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8313 /* Return information to the user about the current position of the mouse
8314 on the scroll bar. */
8317 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8319 Lisp_Object
*bar_window
;
8320 enum scroll_bar_part
*part
;
8322 unsigned long *time
;
8324 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8325 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8326 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8328 Window dummy_window
;
8330 unsigned int dummy_mask
;
8334 /* Get the mouse's position relative to the scroll bar window, and
8336 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
8338 /* Root, child, root x and root y. */
8339 &dummy_window
, &dummy_window
,
8340 &dummy_coord
, &dummy_coord
,
8342 /* Position relative to scroll bar. */
8345 /* Mouse buttons and modifier keys. */
8352 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8355 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8357 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8359 if (! NILP (bar
->dragging
))
8360 win_y
-= XINT (bar
->dragging
);
8364 if (win_y
> top_range
)
8368 *bar_window
= bar
->window
;
8370 if (! NILP (bar
->dragging
))
8371 *part
= scroll_bar_handle
;
8372 else if (win_y
< XINT (bar
->start
))
8373 *part
= scroll_bar_above_handle
;
8374 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8375 *part
= scroll_bar_handle
;
8377 *part
= scroll_bar_below_handle
;
8379 XSETINT (*x
, win_y
);
8380 XSETINT (*y
, top_range
);
8383 last_mouse_scroll_bar
= Qnil
;
8386 *time
= last_mouse_movement_time
;
8392 /* The screen has been cleared so we may have changed foreground or
8393 background colors, and the scroll bars may need to be redrawn.
8394 Clear out the scroll bars, and ask for expose events, so we can
8398 x_scroll_bar_clear (f
)
8401 #ifndef USE_TOOLKIT_SCROLL_BARS
8404 /* We can have scroll bars even if this is 0,
8405 if we just turned off scroll bar mode.
8406 But in that case we should not clear them. */
8407 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8408 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
8409 bar
= XSCROLL_BAR (bar
)->next
)
8410 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
8412 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8415 /* This processes Expose events from the menu-bar specific X event
8416 loop in xmenu.c. This allows to redisplay the frame if necessary
8417 when handling menu-bar or pop-up items. */
8420 process_expose_from_menu (event
)
8424 struct x_display_info
*dpyinfo
;
8425 int frame_exposed_p
= 0;
8429 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
8430 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8433 if (f
->async_visible
== 0)
8435 f
->async_visible
= 1;
8436 f
->async_iconified
= 0;
8437 f
->output_data
.x
->has_been_visible
= 1;
8438 SET_FRAME_GARBAGED (f
);
8442 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
8443 event
.xexpose
.x
, event
.xexpose
.y
,
8444 event
.xexpose
.width
, event
.xexpose
.height
);
8445 frame_exposed_p
= 1;
8450 struct scroll_bar
*bar
8451 = x_window_to_scroll_bar (event
.xexpose
.window
);
8454 x_scroll_bar_expose (bar
, &event
);
8458 return frame_exposed_p
;
8461 /* Define a queue to save up SelectionRequest events for later handling. */
8463 struct selection_event_queue
8466 struct selection_event_queue
*next
;
8469 static struct selection_event_queue
*queue
;
8471 /* Nonzero means queue up certain events--don't process them yet. */
8473 static int x_queue_selection_requests
;
8475 /* Queue up an X event *EVENT, to be processed later. */
8478 x_queue_event (f
, event
)
8482 struct selection_event_queue
*queue_tmp
8483 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
8485 if (queue_tmp
!= NULL
)
8487 queue_tmp
->event
= *event
;
8488 queue_tmp
->next
= queue
;
8493 /* Take all the queued events and put them back
8494 so that they get processed afresh. */
8497 x_unqueue_events (display
)
8500 while (queue
!= NULL
)
8502 struct selection_event_queue
*queue_tmp
= queue
;
8503 XPutBackEvent (display
, &queue_tmp
->event
);
8504 queue
= queue_tmp
->next
;
8505 xfree ((char *)queue_tmp
);
8509 /* Start queuing SelectionRequest events. */
8512 x_start_queuing_selection_requests (display
)
8515 x_queue_selection_requests
++;
8518 /* Stop queuing SelectionRequest events. */
8521 x_stop_queuing_selection_requests (display
)
8524 x_queue_selection_requests
--;
8525 x_unqueue_events (display
);
8528 /* The main X event-reading loop - XTread_socket. */
8530 /* Time stamp of enter window event. This is only used by XTread_socket,
8531 but we have to put it out here, since static variables within functions
8532 sometimes don't work. */
8534 static Time enter_timestamp
;
8536 /* This holds the state XLookupString needs to implement dead keys
8537 and other tricks known as "compose processing". _X Window System_
8538 says that a portable program can't use this, but Stephen Gildea assures
8539 me that letting the compiler initialize it to zeros will work okay.
8541 This must be defined outside of XTread_socket, for the same reasons
8542 given for enter_time stamp, above. */
8544 static XComposeStatus compose_status
;
8546 /* Record the last 100 characters stored
8547 to help debug the loss-of-chars-during-GC problem. */
8549 static int temp_index
;
8550 static short temp_buffer
[100];
8552 /* Set this to nonzero to fake an "X I/O error"
8553 on a particular display. */
8555 struct x_display_info
*XTread_socket_fake_io_error
;
8557 /* When we find no input here, we occasionally do a no-op command
8558 to verify that the X server is still running and we can still talk with it.
8559 We try all the open displays, one by one.
8560 This variable is used for cycling thru the displays. */
8562 static struct x_display_info
*next_noop_dpyinfo
;
8564 #define SET_SAVED_MENU_EVENT(size) \
8567 if (f->output_data.x->saved_menu_event == 0) \
8568 f->output_data.x->saved_menu_event \
8569 = (XEvent *) xmalloc (sizeof (XEvent)); \
8570 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8571 if (numchars >= 1) \
8573 bufp->kind = menu_bar_activate_event; \
8574 XSETFRAME (bufp->frame_or_window, f); \
8582 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8583 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8585 /* Read events coming from the X server.
8586 This routine is called by the SIGIO handler.
8587 We return as soon as there are no more events to be read.
8589 Events representing keys are stored in buffer BUFP,
8590 which can hold up to NUMCHARS characters.
8591 We return the number of characters stored into the buffer,
8592 thus pretending to be `read'.
8594 EXPECTED is nonzero if the caller knows input is available. */
8597 XTread_socket (sd
, bufp
, numchars
, expected
)
8599 /* register */ struct input_event
*bufp
;
8600 /* register */ int numchars
;
8607 int event_found
= 0;
8608 struct x_display_info
*dpyinfo
;
8610 Status status_return
;
8613 if (interrupt_input_blocked
)
8615 interrupt_input_pending
= 1;
8619 interrupt_input_pending
= 0;
8622 /* So people can tell when we have read the available input. */
8623 input_signal_count
++;
8626 abort (); /* Don't think this happens. */
8628 /* Find the display we are supposed to read input for.
8629 It's the one communicating on descriptor SD. */
8630 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
8632 #if 0 /* This ought to be unnecessary; let's verify it. */
8634 /* If available, Xlib uses FIOSNBIO to make the socket
8635 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8636 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8637 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8638 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
8639 #endif /* ! defined (FIOSNBIO) */
8642 #if 0 /* This code can't be made to work, with multiple displays,
8643 and appears not to be used on any system any more.
8644 Also keyboard.c doesn't turn O_NDELAY on and off
8645 for X connections. */
8648 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
8650 extern int read_alarm_should_throw
;
8651 read_alarm_should_throw
= 1;
8652 XPeekEvent (dpyinfo
->display
, &event
);
8653 read_alarm_should_throw
= 0;
8655 #endif /* HAVE_SELECT */
8659 /* For debugging, this gives a way to fake an I/O error. */
8660 if (dpyinfo
== XTread_socket_fake_io_error
)
8662 XTread_socket_fake_io_error
= 0;
8663 x_io_error_quitter (dpyinfo
->display
);
8666 while (XPending (dpyinfo
->display
))
8668 XNextEvent (dpyinfo
->display
, &event
);
8670 if (display_busy_cursor_p
)
8672 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8673 display until the next X event is read and we come
8674 here again. Setting it to 1 inhibits busy-cursor
8675 display for direct commands. */
8676 if (event
.type
== MotionNotify
8677 || event
.type
== EnterNotify
8678 || (dpyinfo
->grabbed
8679 && event
.type
!= ButtonRelease
))
8680 inhibit_busy_cursor
= 2;
8682 inhibit_busy_cursor
= 1;
8687 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
8688 event
.xclient
.window
);
8689 /* The necessity of the following line took me
8690 a full work-day to decipher from the docs!! */
8691 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
8701 if (event
.xclient
.message_type
8702 == dpyinfo
->Xatom_wm_protocols
8703 && event
.xclient
.format
== 32)
8705 if (event
.xclient
.data
.l
[0]
8706 == dpyinfo
->Xatom_wm_take_focus
)
8708 /* Use x_any_window_to_frame because this
8709 could be the shell widget window
8710 if the frame has no title bar. */
8711 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8713 /* Not quite sure this is needed -pd */
8714 if (f
&& FRAME_XIC (f
))
8715 XSetICFocus (FRAME_XIC (f
));
8717 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8718 instructs the WM to set the input focus automatically for
8719 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8720 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8721 it has set the focus. So, XSetInputFocus below is not
8724 The call to XSetInputFocus below has also caused trouble. In
8725 cases where the XSetInputFocus done by the WM and the one
8726 below are temporally close (on a fast machine), the call
8727 below can generate additional FocusIn events which confuse
8730 /* Since we set WM_TAKE_FOCUS, we must call
8731 XSetInputFocus explicitly. But not if f is null,
8732 since that might be an event for a deleted frame. */
8735 Display
*d
= event
.xclient
.display
;
8736 /* Catch and ignore errors, in case window has been
8737 iconified by a window manager such as GWM. */
8738 int count
= x_catch_errors (d
);
8739 XSetInputFocus (d
, event
.xclient
.window
,
8740 /* The ICCCM says this is
8741 the only valid choice. */
8743 event
.xclient
.data
.l
[1]);
8744 /* This is needed to detect the error
8745 if there is an error. */
8747 x_uncatch_errors (d
, count
);
8749 /* Not certain about handling scroll bars here */
8752 else if (event
.xclient
.data
.l
[0]
8753 == dpyinfo
->Xatom_wm_save_yourself
)
8755 /* Save state modify the WM_COMMAND property to
8756 something which can reinstate us. This notifies
8757 the session manager, who's looking for such a
8758 PropertyNotify. Can restart processing when
8759 a keyboard or mouse event arrives. */
8762 f
= x_top_window_to_frame (dpyinfo
,
8763 event
.xclient
.window
);
8765 /* This is just so we only give real data once
8766 for a single Emacs process. */
8767 if (f
== SELECTED_FRAME ())
8768 XSetCommand (FRAME_X_DISPLAY (f
),
8769 event
.xclient
.window
,
8770 initial_argv
, initial_argc
);
8772 XSetCommand (FRAME_X_DISPLAY (f
),
8773 event
.xclient
.window
,
8777 else if (event
.xclient
.data
.l
[0]
8778 == dpyinfo
->Xatom_wm_delete_window
)
8781 = x_any_window_to_frame (dpyinfo
,
8782 event
.xclient
.window
);
8789 bufp
->kind
= delete_window_event
;
8790 XSETFRAME (bufp
->frame_or_window
, f
);
8798 else if (event
.xclient
.message_type
8799 == dpyinfo
->Xatom_wm_configure_denied
)
8802 else if (event
.xclient
.message_type
8803 == dpyinfo
->Xatom_wm_window_moved
)
8807 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
8809 new_x
= event
.xclient
.data
.s
[0];
8810 new_y
= event
.xclient
.data
.s
[1];
8814 f
->output_data
.x
->left_pos
= new_x
;
8815 f
->output_data
.x
->top_pos
= new_y
;
8819 else if (event
.xclient
.message_type
8820 == dpyinfo
->Xatom_editres
)
8823 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8824 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
8827 #endif /* HACK_EDITRES */
8828 else if ((event
.xclient
.message_type
8829 == dpyinfo
->Xatom_DONE
)
8830 || (event
.xclient
.message_type
8831 == dpyinfo
->Xatom_PAGE
))
8833 /* Ghostview job completed. Kill it. We could
8834 reply with "Next" if we received "Page", but we
8835 currently never do because we are interested in
8836 images, only, which should have 1 page. */
8837 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
8839 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
8840 x_kill_gs_process (pixmap
, f
);
8841 expose_frame (f
, 0, 0, 0, 0);
8843 #ifdef USE_TOOLKIT_SCROLL_BARS
8844 /* Scroll bar callbacks send a ClientMessage from which
8845 we construct an input_event. */
8846 else if (event
.xclient
.message_type
8847 == dpyinfo
->Xatom_Scrollbar
)
8849 if (display_busy_cursor_p
)
8850 inhibit_busy_cursor
= 2;
8851 x_scroll_bar_to_input_event (&event
, bufp
);
8852 ++bufp
, ++count
, --numchars
;
8855 #endif /* USE_TOOLKIT_SCROLL_BARS */
8861 case SelectionNotify
:
8862 #ifdef USE_X_TOOLKIT
8863 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
8865 #endif /* not USE_X_TOOLKIT */
8866 x_handle_selection_notify (&event
.xselection
);
8869 case SelectionClear
: /* Someone has grabbed ownership. */
8870 #ifdef USE_X_TOOLKIT
8871 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
8873 #endif /* USE_X_TOOLKIT */
8875 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
8880 bufp
->kind
= selection_clear_event
;
8881 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
8882 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
8883 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
8884 bufp
->frame_or_window
= Qnil
;
8892 case SelectionRequest
: /* Someone wants our selection. */
8893 #ifdef USE_X_TOOLKIT
8894 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
8896 #endif /* USE_X_TOOLKIT */
8897 if (x_queue_selection_requests
)
8898 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
8902 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
8907 bufp
->kind
= selection_request_event
;
8908 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
8909 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
8910 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
8911 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
8912 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
8913 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
8914 bufp
->frame_or_window
= Qnil
;
8922 case PropertyNotify
:
8923 #ifdef USE_X_TOOLKIT
8924 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
8926 #endif /* not USE_X_TOOLKIT */
8927 x_handle_property_notify (&event
.xproperty
);
8930 case ReparentNotify
:
8931 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
8935 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
8936 x_real_positions (f
, &x
, &y
);
8937 f
->output_data
.x
->left_pos
= x
;
8938 f
->output_data
.x
->top_pos
= y
;
8943 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8946 if (f
->async_visible
== 0)
8948 f
->async_visible
= 1;
8949 f
->async_iconified
= 0;
8950 f
->output_data
.x
->has_been_visible
= 1;
8951 SET_FRAME_GARBAGED (f
);
8954 expose_frame (x_window_to_frame (dpyinfo
,
8955 event
.xexpose
.window
),
8956 event
.xexpose
.x
, event
.xexpose
.y
,
8957 event
.xexpose
.width
, event
.xexpose
.height
);
8961 #ifdef USE_TOOLKIT_SCROLL_BARS
8962 /* Dispatch event to the widget. */
8964 #else /* not USE_TOOLKIT_SCROLL_BARS */
8965 struct scroll_bar
*bar
8966 = x_window_to_scroll_bar (event
.xexpose
.window
);
8969 x_scroll_bar_expose (bar
, &event
);
8970 #ifdef USE_X_TOOLKIT
8973 #endif /* USE_X_TOOLKIT */
8974 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8978 case GraphicsExpose
: /* This occurs when an XCopyArea's
8979 source area was obscured or not
8981 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
8985 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
8986 event
.xgraphicsexpose
.width
,
8987 event
.xgraphicsexpose
.height
);
8989 #ifdef USE_X_TOOLKIT
8992 #endif /* USE_X_TOOLKIT */
8995 case NoExpose
: /* This occurs when an XCopyArea's
8996 source area was completely
9001 /* Redo the mouse-highlight after the tooltip has gone. */
9002 if (event
.xmap
.window
== tip_window
)
9005 redo_mouse_highlight ();
9008 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
9009 if (f
) /* F may no longer exist if
9010 the frame was deleted. */
9012 /* While a frame is unmapped, display generation is
9013 disabled; you don't want to spend time updating a
9014 display that won't ever be seen. */
9015 f
->async_visible
= 0;
9016 /* We can't distinguish, from the event, whether the window
9017 has become iconified or invisible. So assume, if it
9018 was previously visible, than now it is iconified.
9019 But x_make_frame_invisible clears both
9020 the visible flag and the iconified flag;
9021 and that way, we know the window is not iconified now. */
9022 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
9024 f
->async_iconified
= 1;
9026 bufp
->kind
= iconify_event
;
9027 XSETFRAME (bufp
->frame_or_window
, f
);
9036 if (event
.xmap
.window
== tip_window
)
9037 /* The tooltip has been drawn already. Avoid
9038 the SET_FRAME_GARBAGED below. */
9041 /* We use x_top_window_to_frame because map events can
9042 come for sub-windows and they don't mean that the
9043 frame is visible. */
9044 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
9047 f
->async_visible
= 1;
9048 f
->async_iconified
= 0;
9049 f
->output_data
.x
->has_been_visible
= 1;
9051 /* wait_reading_process_input will notice this and update
9052 the frame's display structures. */
9053 SET_FRAME_GARBAGED (f
);
9057 bufp
->kind
= deiconify_event
;
9058 XSETFRAME (bufp
->frame_or_window
, f
);
9063 else if (! NILP (Vframe_list
)
9064 && ! NILP (XCDR (Vframe_list
)))
9065 /* Force a redisplay sooner or later
9066 to update the frame titles
9067 in case this is the second frame. */
9068 record_asynch_buffer_change ();
9073 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
9076 /* I couldn't find a way to prevent LessTif scroll bars
9077 from consuming key events. */
9080 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
9082 if (widget
&& XmIsScrollBar (widget
))
9084 widget
= XtParent (widget
);
9085 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
9088 #endif /* USE_MOTIF */
9092 KeySym keysym
, orig_keysym
;
9093 /* al%imercury@uunet.uu.net says that making this 81 instead of
9094 80 fixed a bug whereby meta chars made his Emacs hang. */
9095 unsigned char copy_buffer
[81];
9099 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
9100 extra_keyboard_modifiers
);
9101 modifiers
= event
.xkey
.state
;
9103 /* This will have to go some day... */
9105 /* make_lispy_event turns chars into control chars.
9106 Don't do it here because XLookupString is too eager. */
9107 event
.xkey
.state
&= ~ControlMask
;
9108 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
9109 | dpyinfo
->super_mod_mask
9110 | dpyinfo
->hyper_mod_mask
9111 | dpyinfo
->alt_mod_mask
);
9113 /* In case Meta is ComposeCharacter,
9114 clear its status. According to Markus Ehrnsperger
9115 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9116 this enables ComposeCharacter to work whether or
9117 not it is combined with Meta. */
9118 if (modifiers
& dpyinfo
->meta_mod_mask
)
9119 bzero (&compose_status
, sizeof (compose_status
));
9124 /* The necessity of the following line took me
9125 a full work-day to decipher from the docs!! */
9126 if (XFilterEvent (&event
, None
))
9128 nbytes
= XmbLookupString (FRAME_XIC (f
),
9129 &event
.xkey
, copy_buffer
,
9132 if (status_return
== XLookupNone
)
9134 else if (status_return
== XLookupChars
)
9136 else if (status_return
!= XLookupKeySym
9137 && status_return
!= XLookupBoth
)
9141 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9142 80, &keysym
, &compose_status
);
9144 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9145 80, &keysym
, &compose_status
);
9148 orig_keysym
= keysym
;
9152 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
9153 || keysym
== XK_Delete
9154 #ifdef XK_ISO_Left_Tab
9155 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
9157 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
9158 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
9159 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
9161 /* This recognizes the "extended function keys".
9162 It seems there's no cleaner way.
9163 Test IsModifierKey to avoid handling mode_switch
9165 || ((unsigned) (keysym
) >= XK_Select
9166 && (unsigned)(keysym
) < XK_KP_Space
)
9168 #ifdef XK_dead_circumflex
9169 || orig_keysym
== XK_dead_circumflex
9171 #ifdef XK_dead_grave
9172 || orig_keysym
== XK_dead_grave
9174 #ifdef XK_dead_tilde
9175 || orig_keysym
== XK_dead_tilde
9177 #ifdef XK_dead_diaeresis
9178 || orig_keysym
== XK_dead_diaeresis
9180 #ifdef XK_dead_macron
9181 || orig_keysym
== XK_dead_macron
9183 #ifdef XK_dead_degree
9184 || orig_keysym
== XK_dead_degree
9186 #ifdef XK_dead_acute
9187 || orig_keysym
== XK_dead_acute
9189 #ifdef XK_dead_cedilla
9190 || orig_keysym
== XK_dead_cedilla
9192 #ifdef XK_dead_breve
9193 || orig_keysym
== XK_dead_breve
9195 #ifdef XK_dead_ogonek
9196 || orig_keysym
== XK_dead_ogonek
9198 #ifdef XK_dead_caron
9199 || orig_keysym
== XK_dead_caron
9201 #ifdef XK_dead_doubleacute
9202 || orig_keysym
== XK_dead_doubleacute
9204 #ifdef XK_dead_abovedot
9205 || orig_keysym
== XK_dead_abovedot
9207 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
9208 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
9209 /* Any "vendor-specific" key is ok. */
9210 || (orig_keysym
& (1 << 28)))
9211 && ! (IsModifierKey (orig_keysym
)
9213 #ifdef XK_Mode_switch
9214 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
9217 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
9219 #endif /* not HAVE_X11R5 */
9222 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9224 temp_buffer
[temp_index
++] = keysym
;
9225 bufp
->kind
= non_ascii_keystroke
;
9226 bufp
->code
= keysym
;
9227 XSETFRAME (bufp
->frame_or_window
, f
);
9229 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9231 bufp
->timestamp
= event
.xkey
.time
;
9236 if (display_busy_cursor_p
)
9237 if (keysym
!= XK_Return
|| minibuf_level
== 0)
9238 inhibit_busy_cursor
= 2;
9240 else if (numchars
> nbytes
)
9244 for (i
= 0; i
< nbytes
; i
++)
9246 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9248 temp_buffer
[temp_index
++] = copy_buffer
[i
];
9249 bufp
->kind
= ascii_keystroke
;
9250 bufp
->code
= copy_buffer
[i
];
9251 XSETFRAME (bufp
->frame_or_window
, f
);
9253 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9255 bufp
->timestamp
= event
.xkey
.time
;
9262 if (keysym
== NoSymbol
)
9273 /* Here's a possible interpretation of the whole
9274 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9275 you get a FocusIn event, you have to get a FocusOut
9276 event before you relinquish the focus. If you
9277 haven't received a FocusIn event, then a mere
9278 LeaveNotify is enough to free you. */
9282 int from_menu_bar_p
= 0;
9284 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9286 #ifdef LESSTIF_VERSION
9287 /* When clicking outside of a menu bar popup to close
9288 it, we get a FocusIn/ EnterNotify sequence of
9289 events. The flag event.xcrossing.focus is not set
9290 in the EnterNotify event of that sequence because
9291 the focus is in the menu bar,
9292 event.xcrossing.window is the frame's X window.
9293 Unconditionally setting the focus frame to null in
9294 this case is not the right thing, because no event
9295 follows that could set the focus frame to the right
9298 This could be a LessTif bug, but I wasn't able to
9299 reproduce the behavior in a simple test program.
9301 (gerd, LessTif 0.88.1). */
9303 if (!event
.xcrossing
.focus
9305 && f
->output_data
.x
->menubar_widget
)
9310 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9311 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9312 from_menu_bar_p
= 1;
9314 #endif /* LESSTIF_VERSION */
9316 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9318 /* Avoid nasty pop/raise loops. */
9319 if (f
&& (!(f
->auto_raise
)
9321 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
9323 x_new_focus_frame (dpyinfo
, f
);
9324 enter_timestamp
= event
.xcrossing
.time
;
9327 else if (f
== dpyinfo
->x_focus_frame
)
9328 x_new_focus_frame (dpyinfo
, 0);
9330 /* EnterNotify counts as mouse movement,
9331 so update things that depend on mouse position. */
9332 if (f
&& !f
->output_data
.x
->busy_p
)
9333 note_mouse_movement (f
, &event
.xmotion
);
9338 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9339 if (event
.xfocus
.detail
!= NotifyPointer
)
9340 dpyinfo
->x_focus_event_frame
= f
;
9342 x_new_focus_frame (dpyinfo
, f
);
9345 if (f
&& FRAME_XIC (f
))
9346 XSetICFocus (FRAME_XIC (f
));
9352 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9356 int from_menu_bar_p
= 0;
9358 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9360 /* If we move outside the frame, then we're
9361 certainly no longer on any text in the frame. */
9362 clear_mouse_face (dpyinfo
);
9363 dpyinfo
->mouse_face_mouse_frame
= 0;
9366 /* Generate a nil HELP_EVENT to cancel a help-echo.
9367 Do it only if there's something to cancel.
9368 Otherwise, the startup message is cleared when
9369 the mouse leaves the frame. */
9370 if (any_help_event_p
)
9372 XSETFRAME (frame
, f
);
9373 bufp
->kind
= HELP_EVENT
;
9374 bufp
->frame_or_window
= Fcons (frame
, Qnil
);
9375 ++bufp
, ++count
, --numchars
;
9378 #ifdef LESSTIF_VERSION
9379 /* Please see the comment at the start of the
9380 EnterNotify case. */
9381 if (!event
.xcrossing
.focus
9382 && f
->output_data
.x
->menubar_widget
)
9386 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9387 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9388 from_menu_bar_p
= 1;
9390 #endif /* LESSTIF_VERSION */
9392 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9393 x_mouse_leave (dpyinfo
);
9396 if (f
== dpyinfo
->x_focus_event_frame
)
9397 dpyinfo
->x_focus_event_frame
= 0;
9398 if (f
== dpyinfo
->x_focus_frame
)
9399 x_new_focus_frame (dpyinfo
, 0);
9405 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9406 if (event
.xfocus
.detail
!= NotifyPointer
9407 && f
== dpyinfo
->x_focus_event_frame
)
9408 dpyinfo
->x_focus_event_frame
= 0;
9409 if (f
&& f
== dpyinfo
->x_focus_frame
)
9410 x_new_focus_frame (dpyinfo
, 0);
9413 if (f
&& FRAME_XIC (f
))
9414 XUnsetICFocus (FRAME_XIC (f
));
9421 previous_help_echo
= help_echo
;
9424 if (dpyinfo
->grabbed
&& last_mouse_frame
9425 && FRAME_LIVE_P (last_mouse_frame
))
9426 f
= last_mouse_frame
;
9428 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
9431 note_mouse_movement (f
, &event
.xmotion
);
9434 #ifndef USE_TOOLKIT_SCROLL_BARS
9435 struct scroll_bar
*bar
9436 = x_window_to_scroll_bar (event
.xmotion
.window
);
9439 x_scroll_bar_note_movement (bar
, &event
);
9440 #endif /* USE_TOOLKIT_SCROLL_BARS */
9442 /* If we move outside the frame, then we're
9443 certainly no longer on any text in the frame. */
9444 clear_mouse_face (dpyinfo
);
9447 /* If the contents of the global variable help_echo
9448 has changed, generate a HELP_EVENT. */
9449 if (STRINGP (help_echo
)
9450 || STRINGP (previous_help_echo
))
9455 XSETFRAME (frame
, f
);
9459 any_help_event_p
= 1;
9460 bufp
->kind
= HELP_EVENT
;
9461 bufp
->frame_or_window
= Fcons (frame
, help_echo
);
9462 ++bufp
, ++count
, --numchars
;
9468 case ConfigureNotify
:
9469 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
9472 #ifndef USE_X_TOOLKIT
9473 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
9474 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
9476 /* In the toolkit version, change_frame_size
9477 is called by the code that handles resizing
9478 of the EmacsFrame widget. */
9480 /* Even if the number of character rows and columns has
9481 not changed, the font size may have changed, so we need
9482 to check the pixel dimensions as well. */
9483 if (columns
!= f
->width
9484 || rows
!= f
->height
9485 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
9486 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
9488 change_frame_size (f
, rows
, columns
, 0, 1, 0);
9489 SET_FRAME_GARBAGED (f
);
9490 cancel_mouse_face (f
);
9494 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
9495 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
9497 /* What we have now is the position of Emacs's own window.
9498 Convert that to the position of the window manager window. */
9499 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
9500 &f
->output_data
.x
->top_pos
);
9502 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
9504 /* Since the WM decorations come below top_pos now,
9505 we must put them below top_pos in the future. */
9506 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9507 x_wm_set_size_hint (f
, (long) 0, 0);
9510 /* Some window managers pass (0,0) as the location of
9511 the window, and the Motif event handler stores it
9512 in the emacs widget, which messes up Motif menus. */
9513 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
9515 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
9516 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
9518 #endif /* USE_MOTIF */
9525 /* If we decide we want to generate an event to be seen
9526 by the rest of Emacs, we put it here. */
9527 struct input_event emacs_event
;
9530 emacs_event
.kind
= no_event
;
9531 bzero (&compose_status
, sizeof (compose_status
));
9533 if (dpyinfo
->grabbed
9535 && FRAME_LIVE_P (last_mouse_frame
))
9536 f
= last_mouse_frame
;
9538 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9542 /* Is this in the tool-bar? */
9543 if (WINDOWP (f
->tool_bar_window
)
9544 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
9549 x
= event
.xbutton
.x
;
9550 y
= event
.xbutton
.y
;
9553 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
9554 if (EQ (window
, f
->tool_bar_window
))
9556 x_handle_tool_bar_click (f
, &event
.xbutton
);
9562 if (!dpyinfo
->x_focus_frame
9563 || f
== dpyinfo
->x_focus_frame
)
9564 construct_mouse_click (&emacs_event
, &event
, f
);
9568 #ifndef USE_TOOLKIT_SCROLL_BARS
9569 struct scroll_bar
*bar
9570 = x_window_to_scroll_bar (event
.xbutton
.window
);
9573 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
9574 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9577 if (event
.type
== ButtonPress
)
9579 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
9580 last_mouse_frame
= f
;
9581 /* Ignore any mouse motion that happened
9582 before this event; any subsequent mouse-movement
9583 Emacs events should reflect only motion after
9589 last_tool_bar_item
= -1;
9590 if (display_busy_cursor_p
)
9591 inhibit_busy_cursor
= 2;
9595 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
9598 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
9600 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
9606 #ifdef USE_X_TOOLKIT
9607 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9608 /* For a down-event in the menu bar,
9609 don't pass it to Xt right now.
9610 Instead, save it away
9611 and we will pass it to Xt from kbd_buffer_get_event.
9612 That way, we can run some Lisp code first. */
9613 if (f
&& event
.type
== ButtonPress
9614 /* Verify the event is really within the menu bar
9615 and not just sent to it due to grabbing. */
9616 && event
.xbutton
.x
>= 0
9617 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
9618 && event
.xbutton
.y
>= 0
9619 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
9620 && event
.xbutton
.same_screen
)
9622 SET_SAVED_BUTTON_EVENT
;
9623 XSETFRAME (last_mouse_press_frame
, f
);
9625 else if (event
.type
== ButtonPress
)
9627 last_mouse_press_frame
= Qnil
;
9631 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9632 but I am trying to be cautious. */
9633 else if (event
.type
== ButtonRelease
)
9635 if (!NILP (last_mouse_press_frame
))
9637 f
= XFRAME (last_mouse_press_frame
);
9638 if (f
->output_data
.x
)
9639 SET_SAVED_BUTTON_EVENT
;
9644 #endif /* USE_MOTIF */
9647 #endif /* USE_X_TOOLKIT */
9651 case CirculateNotify
:
9654 case CirculateRequest
:
9657 case VisibilityNotify
:
9661 /* Someone has changed the keyboard mapping - update the
9663 switch (event
.xmapping
.request
)
9665 case MappingModifier
:
9666 x_find_modifier_meanings (dpyinfo
);
9667 /* This is meant to fall through. */
9668 case MappingKeyboard
:
9669 XRefreshKeyboardMapping (&event
.xmapping
);
9675 #ifdef USE_X_TOOLKIT
9677 XtDispatchEvent (&event
);
9679 #endif /* USE_X_TOOLKIT */
9687 /* On some systems, an X bug causes Emacs to get no more events
9688 when the window is destroyed. Detect that. (1994.) */
9691 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9692 One XNOOP in 100 loops will make Emacs terminate.
9693 B. Bretthauer, 1994 */
9695 if (x_noop_count
>= 100)
9699 if (next_noop_dpyinfo
== 0)
9700 next_noop_dpyinfo
= x_display_list
;
9702 XNoOp (next_noop_dpyinfo
->display
);
9704 /* Each time we get here, cycle through the displays now open. */
9705 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
9709 /* If the focus was just given to an auto-raising frame,
9711 /* ??? This ought to be able to handle more than one such frame. */
9712 if (pending_autoraise_frame
)
9714 x_raise_frame (pending_autoraise_frame
);
9715 pending_autoraise_frame
= 0;
9725 /***********************************************************************
9727 ***********************************************************************/
9729 /* Note if the text cursor of window W has been overwritten by a
9730 drawing operation that outputs N glyphs starting at HPOS in the
9731 line given by output_cursor.vpos. N < 0 means all the rest of the
9732 line after HPOS has been written. */
9735 note_overwritten_text_cursor (w
, hpos
, n
)
9739 if (updated_area
== TEXT_AREA
9740 && output_cursor
.vpos
== w
->phys_cursor
.vpos
9741 && hpos
<= w
->phys_cursor
.hpos
9743 || hpos
+ n
> w
->phys_cursor
.hpos
))
9744 w
->phys_cursor_on_p
= 0;
9748 /* Set clipping for output in glyph row ROW. W is the window in which
9749 we operate. GC is the graphics context to set clipping in.
9750 WHOLE_LINE_P non-zero means include the areas used for truncation
9751 mark display and alike in the clipping rectangle.
9753 ROW may be a text row or, e.g., a mode line. Text rows must be
9754 clipped to the interior of the window dedicated to text display,
9755 mode lines must be clipped to the whole window. */
9758 x_clip_to_row (w
, row
, gc
, whole_line_p
)
9760 struct glyph_row
*row
;
9764 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9765 XRectangle clip_rect
;
9766 int window_x
, window_y
, window_width
, window_height
;
9768 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
9770 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
9771 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
9772 clip_rect
.y
= max (clip_rect
.y
, window_y
);
9773 clip_rect
.width
= window_width
;
9774 clip_rect
.height
= row
->visible_height
;
9776 /* If clipping to the whole line, including trunc marks, extend
9777 the rectangle to the left and increase its width. */
9780 clip_rect
.x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
9781 clip_rect
.width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
9784 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
9788 /* Draw a hollow box cursor on window W in glyph row ROW. */
9791 x_draw_hollow_cursor (w
, row
)
9793 struct glyph_row
*row
;
9795 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9796 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9797 Display
*dpy
= FRAME_X_DISPLAY (f
);
9800 struct glyph
*cursor_glyph
;
9803 /* Compute frame-relative coordinates from window-relative
9805 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9806 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
9807 + row
->ascent
- w
->phys_cursor_ascent
);
9808 h
= row
->height
- 1;
9810 /* Get the glyph the cursor is on. If we can't tell because
9811 the current matrix is invalid or such, give up. */
9812 cursor_glyph
= get_phys_cursor_glyph (w
);
9813 if (cursor_glyph
== NULL
)
9816 /* Compute the width of the rectangle to draw. If on a stretch
9817 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9818 rectangle as wide as the glyph, but use a canonical character
9820 wd
= cursor_glyph
->pixel_width
- 1;
9821 if (cursor_glyph
->type
== STRETCH_GLYPH
9822 && !x_stretch_cursor_p
)
9823 wd
= min (CANON_X_UNIT (f
), wd
);
9825 /* The foreground of cursor_gc is typically the same as the normal
9826 background color, which can cause the cursor box to be invisible. */
9827 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
9828 if (dpyinfo
->scratch_cursor_gc
)
9829 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
9831 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
9832 GCForeground
, &xgcv
);
9833 gc
= dpyinfo
->scratch_cursor_gc
;
9835 /* Set clipping, draw the rectangle, and reset clipping again. */
9836 x_clip_to_row (w
, row
, gc
, 0);
9837 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
9838 XSetClipMask (dpy
, gc
, None
);
9842 /* Draw a bar cursor on window W in glyph row ROW.
9844 Implementation note: One would like to draw a bar cursor with an
9845 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9846 Unfortunately, I didn't find a font yet that has this property set.
9850 x_draw_bar_cursor (w
, row
)
9852 struct glyph_row
*row
;
9854 /* If cursor hpos is out of bounds, don't draw garbage. This can
9855 happen in mini-buffer windows when switching between echo area
9856 glyphs and mini-buffer. */
9857 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9859 struct frame
*f
= XFRAME (w
->frame
);
9860 struct glyph
*cursor_glyph
;
9868 cursor_glyph
= get_phys_cursor_glyph (w
);
9869 if (cursor_glyph
== NULL
)
9872 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
9873 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
9874 xgcv
.graphics_exposures
= 0;
9875 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
9876 dpy
= FRAME_X_DISPLAY (f
);
9877 window
= FRAME_X_WINDOW (f
);
9878 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
9881 XChangeGC (dpy
, gc
, mask
, &xgcv
);
9884 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
9885 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
9888 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
9889 x_clip_to_row (w
, row
, gc
, 0);
9890 XFillRectangle (dpy
, window
, gc
,
9892 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
9893 min (cursor_glyph
->pixel_width
,
9894 f
->output_data
.x
->cursor_width
),
9896 XSetClipMask (dpy
, gc
, None
);
9901 /* Clear the cursor of window W to background color, and mark the
9902 cursor as not shown. This is used when the text where the cursor
9903 is is about to be rewritten. */
9909 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
9910 x_update_window_cursor (w
, 0);
9914 /* Draw the cursor glyph of window W in glyph row ROW. See the
9915 comment of x_draw_glyphs for the meaning of HL. */
9918 x_draw_phys_cursor_glyph (w
, row
, hl
)
9920 struct glyph_row
*row
;
9921 enum draw_glyphs_face hl
;
9923 /* If cursor hpos is out of bounds, don't draw garbage. This can
9924 happen in mini-buffer windows when switching between echo area
9925 glyphs and mini-buffer. */
9926 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
9928 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
9929 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
9932 /* When we erase the cursor, and ROW is overlapped by other
9933 rows, make sure that these overlapping parts of other rows
9935 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
9937 if (row
> w
->current_matrix
->rows
9938 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
9939 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
9941 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
9942 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
9943 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
9949 /* Erase the image of a cursor of window W from the screen. */
9952 x_erase_phys_cursor (w
)
9955 struct frame
*f
= XFRAME (w
->frame
);
9956 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9957 int hpos
= w
->phys_cursor
.hpos
;
9958 int vpos
= w
->phys_cursor
.vpos
;
9959 int mouse_face_here_p
= 0;
9960 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
9961 struct glyph_row
*cursor_row
;
9962 struct glyph
*cursor_glyph
;
9963 enum draw_glyphs_face hl
;
9965 /* No cursor displayed or row invalidated => nothing to do on the
9967 if (w
->phys_cursor_type
== NO_CURSOR
)
9968 goto mark_cursor_off
;
9970 /* VPOS >= active_glyphs->nrows means that window has been resized.
9971 Don't bother to erase the cursor. */
9972 if (vpos
>= active_glyphs
->nrows
)
9973 goto mark_cursor_off
;
9975 /* If row containing cursor is marked invalid, there is nothing we
9977 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
9978 if (!cursor_row
->enabled_p
)
9979 goto mark_cursor_off
;
9981 /* This can happen when the new row is shorter than the old one.
9982 In this case, either x_draw_glyphs or clear_end_of_line
9983 should have cleared the cursor. Note that we wouldn't be
9984 able to erase the cursor in this case because we don't have a
9985 cursor glyph at hand. */
9986 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
9987 goto mark_cursor_off
;
9989 /* If the cursor is in the mouse face area, redisplay that when
9990 we clear the cursor. */
9991 if (w
== XWINDOW (dpyinfo
->mouse_face_window
)
9992 && (vpos
> dpyinfo
->mouse_face_beg_row
9993 || (vpos
== dpyinfo
->mouse_face_beg_row
9994 && hpos
>= dpyinfo
->mouse_face_beg_col
))
9995 && (vpos
< dpyinfo
->mouse_face_end_row
9996 || (vpos
== dpyinfo
->mouse_face_end_row
9997 && hpos
< dpyinfo
->mouse_face_end_col
))
9998 /* Don't redraw the cursor's spot in mouse face if it is at the
9999 end of a line (on a newline). The cursor appears there, but
10000 mouse highlighting does not. */
10001 && cursor_row
->used
[TEXT_AREA
] > hpos
)
10002 mouse_face_here_p
= 1;
10004 /* Maybe clear the display under the cursor. */
10005 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
10008 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
10010 cursor_glyph
= get_phys_cursor_glyph (w
);
10011 if (cursor_glyph
== NULL
)
10012 goto mark_cursor_off
;
10014 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
10016 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10018 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
10020 cursor_glyph
->pixel_width
,
10021 cursor_row
->visible_height
,
10025 /* Erase the cursor by redrawing the character underneath it. */
10026 if (mouse_face_here_p
)
10027 hl
= DRAW_MOUSE_FACE
;
10028 else if (cursor_row
->inverse_p
)
10029 hl
= DRAW_INVERSE_VIDEO
;
10031 hl
= DRAW_NORMAL_TEXT
;
10032 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
10035 w
->phys_cursor_on_p
= 0;
10036 w
->phys_cursor_type
= NO_CURSOR
;
10040 /* Display or clear cursor of window W. If ON is zero, clear the
10041 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10042 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10045 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
10047 int on
, hpos
, vpos
, x
, y
;
10049 struct frame
*f
= XFRAME (w
->frame
);
10050 int new_cursor_type
;
10051 struct glyph_matrix
*current_glyphs
;
10052 struct glyph_row
*glyph_row
;
10053 struct glyph
*glyph
;
10055 /* This is pointless on invisible frames, and dangerous on garbaged
10056 windows and frames; in the latter case, the frame or window may
10057 be in the midst of changing its size, and x and y may be off the
10059 if (! FRAME_VISIBLE_P (f
)
10060 || FRAME_GARBAGED_P (f
)
10061 || vpos
>= w
->current_matrix
->nrows
10062 || hpos
>= w
->current_matrix
->matrix_w
)
10065 /* If cursor is off and we want it off, return quickly. */
10066 if (!on
&& !w
->phys_cursor_on_p
)
10069 current_glyphs
= w
->current_matrix
;
10070 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
10071 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
10073 /* If cursor row is not enabled, we don't really know where to
10074 display the cursor. */
10075 if (!glyph_row
->enabled_p
)
10077 w
->phys_cursor_on_p
= 0;
10081 xassert (interrupt_input_blocked
);
10083 /* Set new_cursor_type to the cursor we want to be displayed. In a
10084 mini-buffer window, we want the cursor only to appear if we are
10085 reading input from this window. For the selected window, we want
10086 the cursor type given by the frame parameter. If explicitly
10087 marked off, draw no cursor. In all other cases, we want a hollow
10089 if (cursor_in_echo_area
10090 && FRAME_HAS_MINIBUF_P (f
)
10091 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
10093 if (w
== XWINDOW (echo_area_window
))
10094 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10096 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10100 if (w
!= XWINDOW (selected_window
)
10101 || f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
10103 if (MINI_WINDOW_P (w
))
10104 new_cursor_type
= NO_CURSOR
;
10106 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10108 else if (w
->cursor_off_p
)
10109 new_cursor_type
= NO_CURSOR
;
10111 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10114 /* If cursor is currently being shown and we don't want it to be or
10115 it is in the wrong place, or the cursor type is not what we want,
10117 if (w
->phys_cursor_on_p
10119 || w
->phys_cursor
.x
!= x
10120 || w
->phys_cursor
.y
!= y
10121 || new_cursor_type
!= w
->phys_cursor_type
))
10122 x_erase_phys_cursor (w
);
10124 /* If the cursor is now invisible and we want it to be visible,
10126 if (on
&& !w
->phys_cursor_on_p
)
10128 w
->phys_cursor_ascent
= glyph_row
->ascent
;
10129 w
->phys_cursor_height
= glyph_row
->height
;
10131 /* Set phys_cursor_.* before x_draw_.* is called because some
10132 of them may need the information. */
10133 w
->phys_cursor
.x
= x
;
10134 w
->phys_cursor
.y
= glyph_row
->y
;
10135 w
->phys_cursor
.hpos
= hpos
;
10136 w
->phys_cursor
.vpos
= vpos
;
10137 w
->phys_cursor_type
= new_cursor_type
;
10138 w
->phys_cursor_on_p
= 1;
10140 switch (new_cursor_type
)
10142 case HOLLOW_BOX_CURSOR
:
10143 x_draw_hollow_cursor (w
, glyph_row
);
10146 case FILLED_BOX_CURSOR
:
10147 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
10151 x_draw_bar_cursor (w
, glyph_row
);
10163 if (updating_frame
!= f
)
10164 XFlush (FRAME_X_DISPLAY (f
));
10169 /* Display the cursor on window W, or clear it. X and Y are window
10170 relative pixel coordinates. HPOS and VPOS are glyph matrix
10171 positions. If W is not the selected window, display a hollow
10172 cursor. ON non-zero means display the cursor at X, Y which
10173 correspond to HPOS, VPOS, otherwise it is cleared. */
10176 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
10178 int on
, hpos
, vpos
, x
, y
;
10181 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
10186 /* Display the cursor on window W, or clear it, according to ON_P.
10187 Don't change the cursor's position. */
10190 x_update_cursor (f
, on_p
)
10193 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
10197 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10198 in the window tree rooted at W. */
10201 x_update_cursor_in_window_tree (w
, on_p
)
10207 if (!NILP (w
->hchild
))
10208 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
10209 else if (!NILP (w
->vchild
))
10210 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
10212 x_update_window_cursor (w
, on_p
);
10214 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
10219 /* Switch the display of W's cursor on or off, according to the value
10223 x_update_window_cursor (w
, on
)
10228 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
10229 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
10238 /* Refresh bitmap kitchen sink icon for frame F
10239 when we get an expose event for it. */
10245 /* Normally, the window manager handles this function. */
10248 /* Make the x-window of frame F use the gnu icon bitmap. */
10251 x_bitmap_icon (f
, file
)
10257 if (FRAME_X_WINDOW (f
) == 0)
10260 /* Free up our existing icon bitmap if any. */
10261 if (f
->output_data
.x
->icon_bitmap
> 0)
10262 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10263 f
->output_data
.x
->icon_bitmap
= 0;
10265 if (STRINGP (file
))
10266 bitmap_id
= x_create_bitmap_from_file (f
, file
);
10269 /* Create the GNU bitmap if necessary. */
10270 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
10271 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
10272 = x_create_bitmap_from_data (f
, gnu_bits
,
10273 gnu_width
, gnu_height
);
10275 /* The first time we create the GNU bitmap,
10276 this increments the ref-count one extra time.
10277 As a result, the GNU bitmap is never freed.
10278 That way, we don't have to worry about allocating it again. */
10279 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
10281 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
10284 x_wm_set_icon_pixmap (f
, bitmap_id
);
10285 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
10291 /* Make the x-window of frame F use a rectangle with text.
10292 Use ICON_NAME as the text. */
10295 x_text_icon (f
, icon_name
)
10299 if (FRAME_X_WINDOW (f
) == 0)
10304 XTextProperty text
;
10305 text
.value
= (unsigned char *) icon_name
;
10306 text
.encoding
= XA_STRING
;
10308 text
.nitems
= strlen (icon_name
);
10309 #ifdef USE_X_TOOLKIT
10310 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10312 #else /* not USE_X_TOOLKIT */
10313 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
10314 #endif /* not USE_X_TOOLKIT */
10316 #else /* not HAVE_X11R4 */
10317 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
10318 #endif /* not HAVE_X11R4 */
10320 if (f
->output_data
.x
->icon_bitmap
> 0)
10321 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10322 f
->output_data
.x
->icon_bitmap
= 0;
10323 x_wm_set_icon_pixmap (f
, 0);
10328 #define X_ERROR_MESSAGE_SIZE 200
10330 /* If non-nil, this should be a string.
10331 It means catch X errors and store the error message in this string. */
10333 static Lisp_Object x_error_message_string
;
10335 /* An X error handler which stores the error message in
10336 x_error_message_string. This is called from x_error_handler if
10337 x_catch_errors is in effect. */
10340 x_error_catcher (display
, error
)
10342 XErrorEvent
*error
;
10344 XGetErrorText (display
, error
->error_code
,
10345 XSTRING (x_error_message_string
)->data
,
10346 X_ERROR_MESSAGE_SIZE
);
10349 /* Begin trapping X errors for display DPY. Actually we trap X errors
10350 for all displays, but DPY should be the display you are actually
10353 After calling this function, X protocol errors no longer cause
10354 Emacs to exit; instead, they are recorded in the string
10355 stored in x_error_message_string.
10357 Calling x_check_errors signals an Emacs error if an X error has
10358 occurred since the last call to x_catch_errors or x_check_errors.
10360 Calling x_uncatch_errors resumes the normal error handling. */
10362 void x_check_errors ();
10363 static Lisp_Object
x_catch_errors_unwind ();
10366 x_catch_errors (dpy
)
10369 int count
= specpdl_ptr
- specpdl
;
10371 /* Make sure any errors from previous requests have been dealt with. */
10372 XSync (dpy
, False
);
10374 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
10376 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
10377 XSTRING (x_error_message_string
)->data
[0] = 0;
10382 /* Unbind the binding that we made to check for X errors. */
10385 x_catch_errors_unwind (old_val
)
10386 Lisp_Object old_val
;
10388 x_error_message_string
= old_val
;
10392 /* If any X protocol errors have arrived since the last call to
10393 x_catch_errors or x_check_errors, signal an Emacs error using
10394 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10397 x_check_errors (dpy
, format
)
10401 /* Make sure to catch any errors incurred so far. */
10402 XSync (dpy
, False
);
10404 if (XSTRING (x_error_message_string
)->data
[0])
10405 error (format
, XSTRING (x_error_message_string
)->data
);
10408 /* Nonzero if we had any X protocol errors
10409 since we did x_catch_errors on DPY. */
10412 x_had_errors_p (dpy
)
10415 /* Make sure to catch any errors incurred so far. */
10416 XSync (dpy
, False
);
10418 return XSTRING (x_error_message_string
)->data
[0] != 0;
10421 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10424 x_clear_errors (dpy
)
10427 XSTRING (x_error_message_string
)->data
[0] = 0;
10430 /* Stop catching X protocol errors and let them make Emacs die.
10431 DPY should be the display that was passed to x_catch_errors.
10432 COUNT should be the value that was returned by
10433 the corresponding call to x_catch_errors. */
10436 x_uncatch_errors (dpy
, count
)
10440 unbind_to (count
, Qnil
);
10444 static unsigned int x_wire_count
;
10447 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
10452 /* Handle SIGPIPE, which can happen when the connection to a server
10453 simply goes away. SIGPIPE is handled by x_connection_signal.
10454 Don't need to do anything, because the write which caused the
10455 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10456 which will do the appropriate cleanup for us. */
10459 x_connection_signal (signalnum
) /* If we don't have an argument, */
10460 int signalnum
; /* some compilers complain in signal calls. */
10463 /* USG systems forget handlers when they are used;
10464 must reestablish each time */
10465 signal (signalnum
, x_connection_signal
);
10469 /* Handling X errors. */
10471 /* Handle the loss of connection to display DISPLAY. */
10474 x_connection_closed (display
, error_message
)
10476 char *error_message
;
10478 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
10479 Lisp_Object frame
, tail
;
10481 /* Indicate that this display is dead. */
10483 #ifdef USE_X_TOOLKIT
10484 XtCloseDisplay (display
);
10487 dpyinfo
->display
= 0;
10489 /* First delete frames whose mini-buffers are on frames
10490 that are on the dead display. */
10491 FOR_EACH_FRAME (tail
, frame
)
10493 Lisp_Object minibuf_frame
;
10495 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
10496 if (FRAME_X_P (XFRAME (frame
))
10497 && FRAME_X_P (XFRAME (minibuf_frame
))
10498 && ! EQ (frame
, minibuf_frame
)
10499 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
10500 Fdelete_frame (frame
, Qt
);
10503 /* Now delete all remaining frames on the dead display.
10504 We are now sure none of these is used as the mini-buffer
10505 for another frame that we need to delete. */
10506 FOR_EACH_FRAME (tail
, frame
)
10507 if (FRAME_X_P (XFRAME (frame
))
10508 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
10510 /* Set this to t so that Fdelete_frame won't get confused
10511 trying to find a replacement. */
10512 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
10513 Fdelete_frame (frame
, Qt
);
10517 x_delete_display (dpyinfo
);
10519 if (x_display_list
== 0)
10521 fprintf (stderr
, "%s\n", error_message
);
10522 shut_down_emacs (0, 0, Qnil
);
10526 /* Ordinary stack unwind doesn't deal with these. */
10528 sigunblock (sigmask (SIGIO
));
10530 sigunblock (sigmask (SIGALRM
));
10531 TOTALLY_UNBLOCK_INPUT
;
10533 clear_waiting_for_input ();
10534 error ("%s", error_message
);
10537 /* This is the usual handler for X protocol errors.
10538 It kills all frames on the display that we got the error for.
10539 If that was the only one, it prints an error message and kills Emacs. */
10542 x_error_quitter (display
, error
)
10544 XErrorEvent
*error
;
10546 char buf
[256], buf1
[356];
10548 /* Note that there is no real way portable across R3/R4 to get the
10549 original error handler. */
10551 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
10552 sprintf (buf1
, "X protocol error: %s on protocol request %d",
10553 buf
, error
->request_code
);
10554 x_connection_closed (display
, buf1
);
10557 /* This is the first-level handler for X protocol errors.
10558 It calls x_error_quitter or x_error_catcher. */
10561 x_error_handler (display
, error
)
10563 XErrorEvent
*error
;
10565 if (! NILP (x_error_message_string
))
10566 x_error_catcher (display
, error
);
10568 x_error_quitter (display
, error
);
10572 /* This is the handler for X IO errors, always.
10573 It kills all frames on the display that we lost touch with.
10574 If that was the only one, it prints an error message and kills Emacs. */
10577 x_io_error_quitter (display
)
10582 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
10583 x_connection_closed (display
, buf
);
10587 /* Changing the font of the frame. */
10589 /* Give frame F the font named FONTNAME as its default font, and
10590 return the full name of that font. FONTNAME may be a wildcard
10591 pattern; in that case, we choose some font that fits the pattern.
10592 The return value shows which font we chose. */
10595 x_new_font (f
, fontname
)
10597 register char *fontname
;
10599 struct font_info
*fontp
10600 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
10605 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
10606 f
->output_data
.x
->font_baseline
10607 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
10608 f
->output_data
.x
->fontset
= -1;
10610 /* Compute the scroll bar width in character columns. */
10611 if (f
->scroll_bar_pixel_width
> 0)
10613 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10614 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
10618 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10619 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
10622 /* Now make the frame display the given font. */
10623 if (FRAME_X_WINDOW (f
) != 0)
10625 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
10626 f
->output_data
.x
->font
->fid
);
10627 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
10628 f
->output_data
.x
->font
->fid
);
10629 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
10630 f
->output_data
.x
->font
->fid
);
10632 frame_update_line_height (f
);
10633 x_set_window_size (f
, 0, f
->width
, f
->height
);
10636 /* If we are setting a new frame's font for the first time,
10637 there are no faces yet, so this font's height is the line height. */
10638 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
10640 return build_string (fontp
->full_name
);
10643 /* Give frame F the fontset named FONTSETNAME as its default font, and
10644 return the full name of that fontset. FONTSETNAME may be a wildcard
10645 pattern; in that case, we choose some fontset that fits the pattern.
10646 The return value shows which fontset we chose. */
10649 x_new_fontset (f
, fontsetname
)
10653 int fontset
= fs_query_fontset (f
, fontsetname
);
10654 struct fontset_info
*fontsetp
;
10655 Lisp_Object result
;
10660 if (f
->output_data
.x
->fontset
== fontset
)
10661 /* This fontset is already set in frame F. There's nothing more
10663 return build_string (fontsetname
);
10665 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
10667 if (!fontsetp
->fontname
[CHARSET_ASCII
])
10668 /* This fontset doesn't contain ASCII font. */
10671 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
10673 if (!STRINGP (result
))
10674 /* Can't load ASCII font. */
10677 /* Since x_new_font doesn't update any fontset information, do it now. */
10678 f
->output_data
.x
->fontset
= fontset
;
10679 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
10680 CHARSET_ASCII
, fontsetp
->fontname
[CHARSET_ASCII
], fontset
);
10682 return build_string (fontsetname
);
10685 /* Calculate the absolute position in frame F
10686 from its current recorded position values and gravity. */
10689 x_calc_absolute_position (f
)
10693 int win_x
= 0, win_y
= 0;
10694 int flags
= f
->output_data
.x
->size_hint_flags
;
10697 /* We have nothing to do if the current position
10698 is already for the top-left corner. */
10699 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
10702 #ifdef USE_X_TOOLKIT
10703 this_window
= XtWindow (f
->output_data
.x
->widget
);
10705 this_window
= FRAME_X_WINDOW (f
);
10708 /* Find the position of the outside upper-left corner of
10709 the inner window, with respect to the outer window.
10710 But do this only if we will need the results. */
10711 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
10716 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
10719 x_clear_errors (FRAME_X_DISPLAY (f
));
10720 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
10722 /* From-window, to-window. */
10724 f
->output_data
.x
->parent_desc
,
10726 /* From-position, to-position. */
10727 0, 0, &win_x
, &win_y
,
10729 /* Child of win. */
10731 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
10733 Window newroot
, newparent
= 0xdeadbeef;
10734 Window
*newchildren
;
10737 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
10738 &newparent
, &newchildren
, &nchildren
))
10741 XFree ((char *) newchildren
);
10743 f
->output_data
.x
->parent_desc
= newparent
;
10749 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
10753 /* Treat negative positions as relative to the leftmost bottommost
10754 position that fits on the screen. */
10755 if (flags
& XNegative
)
10756 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
10757 - 2 * f
->output_data
.x
->border_width
- win_x
10759 + f
->output_data
.x
->left_pos
);
10761 if (flags
& YNegative
)
10763 int menubar_height
= 0;
10765 #ifdef USE_X_TOOLKIT
10766 if (f
->output_data
.x
->menubar_widget
)
10768 = (f
->output_data
.x
->menubar_widget
->core
.height
10769 + f
->output_data
.x
->menubar_widget
->core
.border_width
);
10772 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
10773 - 2 * f
->output_data
.x
->border_width
10777 + f
->output_data
.x
->top_pos
);
10780 /* The left_pos and top_pos
10781 are now relative to the top and left screen edges,
10782 so the flags should correspond. */
10783 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10786 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10787 to really change the position, and 0 when calling from
10788 x_make_frame_visible (in that case, XOFF and YOFF are the current
10789 position values). It is -1 when calling from x_set_frame_parameters,
10790 which means, do adjust for borders but don't change the gravity. */
10793 x_set_offset (f
, xoff
, yoff
, change_gravity
)
10795 register int xoff
, yoff
;
10796 int change_gravity
;
10798 int modified_top
, modified_left
;
10800 if (change_gravity
> 0)
10802 f
->output_data
.x
->top_pos
= yoff
;
10803 f
->output_data
.x
->left_pos
= xoff
;
10804 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10806 f
->output_data
.x
->size_hint_flags
|= XNegative
;
10808 f
->output_data
.x
->size_hint_flags
|= YNegative
;
10809 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10811 x_calc_absolute_position (f
);
10814 x_wm_set_size_hint (f
, (long) 0, 0);
10816 modified_left
= f
->output_data
.x
->left_pos
;
10817 modified_top
= f
->output_data
.x
->top_pos
;
10818 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
10819 this seems to be unnecessary and incorrect. rms, 4/17/97. */
10820 /* It is a mystery why we need to add the border_width here
10821 when the frame is already visible, but experiment says we do. */
10822 if (change_gravity
!= 0)
10824 modified_left
+= f
->output_data
.x
->border_width
;
10825 modified_top
+= f
->output_data
.x
->border_width
;
10829 #ifdef USE_X_TOOLKIT
10830 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10831 modified_left
, modified_top
);
10832 #else /* not USE_X_TOOLKIT */
10833 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10834 modified_left
, modified_top
);
10835 #endif /* not USE_X_TOOLKIT */
10839 /* Call this to change the size of frame F's x-window.
10840 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10841 for this size change and subsequent size changes.
10842 Otherwise we leave the window gravity unchanged. */
10845 x_set_window_size (f
, change_gravity
, cols
, rows
)
10847 int change_gravity
;
10850 #ifndef USE_X_TOOLKIT
10851 int pixelwidth
, pixelheight
;
10856 #ifdef USE_X_TOOLKIT
10858 /* The x and y position of the widget is clobbered by the
10859 call to XtSetValues within EmacsFrameSetCharSize.
10860 This is a real kludge, but I don't understand Xt so I can't
10861 figure out a correct fix. Can anyone else tell me? -- rms. */
10862 int xpos
= f
->output_data
.x
->widget
->core
.x
;
10863 int ypos
= f
->output_data
.x
->widget
->core
.y
;
10864 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
10865 f
->output_data
.x
->widget
->core
.x
= xpos
;
10866 f
->output_data
.x
->widget
->core
.y
= ypos
;
10869 #else /* not USE_X_TOOLKIT */
10871 check_frame_size (f
, &rows
, &cols
);
10872 f
->output_data
.x
->vertical_scroll_bar_extra
10873 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
10875 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
10876 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
10877 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
10878 f
->output_data
.x
->flags_areas_extra
10879 = FRAME_FLAGS_AREA_WIDTH (f
);
10880 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
10881 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
10883 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
10884 x_wm_set_size_hint (f
, (long) 0, 0);
10886 XSync (FRAME_X_DISPLAY (f
), False
);
10887 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10888 pixelwidth
, pixelheight
);
10890 /* Now, strictly speaking, we can't be sure that this is accurate,
10891 but the window manager will get around to dealing with the size
10892 change request eventually, and we'll hear how it went when the
10893 ConfigureNotify event gets here.
10895 We could just not bother storing any of this information here,
10896 and let the ConfigureNotify event set everything up, but that
10897 might be kind of confusing to the Lisp code, since size changes
10898 wouldn't be reported in the frame parameters until some random
10899 point in the future when the ConfigureNotify event arrives.
10901 We pass 1 for DELAY since we can't run Lisp code inside of
10903 change_frame_size (f
, rows
, cols
, 0, 1, 0);
10904 PIXEL_WIDTH (f
) = pixelwidth
;
10905 PIXEL_HEIGHT (f
) = pixelheight
;
10907 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10908 receive in the ConfigureNotify event; if we get what we asked
10909 for, then the event won't cause the screen to become garbaged, so
10910 we have to make sure to do it here. */
10911 SET_FRAME_GARBAGED (f
);
10913 XFlush (FRAME_X_DISPLAY (f
));
10915 #endif /* not USE_X_TOOLKIT */
10917 /* If cursor was outside the new size, mark it as off. */
10918 mark_window_cursors_off (XWINDOW (f
->root_window
));
10920 /* Clear out any recollection of where the mouse highlighting was,
10921 since it might be in a place that's outside the new frame size.
10922 Actually checking whether it is outside is a pain in the neck,
10923 so don't try--just let the highlighting be done afresh with new size. */
10924 cancel_mouse_face (f
);
10929 /* Mouse warping. */
10932 x_set_mouse_position (f
, x
, y
)
10938 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
10939 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
10941 if (pix_x
< 0) pix_x
= 0;
10942 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
10944 if (pix_y
< 0) pix_y
= 0;
10945 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
10949 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
10950 0, 0, 0, 0, pix_x
, pix_y
);
10954 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
10957 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
10963 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
10964 0, 0, 0, 0, pix_x
, pix_y
);
10968 /* focus shifting, raising and lowering. */
10971 x_focus_on_frame (f
)
10974 #if 0 /* This proves to be unpleasant. */
10978 /* I don't think that the ICCCM allows programs to do things like this
10979 without the interaction of the window manager. Whatever you end up
10980 doing with this code, do it to x_unfocus_frame too. */
10981 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10982 RevertToPointerRoot
, CurrentTime
);
10987 x_unfocus_frame (f
)
10991 /* Look at the remarks in x_focus_on_frame. */
10992 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
10993 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
10994 RevertToPointerRoot
, CurrentTime
);
10998 /* Raise frame F. */
11004 if (f
->async_visible
)
11007 #ifdef USE_X_TOOLKIT
11008 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11009 #else /* not USE_X_TOOLKIT */
11010 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11011 #endif /* not USE_X_TOOLKIT */
11012 XFlush (FRAME_X_DISPLAY (f
));
11017 /* Lower frame F. */
11023 if (f
->async_visible
)
11026 #ifdef USE_X_TOOLKIT
11027 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11028 #else /* not USE_X_TOOLKIT */
11029 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11030 #endif /* not USE_X_TOOLKIT */
11031 XFlush (FRAME_X_DISPLAY (f
));
11037 XTframe_raise_lower (f
, raise_flag
)
11047 /* Change of visibility. */
11049 /* This tries to wait until the frame is really visible.
11050 However, if the window manager asks the user where to position
11051 the frame, this will return before the user finishes doing that.
11052 The frame will not actually be visible at that time,
11053 but it will become visible later when the window manager
11054 finishes with it. */
11057 x_make_frame_visible (f
)
11061 int original_top
, original_left
;
11065 type
= x_icon_type (f
);
11067 x_bitmap_icon (f
, type
);
11069 if (! FRAME_VISIBLE_P (f
))
11071 /* We test FRAME_GARBAGED_P here to make sure we don't
11072 call x_set_offset a second time
11073 if we get to x_make_frame_visible a second time
11074 before the window gets really visible. */
11075 if (! FRAME_ICONIFIED_P (f
)
11076 && ! f
->output_data
.x
->asked_for_visible
)
11077 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11079 f
->output_data
.x
->asked_for_visible
= 1;
11081 if (! EQ (Vx_no_window_manager
, Qt
))
11082 x_wm_set_window_state (f
, NormalState
);
11083 #ifdef USE_X_TOOLKIT
11084 /* This was XtPopup, but that did nothing for an iconified frame. */
11085 XtMapWidget (f
->output_data
.x
->widget
);
11086 #else /* not USE_X_TOOLKIT */
11087 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11088 #endif /* not USE_X_TOOLKIT */
11089 #if 0 /* This seems to bring back scroll bars in the wrong places
11090 if the window configuration has changed. They seem
11091 to come back ok without this. */
11092 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
11093 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11097 XFlush (FRAME_X_DISPLAY (f
));
11099 /* Synchronize to ensure Emacs knows the frame is visible
11100 before we do anything else. We do this loop with input not blocked
11101 so that incoming events are handled. */
11104 int count
= input_signal_count
;
11105 /* This must be before UNBLOCK_INPUT
11106 since events that arrive in response to the actions above
11107 will set it when they are handled. */
11108 int previously_visible
= f
->output_data
.x
->has_been_visible
;
11110 original_left
= f
->output_data
.x
->left_pos
;
11111 original_top
= f
->output_data
.x
->top_pos
;
11113 /* This must come after we set COUNT. */
11116 /* We unblock here so that arriving X events are processed. */
11118 /* Now move the window back to where it was "supposed to be".
11119 But don't do it if the gravity is negative.
11120 When the gravity is negative, this uses a position
11121 that is 3 pixels too low. Perhaps that's really the border width.
11123 Don't do this if the window has never been visible before,
11124 because the window manager may choose the position
11125 and we don't want to override it. */
11127 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
11128 && f
->output_data
.x
->win_gravity
== NorthWestGravity
11129 && previously_visible
)
11133 unsigned int width
, height
, border
, depth
;
11137 /* On some window managers (such as FVWM) moving an existing
11138 window, even to the same place, causes the window manager
11139 to introduce an offset. This can cause the window to move
11140 to an unexpected location. Check the geometry (a little
11141 slow here) and then verify that the window is in the right
11142 place. If the window is not in the right place, move it
11143 there, and take the potential window manager hit. */
11144 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11145 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
11147 if (original_left
!= x
|| original_top
!= y
)
11148 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11149 original_left
, original_top
);
11154 XSETFRAME (frame
, f
);
11159 /* Once we have handled input events,
11160 we should have received the MapNotify if one is coming.
11161 So if we have not got it yet, stop looping.
11162 Some window managers make their own decisions
11163 about visibility. */
11164 if (input_signal_count
!= count
)
11166 /* Machines that do polling rather than SIGIO have been observed
11167 to go into a busy-wait here. So we'll fake an alarm signal
11168 to let the handler know that there's something to be read.
11169 We used to raise a real alarm, but it seems that the handler
11170 isn't always enabled here. This is probably a bug. */
11171 if (input_polling_used ())
11173 /* It could be confusing if a real alarm arrives while processing
11174 the fake one. Turn it off and let the handler reset it. */
11176 input_poll_signal (0);
11178 /* Once we have handled input events,
11179 we should have received the MapNotify if one is coming.
11180 So if we have not got it yet, stop looping.
11181 Some window managers make their own decisions
11182 about visibility. */
11183 if (input_signal_count
!= count
)
11186 FRAME_SAMPLE_VISIBILITY (f
);
11190 /* Change from mapped state to withdrawn state. */
11192 /* Make the frame visible (mapped and not iconified). */
11195 x_make_frame_invisible (f
)
11200 #ifdef USE_X_TOOLKIT
11201 /* Use the frame's outermost window, not the one we normally draw on. */
11202 window
= XtWindow (f
->output_data
.x
->widget
);
11203 #else /* not USE_X_TOOLKIT */
11204 window
= FRAME_X_WINDOW (f
);
11205 #endif /* not USE_X_TOOLKIT */
11207 /* Don't keep the highlight on an invisible frame. */
11208 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11209 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11211 #if 0/* This might add unreliability; I don't trust it -- rms. */
11212 if (! f
->async_visible
&& ! f
->async_iconified
)
11218 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11219 that the current position of the window is user-specified, rather than
11220 program-specified, so that when the window is mapped again, it will be
11221 placed at the same location, without forcing the user to position it
11222 by hand again (they have already done that once for this window.) */
11223 x_wm_set_size_hint (f
, (long) 0, 1);
11227 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11228 DefaultScreen (FRAME_X_DISPLAY (f
))))
11230 UNBLOCK_INPUT_RESIGNAL
;
11231 error ("Can't notify window manager of window withdrawal");
11233 #else /* ! defined (HAVE_X11R4) */
11235 /* Tell the window manager what we're going to do. */
11236 if (! EQ (Vx_no_window_manager
, Qt
))
11240 unmap
.xunmap
.type
= UnmapNotify
;
11241 unmap
.xunmap
.window
= window
;
11242 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
11243 unmap
.xunmap
.from_configure
= False
;
11244 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11245 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11247 SubstructureRedirectMaskSubstructureNotifyMask
,
11250 UNBLOCK_INPUT_RESIGNAL
;
11251 error ("Can't notify window manager of withdrawal");
11255 /* Unmap the window ourselves. Cheeky! */
11256 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
11257 #endif /* ! defined (HAVE_X11R4) */
11259 /* We can't distinguish this from iconification
11260 just by the event that we get from the server.
11261 So we can't win using the usual strategy of letting
11262 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11263 and synchronize with the server to make sure we agree. */
11265 FRAME_ICONIFIED_P (f
) = 0;
11266 f
->async_visible
= 0;
11267 f
->async_iconified
= 0;
11274 /* Change window state from mapped to iconified. */
11277 x_iconify_frame (f
)
11283 /* Don't keep the highlight on an invisible frame. */
11284 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11285 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11287 if (f
->async_iconified
)
11292 FRAME_SAMPLE_VISIBILITY (f
);
11294 type
= x_icon_type (f
);
11296 x_bitmap_icon (f
, type
);
11298 #ifdef USE_X_TOOLKIT
11300 if (! FRAME_VISIBLE_P (f
))
11302 if (! EQ (Vx_no_window_manager
, Qt
))
11303 x_wm_set_window_state (f
, IconicState
);
11304 /* This was XtPopup, but that did nothing for an iconified frame. */
11305 XtMapWidget (f
->output_data
.x
->widget
);
11306 /* The server won't give us any event to indicate
11307 that an invisible frame was changed to an icon,
11308 so we have to record it here. */
11311 f
->async_iconified
= 1;
11312 f
->async_visible
= 0;
11317 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11318 XtWindow (f
->output_data
.x
->widget
),
11319 DefaultScreen (FRAME_X_DISPLAY (f
)));
11323 error ("Can't notify window manager of iconification");
11325 f
->async_iconified
= 1;
11326 f
->async_visible
= 0;
11330 XFlush (FRAME_X_DISPLAY (f
));
11332 #else /* not USE_X_TOOLKIT */
11334 /* Make sure the X server knows where the window should be positioned,
11335 in case the user deiconifies with the window manager. */
11336 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
11337 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11339 /* Since we don't know which revision of X we're running, we'll use both
11340 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11342 /* X11R4: send a ClientMessage to the window manager using the
11343 WM_CHANGE_STATE type. */
11347 message
.xclient
.window
= FRAME_X_WINDOW (f
);
11348 message
.xclient
.type
= ClientMessage
;
11349 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
11350 message
.xclient
.format
= 32;
11351 message
.xclient
.data
.l
[0] = IconicState
;
11353 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11354 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11356 SubstructureRedirectMask
| SubstructureNotifyMask
,
11359 UNBLOCK_INPUT_RESIGNAL
;
11360 error ("Can't notify window manager of iconification");
11364 /* X11R3: set the initial_state field of the window manager hints to
11366 x_wm_set_window_state (f
, IconicState
);
11368 if (!FRAME_VISIBLE_P (f
))
11370 /* If the frame was withdrawn, before, we must map it. */
11371 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11374 f
->async_iconified
= 1;
11375 f
->async_visible
= 0;
11377 XFlush (FRAME_X_DISPLAY (f
));
11379 #endif /* not USE_X_TOOLKIT */
11382 /* Destroy the X window of frame F. */
11385 x_destroy_window (f
)
11388 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11392 /* If a display connection is dead, don't try sending more
11393 commands to the X server. */
11394 if (dpyinfo
->display
!= 0)
11396 if (f
->output_data
.x
->icon_desc
!= 0)
11397 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
11401 XDestroyIC (FRAME_XIC (f
));
11402 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11403 /* This line causes crashes on Solaris with Openwin,
11404 due to an apparent bug in XCloseIM.
11405 X11R6 seems not to have the bug. */
11406 XCloseIM (FRAME_XIM (f
));
11410 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
11411 #ifdef USE_X_TOOLKIT
11412 if (f
->output_data
.x
->widget
)
11413 XtDestroyWidget (f
->output_data
.x
->widget
);
11414 free_frame_menubar (f
);
11415 #endif /* USE_X_TOOLKIT */
11417 free_frame_faces (f
);
11418 XFlush (FRAME_X_DISPLAY (f
));
11421 if (f
->output_data
.x
->saved_menu_event
)
11422 xfree (f
->output_data
.x
->saved_menu_event
);
11424 xfree (f
->output_data
.x
);
11425 f
->output_data
.x
= 0;
11426 if (f
== dpyinfo
->x_focus_frame
)
11427 dpyinfo
->x_focus_frame
= 0;
11428 if (f
== dpyinfo
->x_focus_event_frame
)
11429 dpyinfo
->x_focus_event_frame
= 0;
11430 if (f
== dpyinfo
->x_highlight_frame
)
11431 dpyinfo
->x_highlight_frame
= 0;
11433 dpyinfo
->reference_count
--;
11435 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11437 dpyinfo
->mouse_face_beg_row
11438 = dpyinfo
->mouse_face_beg_col
= -1;
11439 dpyinfo
->mouse_face_end_row
11440 = dpyinfo
->mouse_face_end_col
= -1;
11441 dpyinfo
->mouse_face_window
= Qnil
;
11442 dpyinfo
->mouse_face_deferred_gc
= 0;
11443 dpyinfo
->mouse_face_mouse_frame
= 0;
11449 /* Setting window manager hints. */
11451 /* Set the normal size hints for the window manager, for frame F.
11452 FLAGS is the flags word to use--or 0 meaning preserve the flags
11453 that the window now has.
11454 If USER_POSITION is nonzero, we set the USPosition
11455 flag (this is useful when FLAGS is 0). */
11458 x_wm_set_size_hint (f
, flags
, user_position
)
11463 XSizeHints size_hints
;
11465 #ifdef USE_X_TOOLKIT
11468 Dimension widget_width
, widget_height
;
11469 Window window
= XtWindow (f
->output_data
.x
->widget
);
11470 #else /* not USE_X_TOOLKIT */
11471 Window window
= FRAME_X_WINDOW (f
);
11472 #endif /* not USE_X_TOOLKIT */
11474 /* Setting PMaxSize caused various problems. */
11475 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
11477 size_hints
.x
= f
->output_data
.x
->left_pos
;
11478 size_hints
.y
= f
->output_data
.x
->top_pos
;
11480 #ifdef USE_X_TOOLKIT
11481 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
11482 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
11483 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
11484 size_hints
.height
= widget_height
;
11485 size_hints
.width
= widget_width
;
11486 #else /* not USE_X_TOOLKIT */
11487 size_hints
.height
= PIXEL_HEIGHT (f
);
11488 size_hints
.width
= PIXEL_WIDTH (f
);
11489 #endif /* not USE_X_TOOLKIT */
11491 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
11492 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
11493 size_hints
.max_width
11494 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
11495 size_hints
.max_height
11496 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
11498 /* Calculate the base and minimum sizes.
11500 (When we use the X toolkit, we don't do it here.
11501 Instead we copy the values that the widgets are using, below.) */
11502 #ifndef USE_X_TOOLKIT
11504 int base_width
, base_height
;
11505 int min_rows
= 0, min_cols
= 0;
11507 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
11508 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
11510 check_frame_size (f
, &min_rows
, &min_cols
);
11512 /* The window manager uses the base width hints to calculate the
11513 current number of rows and columns in the frame while
11514 resizing; min_width and min_height aren't useful for this
11515 purpose, since they might not give the dimensions for a
11516 zero-row, zero-column frame.
11518 We use the base_width and base_height members if we have
11519 them; otherwise, we set the min_width and min_height members
11520 to the size for a zero x zero frame. */
11523 size_hints
.flags
|= PBaseSize
;
11524 size_hints
.base_width
= base_width
;
11525 size_hints
.base_height
= base_height
;
11526 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
11527 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
11529 size_hints
.min_width
= base_width
;
11530 size_hints
.min_height
= base_height
;
11534 /* If we don't need the old flags, we don't need the old hint at all. */
11537 size_hints
.flags
|= flags
;
11540 #endif /* not USE_X_TOOLKIT */
11543 XSizeHints hints
; /* Sometimes I hate X Windows... */
11544 long supplied_return
;
11548 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
11551 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
11554 #ifdef USE_X_TOOLKIT
11555 size_hints
.base_height
= hints
.base_height
;
11556 size_hints
.base_width
= hints
.base_width
;
11557 size_hints
.min_height
= hints
.min_height
;
11558 size_hints
.min_width
= hints
.min_width
;
11562 size_hints
.flags
|= flags
;
11567 if (hints
.flags
& PSize
)
11568 size_hints
.flags
|= PSize
;
11569 if (hints
.flags
& PPosition
)
11570 size_hints
.flags
|= PPosition
;
11571 if (hints
.flags
& USPosition
)
11572 size_hints
.flags
|= USPosition
;
11573 if (hints
.flags
& USSize
)
11574 size_hints
.flags
|= USSize
;
11578 #ifndef USE_X_TOOLKIT
11583 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
11584 size_hints
.flags
|= PWinGravity
;
11588 size_hints
.flags
&= ~ PPosition
;
11589 size_hints
.flags
|= USPosition
;
11591 #endif /* PWinGravity */
11594 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11596 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11600 /* Used for IconicState or NormalState */
11603 x_wm_set_window_state (f
, state
)
11607 #ifdef USE_X_TOOLKIT
11610 XtSetArg (al
[0], XtNinitialState
, state
);
11611 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11612 #else /* not USE_X_TOOLKIT */
11613 Window window
= FRAME_X_WINDOW (f
);
11615 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
11616 f
->output_data
.x
->wm_hints
.initial_state
= state
;
11618 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11619 #endif /* not USE_X_TOOLKIT */
11623 x_wm_set_icon_pixmap (f
, pixmap_id
)
11627 Pixmap icon_pixmap
;
11629 #ifndef USE_X_TOOLKIT
11630 Window window
= FRAME_X_WINDOW (f
);
11635 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
11636 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
11640 /* It seems there is no way to turn off use of an icon pixmap.
11641 The following line does it, only if no icon has yet been created,
11642 for some window managers. But with mwm it crashes.
11643 Some people say it should clear the IconPixmapHint bit in this case,
11644 but that doesn't work, and the X consortium said it isn't the
11645 right thing at all. Since there is no way to win,
11646 best to explicitly give up. */
11648 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
11654 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11658 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
11659 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11662 #else /* not USE_X_TOOLKIT */
11664 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
11665 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11667 #endif /* not USE_X_TOOLKIT */
11671 x_wm_set_icon_position (f
, icon_x
, icon_y
)
11673 int icon_x
, icon_y
;
11675 #ifdef USE_X_TOOLKIT
11676 Window window
= XtWindow (f
->output_data
.x
->widget
);
11678 Window window
= FRAME_X_WINDOW (f
);
11681 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
11682 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
11683 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
11685 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11689 /***********************************************************************
11691 ***********************************************************************/
11693 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
11696 x_get_font_info (f
, font_idx
)
11700 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
11704 /* Return a list of names of available fonts matching PATTERN on frame
11705 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11706 to be listed. Frame F NULL means we have not yet created any
11707 frame on X, and consult the first display in x_display_list.
11708 MAXNAMES sets a limit on how many fonts to match. */
11711 x_list_fonts (f
, pattern
, size
, maxnames
)
11713 Lisp_Object pattern
;
11717 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
11718 Lisp_Object tem
, second_best
;
11719 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
11720 int try_XLoadQueryFont
= 0;
11723 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
11724 if (NILP (patterns
))
11725 patterns
= Fcons (pattern
, Qnil
);
11727 if (maxnames
== 1 && !size
)
11728 /* We can return any single font matching PATTERN. */
11729 try_XLoadQueryFont
= 1;
11731 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
11736 pattern
= XCAR (patterns
);
11737 /* See if we cached the result for this particular query.
11738 The cache is an alist of the form:
11739 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11741 if (f
&& (tem
= XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
),
11742 key
= Fcons (pattern
, make_number (maxnames
)),
11743 !NILP (list
= Fassoc (key
, tem
))))
11745 list
= Fcdr_safe (list
);
11746 /* We have a cashed list. Don't have to get the list again. */
11750 /* At first, put PATTERN in the cache. */
11753 count
= x_catch_errors (dpy
);
11755 if (try_XLoadQueryFont
)
11758 unsigned long value
;
11760 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
11761 if (x_had_errors_p (dpy
))
11763 /* This error is perhaps due to insufficient memory on X
11764 server. Let's just ignore it. */
11766 x_clear_errors (dpy
);
11770 && XGetFontProperty (font
, XA_FONT
, &value
))
11772 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
11773 int len
= strlen (name
);
11776 /* If DXPC (a Differential X Protocol Compressor)
11777 Ver.3.7 is running, XGetAtomName will return null
11778 string. We must avoid such a name. */
11780 try_XLoadQueryFont
= 0;
11784 names
= (char **) alloca (sizeof (char *));
11785 /* Some systems only allow alloca assigned to a
11787 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
11788 bcopy (name
, names
[0], len
+ 1);
11793 try_XLoadQueryFont
= 0;
11796 XFreeFont (dpy
, font
);
11799 if (!try_XLoadQueryFont
)
11801 /* We try at least 10 fonts because XListFonts will return
11802 auto-scaled fonts at the head. */
11803 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
11805 if (x_had_errors_p (dpy
))
11807 /* This error is perhaps due to insufficient memory on X
11808 server. Let's just ignore it. */
11810 x_clear_errors (dpy
);
11814 x_uncatch_errors (dpy
, count
);
11821 /* Make a list of all the fonts we got back.
11822 Store that in the font cache for the display. */
11823 for (i
= 0; i
< num_fonts
; i
++)
11826 char *p
= names
[i
];
11827 int average_width
= -1, dashes
= 0;
11829 /* Count the number of dashes in NAMES[I]. If there are
11830 14 dashes, and the field value following 12th dash
11831 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
11832 is usually too ugly to be used for editing. Let's
11838 if (dashes
== 7) /* PIXEL_SIZE field */
11840 else if (dashes
== 12) /* AVERAGE_WIDTH field */
11841 average_width
= atoi (p
);
11843 if (dashes
< 14 || average_width
!= 0)
11845 tem
= build_string (names
[i
]);
11846 if (NILP (Fassoc (tem
, list
)))
11848 if (STRINGP (Vx_pixel_size_width_font_regexp
)
11849 && ((fast_c_string_match_ignore_case
11850 (Vx_pixel_size_width_font_regexp
, names
[i
]))
11852 /* We can set the value of PIXEL_SIZE to the
11853 width of this font. */
11854 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
11856 /* For the moment, width is not known. */
11857 list
= Fcons (Fcons (tem
, Qnil
), list
);
11861 if (!try_XLoadQueryFont
)
11862 XFreeFontNames (names
);
11865 /* Now store the result in the cache. */
11867 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)
11868 = Fcons (Fcons (key
, list
),
11869 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
11872 if (NILP (list
)) continue; /* Try the remaining alternatives. */
11874 newlist
= second_best
= Qnil
;
11875 /* Make a list of the fonts that have the right width. */
11876 for (; CONSP (list
); list
= XCDR (list
))
11882 if (!CONSP (tem
) || NILP (XCAR (tem
)))
11886 newlist
= Fcons (XCAR (tem
), newlist
);
11890 if (!INTEGERP (XCDR (tem
)))
11892 /* Since we have not yet known the size of this font, we
11893 must try slow function call XLoadQueryFont. */
11894 XFontStruct
*thisinfo
;
11897 count
= x_catch_errors (dpy
);
11898 thisinfo
= XLoadQueryFont (dpy
,
11899 XSTRING (XCAR (tem
))->data
);
11900 if (x_had_errors_p (dpy
))
11902 /* This error is perhaps due to insufficient memory on X
11903 server. Let's just ignore it. */
11905 x_clear_errors (dpy
);
11907 x_uncatch_errors (dpy
, count
);
11913 = (thisinfo
->min_bounds
.width
== 0
11915 : make_number (thisinfo
->max_bounds
.width
));
11916 XFreeFont (dpy
, thisinfo
);
11919 /* For unknown reason, the previous call of XListFont had
11920 returned a font which can't be opened. Record the size
11921 as 0 not to try to open it again. */
11922 XCDR (tem
) = make_number (0);
11925 found_size
= XINT (XCDR (tem
));
11926 if (found_size
== size
)
11927 newlist
= Fcons (XCAR (tem
), newlist
);
11928 else if (found_size
> 0)
11930 if (NILP (second_best
))
11932 else if (found_size
< size
)
11934 if (XINT (XCDR (second_best
)) > size
11935 || XINT (XCDR (second_best
)) < found_size
)
11940 if (XINT (XCDR (second_best
)) > size
11941 && XINT (XCDR (second_best
)) > found_size
)
11946 if (!NILP (newlist
))
11948 else if (!NILP (second_best
))
11950 newlist
= Fcons (XCAR (second_best
), Qnil
);
11961 /* Check that FONT is valid on frame F. It is if it can be found in F's
11965 x_check_font (f
, font
)
11970 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11972 xassert (font
!= NULL
);
11974 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
11975 if (dpyinfo
->font_table
[i
].name
11976 && font
== dpyinfo
->font_table
[i
].font
)
11979 xassert (i
< dpyinfo
->n_fonts
);
11982 #endif /* GLYPH_DEBUG != 0 */
11984 /* Set *W to the minimum width, *H to the minimum font height of FONT.
11985 Note: There are (broken) X fonts out there with invalid XFontStruct
11986 min_bounds contents. For example, handa@etl.go.jp reports that
11987 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
11988 have font->min_bounds.width == 0. */
11991 x_font_min_bounds (font
, w
, h
)
11995 *h
= FONT_HEIGHT (font
);
11996 *w
= font
->min_bounds
.width
;
11998 /* Try to handle the case where FONT->min_bounds has invalid
11999 contents. Since the only font known to have invalid min_bounds
12000 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12002 *w
= font
->max_bounds
.width
;
12006 /* Compute the smallest character width and smallest font height over
12007 all fonts available on frame F. Set the members smallest_char_width
12008 and smallest_font_height in F's x_display_info structure to
12009 the values computed. Value is non-zero if smallest_font_height or
12010 smallest_char_width become smaller than they were before. */
12013 x_compute_min_glyph_bounds (f
)
12017 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12019 int old_width
= dpyinfo
->smallest_char_width
;
12020 int old_height
= dpyinfo
->smallest_font_height
;
12022 dpyinfo
->smallest_font_height
= 100000;
12023 dpyinfo
->smallest_char_width
= 100000;
12025 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12026 if (dpyinfo
->font_table
[i
].name
)
12028 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
12031 font
= (XFontStruct
*) fontp
->font
;
12032 xassert (font
!= (XFontStruct
*) ~0);
12033 x_font_min_bounds (font
, &w
, &h
);
12035 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
12036 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
12039 xassert (dpyinfo
->smallest_char_width
> 0
12040 && dpyinfo
->smallest_font_height
> 0);
12042 return (dpyinfo
->n_fonts
== 1
12043 || dpyinfo
->smallest_char_width
< old_width
12044 || dpyinfo
->smallest_font_height
< old_height
);
12048 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12049 pointer to the structure font_info while allocating it dynamically.
12050 If SIZE is 0, load any size of font.
12051 If loading is failed, return NULL. */
12054 x_load_font (f
, fontname
, size
)
12056 register char *fontname
;
12059 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12060 Lisp_Object font_names
;
12063 /* Get a list of all the fonts that match this name. Once we
12064 have a list of matching fonts, we compare them against the fonts
12065 we already have by comparing names. */
12066 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
12068 if (!NILP (font_names
))
12073 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12074 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
12075 if (dpyinfo
->font_table
[i
].name
12076 && (!strcmp (dpyinfo
->font_table
[i
].name
,
12077 XSTRING (XCAR (tail
))->data
)
12078 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
12079 XSTRING (XCAR (tail
))->data
)))
12080 return (dpyinfo
->font_table
+ i
);
12083 /* Load the font and add it to the table. */
12087 struct font_info
*fontp
;
12088 unsigned long value
;
12091 /* If we have found fonts by x_list_font, load one of them. If
12092 not, we still try to load a font by the name given as FONTNAME
12093 because XListFonts (called in x_list_font) of some X server has
12094 a bug of not finding a font even if the font surely exists and
12095 is loadable by XLoadQueryFont. */
12096 if (size
> 0 && !NILP (font_names
))
12097 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
12100 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
12101 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
12102 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
12104 /* This error is perhaps due to insufficient memory on X
12105 server. Let's just ignore it. */
12107 x_clear_errors (FRAME_X_DISPLAY (f
));
12109 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
12114 /* Find a free slot in the font table. */
12115 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12116 if (dpyinfo
->font_table
[i
].name
== NULL
)
12119 /* If no free slot found, maybe enlarge the font table. */
12120 if (i
== dpyinfo
->n_fonts
12121 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
12124 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
12125 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
12126 dpyinfo
->font_table
12127 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
12130 fontp
= dpyinfo
->font_table
+ i
;
12131 if (i
== dpyinfo
->n_fonts
)
12132 ++dpyinfo
->n_fonts
;
12134 /* Now fill in the slots of *FONTP. */
12136 fontp
->font
= font
;
12137 fontp
->font_idx
= i
;
12138 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
12139 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
12141 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12143 if (XGetFontProperty (font
, XA_FONT
, &value
))
12145 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
12149 /* Count the number of dashes in the "full name".
12150 If it is too few, this isn't really the font's full name,
12152 In X11R4, the fonts did not come with their canonical names
12163 full_name
= (char *) xmalloc (p
- name
+ 1);
12164 bcopy (name
, full_name
, p
- name
+ 1);
12170 if (full_name
!= 0)
12171 fontp
->full_name
= full_name
;
12173 fontp
->full_name
= fontp
->name
;
12175 fontp
->size
= font
->max_bounds
.width
;
12176 fontp
->height
= FONT_HEIGHT (font
);
12178 /* For some font, ascent and descent in max_bounds field is
12179 larger than the above value. */
12180 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
12181 if (max_height
> fontp
->height
)
12182 fontp
->height
= max_height
;
12185 if (NILP (font_names
))
12187 /* We come here because of a bug of XListFonts mentioned at
12188 the head of this block. Let's store this information in
12189 the cache for x_list_fonts. */
12190 Lisp_Object lispy_name
= build_string (fontname
);
12191 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
12193 XCDR (dpyinfo
->name_list_element
)
12194 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
12195 Fcons (Fcons (lispy_full_name
,
12196 make_number (fontp
->size
)),
12198 XCDR (dpyinfo
->name_list_element
));
12200 XCDR (dpyinfo
->name_list_element
)
12201 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
12202 Fcons (Fcons (lispy_full_name
,
12203 make_number (fontp
->size
)),
12205 XCDR (dpyinfo
->name_list_element
));
12208 /* The slot `encoding' specifies how to map a character
12209 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12210 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12211 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12212 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12213 2:0xA020..0xFF7F). For the moment, we don't know which charset
12214 uses this font. So, we set information in fontp->encoding[1]
12215 which is never used by any charset. If mapping can't be
12216 decided, set FONT_ENCODING_NOT_DECIDED. */
12218 = (font
->max_byte1
== 0
12220 ? (font
->min_char_or_byte2
< 0x80
12221 ? (font
->max_char_or_byte2
< 0x80
12222 ? 0 /* 0x20..0x7F */
12223 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
12224 : 1) /* 0xA0..0xFF */
12226 : (font
->min_byte1
< 0x80
12227 ? (font
->max_byte1
< 0x80
12228 ? (font
->min_char_or_byte2
< 0x80
12229 ? (font
->max_char_or_byte2
< 0x80
12230 ? 0 /* 0x2020..0x7F7F */
12231 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
12232 : 3) /* 0x20A0..0x7FFF */
12233 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
12234 : (font
->min_char_or_byte2
< 0x80
12235 ? (font
->max_char_or_byte2
< 0x80
12236 ? 2 /* 0xA020..0xFF7F */
12237 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
12238 : 1))); /* 0xA0A0..0xFFFF */
12240 fontp
->baseline_offset
12241 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
12242 ? (long) value
: 0);
12243 fontp
->relative_compose
12244 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
12245 ? (long) value
: 0);
12246 fontp
->default_ascent
12247 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
12248 ? (long) value
: 0);
12250 /* Set global flag fonts_changed_p to non-zero if the font loaded
12251 has a character with a smaller width than any other character
12252 before, or if the font loaded has a smalle>r height than any
12253 other font loaded before. If this happens, it will make a
12254 glyph matrix reallocation necessary. */
12255 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
12262 /* Return a pointer to struct font_info of a font named FONTNAME for
12263 frame F. If no such font is loaded, return NULL. */
12266 x_query_font (f
, fontname
)
12268 register char *fontname
;
12270 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12273 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12274 if (dpyinfo
->font_table
[i
].name
12275 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
12276 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
12277 return (dpyinfo
->font_table
+ i
);
12282 /* Find a CCL program for a font specified by FONTP, and set the member
12283 `encoder' of the structure. */
12286 x_find_ccl_program (fontp
)
12287 struct font_info
*fontp
;
12289 Lisp_Object list
, elt
;
12291 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
12295 && STRINGP (XCAR (elt
))
12296 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
12302 struct ccl_program
*ccl
12303 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
12305 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
12308 fontp
->font_encoder
= ccl
;
12314 /***********************************************************************
12316 ***********************************************************************/
12318 #ifdef USE_X_TOOLKIT
12319 static XrmOptionDescRec emacs_options
[] = {
12320 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
12321 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
12323 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12324 XrmoptionSepArg
, NULL
},
12325 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
12327 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12328 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12329 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12330 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12331 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12332 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
12333 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
12335 #endif /* USE_X_TOOLKIT */
12337 static int x_initialized
;
12339 #ifdef MULTI_KBOARD
12340 /* Test whether two display-name strings agree up to the dot that separates
12341 the screen number from the server number. */
12343 same_x_server (name1
, name2
)
12344 char *name1
, *name2
;
12346 int seen_colon
= 0;
12347 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
12348 int system_name_length
= strlen (system_name
);
12349 int length_until_period
= 0;
12351 while (system_name
[length_until_period
] != 0
12352 && system_name
[length_until_period
] != '.')
12353 length_until_period
++;
12355 /* Treat `unix' like an empty host name. */
12356 if (! strncmp (name1
, "unix:", 5))
12358 if (! strncmp (name2
, "unix:", 5))
12360 /* Treat this host's name like an empty host name. */
12361 if (! strncmp (name1
, system_name
, system_name_length
)
12362 && name1
[system_name_length
] == ':')
12363 name1
+= system_name_length
;
12364 if (! strncmp (name2
, system_name
, system_name_length
)
12365 && name2
[system_name_length
] == ':')
12366 name2
+= system_name_length
;
12367 /* Treat this host's domainless name like an empty host name. */
12368 if (! strncmp (name1
, system_name
, length_until_period
)
12369 && name1
[length_until_period
] == ':')
12370 name1
+= length_until_period
;
12371 if (! strncmp (name2
, system_name
, length_until_period
)
12372 && name2
[length_until_period
] == ':')
12373 name2
+= length_until_period
;
12375 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
12379 if (seen_colon
&& *name1
== '.')
12383 && (*name1
== '.' || *name1
== '\0')
12384 && (*name2
== '.' || *name2
== '\0'));
12388 struct x_display_info
*
12389 x_term_init (display_name
, xrm_option
, resource_name
)
12390 Lisp_Object display_name
;
12392 char *resource_name
;
12396 struct x_display_info
*dpyinfo
;
12401 if (!x_initialized
)
12407 #ifdef USE_X_TOOLKIT
12408 /* weiner@footloose.sps.mot.com reports that this causes
12410 X protocol error: BadAtom (invalid Atom parameter)
12411 on protocol request 18skiloaf.
12412 So let's not use it until R6. */
12413 #ifdef HAVE_X11XTR6
12414 XtSetLanguageProc (NULL
, NULL
, NULL
);
12425 argv
[argc
++] = "-xrm";
12426 argv
[argc
++] = xrm_option
;
12428 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
12429 resource_name
, EMACS_CLASS
,
12430 emacs_options
, XtNumber (emacs_options
),
12433 #ifdef HAVE_X11XTR6
12434 /* I think this is to compensate for XtSetLanguageProc. */
12439 #else /* not USE_X_TOOLKIT */
12441 XSetLocaleModifiers ("");
12443 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
12444 #endif /* not USE_X_TOOLKIT */
12446 /* Detect failure. */
12453 /* We have definitely succeeded. Record the new connection. */
12455 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
12457 #ifdef MULTI_KBOARD
12459 struct x_display_info
*share
;
12462 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
12463 share
= share
->next
, tail
= XCDR (tail
))
12464 if (same_x_server (XSTRING (XCAR (XCAR (tail
)))->data
,
12465 XSTRING (display_name
)->data
))
12468 dpyinfo
->kboard
= share
->kboard
;
12471 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
12472 init_kboard (dpyinfo
->kboard
);
12473 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
12475 char *vendor
= ServerVendor (dpy
);
12476 dpyinfo
->kboard
->Vsystem_key_alist
12477 = call1 (Qvendor_specific_keysyms
,
12478 build_string (vendor
? vendor
: ""));
12481 dpyinfo
->kboard
->next_kboard
= all_kboards
;
12482 all_kboards
= dpyinfo
->kboard
;
12483 /* Don't let the initial kboard remain current longer than necessary.
12484 That would cause problems if a file loaded on startup tries to
12485 prompt in the mini-buffer. */
12486 if (current_kboard
== initial_kboard
)
12487 current_kboard
= dpyinfo
->kboard
;
12489 dpyinfo
->kboard
->reference_count
++;
12493 /* Put this display on the chain. */
12494 dpyinfo
->next
= x_display_list
;
12495 x_display_list
= dpyinfo
;
12497 /* Put it on x_display_name_list as well, to keep them parallel. */
12498 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
12499 x_display_name_list
);
12500 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12502 dpyinfo
->display
= dpy
;
12505 XSetAfterFunction (x_current_display
, x_trace_wire
);
12509 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
12510 + STRING_BYTES (XSTRING (Vsystem_name
))
12512 sprintf (dpyinfo
->x_id_name
, "%s@%s",
12513 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
12515 /* Figure out which modifier bits mean what. */
12516 x_find_modifier_meanings (dpyinfo
);
12518 /* Get the scroll bar cursor. */
12519 dpyinfo
->vertical_scroll_bar_cursor
12520 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
12522 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
12523 resource_name
, EMACS_CLASS
);
12524 #ifdef HAVE_XRMSETDATABASE
12525 XrmSetDatabase (dpyinfo
->display
, xrdb
);
12527 dpyinfo
->display
->db
= xrdb
;
12529 /* Put the rdb where we can find it in a way that works on
12531 dpyinfo
->xrdb
= xrdb
;
12533 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
12534 DefaultScreen (dpyinfo
->display
));
12535 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
12536 &dpyinfo
->n_planes
);
12537 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
12538 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
12539 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
12540 dpyinfo
->grabbed
= 0;
12541 dpyinfo
->reference_count
= 0;
12542 dpyinfo
->icon_bitmap_id
= -1;
12543 dpyinfo
->font_table
= NULL
;
12544 dpyinfo
->n_fonts
= 0;
12545 dpyinfo
->font_table_size
= 0;
12546 dpyinfo
->bitmaps
= 0;
12547 dpyinfo
->bitmaps_size
= 0;
12548 dpyinfo
->bitmaps_last
= 0;
12549 dpyinfo
->scratch_cursor_gc
= 0;
12550 dpyinfo
->mouse_face_mouse_frame
= 0;
12551 dpyinfo
->mouse_face_deferred_gc
= 0;
12552 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12553 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12554 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12555 dpyinfo
->mouse_face_window
= Qnil
;
12556 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
12557 dpyinfo
->mouse_face_defer
= 0;
12558 dpyinfo
->x_focus_frame
= 0;
12559 dpyinfo
->x_focus_event_frame
= 0;
12560 dpyinfo
->x_highlight_frame
= 0;
12561 dpyinfo
->image_cache
= make_image_cache ();
12564 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
12565 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
12566 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
12567 dpyinfo
->resy
= pixels
* 25.4 / mm
;
12568 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
12569 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
12570 dpyinfo
->resx
= pixels
* 25.4 / mm
;
12573 dpyinfo
->Xatom_wm_protocols
12574 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
12575 dpyinfo
->Xatom_wm_take_focus
12576 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
12577 dpyinfo
->Xatom_wm_save_yourself
12578 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
12579 dpyinfo
->Xatom_wm_delete_window
12580 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
12581 dpyinfo
->Xatom_wm_change_state
12582 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
12583 dpyinfo
->Xatom_wm_configure_denied
12584 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
12585 dpyinfo
->Xatom_wm_window_moved
12586 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
12587 dpyinfo
->Xatom_editres
12588 = XInternAtom (dpyinfo
->display
, "Editres", False
);
12589 dpyinfo
->Xatom_CLIPBOARD
12590 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
12591 dpyinfo
->Xatom_TIMESTAMP
12592 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
12593 dpyinfo
->Xatom_TEXT
12594 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
12595 dpyinfo
->Xatom_COMPOUND_TEXT
12596 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
12597 dpyinfo
->Xatom_DELETE
12598 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
12599 dpyinfo
->Xatom_MULTIPLE
12600 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
12601 dpyinfo
->Xatom_INCR
12602 = XInternAtom (dpyinfo
->display
, "INCR", False
);
12603 dpyinfo
->Xatom_EMACS_TMP
12604 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
12605 dpyinfo
->Xatom_TARGETS
12606 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
12607 dpyinfo
->Xatom_NULL
12608 = XInternAtom (dpyinfo
->display
, "NULL", False
);
12609 dpyinfo
->Xatom_ATOM_PAIR
12610 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
12611 /* For properties of font. */
12612 dpyinfo
->Xatom_PIXEL_SIZE
12613 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
12614 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
12615 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
12616 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
12617 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
12618 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
12619 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
12621 /* Ghostscript support. */
12622 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
12623 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
12625 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
12628 dpyinfo
->cut_buffers_initialized
= 0;
12630 connection
= ConnectionNumber (dpyinfo
->display
);
12631 dpyinfo
->connection
= connection
;
12636 null_bits
[0] = 0x00;
12638 dpyinfo
->null_pixel
12639 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12640 null_bits
, 1, 1, (long) 0, (long) 0,
12645 extern int gray_bitmap_width
, gray_bitmap_height
;
12646 extern unsigned char *gray_bitmap_bits
;
12648 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12650 gray_bitmap_width
, gray_bitmap_height
,
12651 (unsigned long) 1, (unsigned long) 0, 1);
12654 #ifdef subprocesses
12655 /* This is only needed for distinguishing keyboard and process input. */
12656 if (connection
!= 0)
12657 add_keyboard_wait_descriptor (connection
);
12660 #ifndef F_SETOWN_BUG
12662 #ifdef F_SETOWN_SOCK_NEG
12663 /* stdin is a socket here */
12664 fcntl (connection
, F_SETOWN
, -getpid ());
12665 #else /* ! defined (F_SETOWN_SOCK_NEG) */
12666 fcntl (connection
, F_SETOWN
, getpid ());
12667 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
12668 #endif /* ! defined (F_SETOWN) */
12669 #endif /* F_SETOWN_BUG */
12672 if (interrupt_input
)
12673 init_sigio (connection
);
12674 #endif /* ! defined (SIGIO) */
12677 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
12678 /* Make sure that we have a valid font for dialog boxes
12679 so that Xt does not crash. */
12681 Display
*dpy
= dpyinfo
->display
;
12682 XrmValue d
, fr
, to
;
12686 d
.addr
= (XPointer
)&dpy
;
12687 d
.size
= sizeof (Display
*);
12688 fr
.addr
= XtDefaultFont
;
12689 fr
.size
= sizeof (XtDefaultFont
);
12690 to
.size
= sizeof (Font
*);
12691 to
.addr
= (XPointer
)&font
;
12692 count
= x_catch_errors (dpy
);
12693 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
12695 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
12696 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
12697 x_uncatch_errors (dpy
, count
);
12707 /* Get rid of display DPYINFO, assuming all frames are already gone,
12708 and without sending any more commands to the X server. */
12711 x_delete_display (dpyinfo
)
12712 struct x_display_info
*dpyinfo
;
12714 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
12716 /* Discard this display from x_display_name_list and x_display_list.
12717 We can't use Fdelq because that can quit. */
12718 if (! NILP (x_display_name_list
)
12719 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12720 x_display_name_list
= XCDR (x_display_name_list
);
12725 tail
= x_display_name_list
;
12726 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12728 if (EQ (XCAR (XCDR (tail
)),
12729 dpyinfo
->name_list_element
))
12731 XCDR (tail
) = XCDR (XCDR (tail
));
12734 tail
= XCDR (tail
);
12738 if (x_display_list
== dpyinfo
)
12739 x_display_list
= dpyinfo
->next
;
12742 struct x_display_info
*tail
;
12744 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12745 if (tail
->next
== dpyinfo
)
12746 tail
->next
= tail
->next
->next
;
12749 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12750 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
12751 XrmDestroyDatabase (dpyinfo
->xrdb
);
12754 #ifdef MULTI_KBOARD
12755 if (--dpyinfo
->kboard
->reference_count
== 0)
12756 delete_kboard (dpyinfo
->kboard
);
12758 xfree (dpyinfo
->font_table
);
12759 xfree (dpyinfo
->x_id_name
);
12763 /* Set up use of X before we make the first connection. */
12765 static struct redisplay_interface x_redisplay_interface
=
12770 x_clear_end_of_line
,
12772 x_after_update_window_line
,
12773 x_update_window_begin
,
12774 x_update_window_end
,
12777 x_get_glyph_overhangs
,
12778 x_fix_overlapping_area
12784 rif
= &x_redisplay_interface
;
12786 clear_frame_hook
= x_clear_frame
;
12787 ins_del_lines_hook
= x_ins_del_lines
;
12788 change_line_highlight_hook
= x_change_line_highlight
;
12789 delete_glyphs_hook
= x_delete_glyphs
;
12790 ring_bell_hook
= XTring_bell
;
12791 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12792 set_terminal_modes_hook
= XTset_terminal_modes
;
12793 update_begin_hook
= x_update_begin
;
12794 update_end_hook
= x_update_end
;
12795 set_terminal_window_hook
= XTset_terminal_window
;
12796 read_socket_hook
= XTread_socket
;
12797 frame_up_to_date_hook
= XTframe_up_to_date
;
12798 reassert_line_highlight_hook
= XTreassert_line_highlight
;
12799 mouse_position_hook
= XTmouse_position
;
12800 frame_rehighlight_hook
= XTframe_rehighlight
;
12801 frame_raise_lower_hook
= XTframe_raise_lower
;
12802 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
12803 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
12804 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
12805 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
12806 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
12808 scroll_region_ok
= 1; /* we'll scroll partial frames */
12809 char_ins_del_ok
= 0; /* just as fast to write the line */
12810 line_ins_del_ok
= 1; /* we'll just blt 'em */
12811 fast_clear_end_of_line
= 1; /* X does this well */
12812 memory_below_frame
= 0; /* we don't remember what scrolls
12817 last_tool_bar_item
= -1;
12818 any_help_event_p
= 0;
12820 /* Try to use interrupt input; if we can't, then start polling. */
12821 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
12823 #ifdef USE_X_TOOLKIT
12824 XtToolkitInitialize ();
12825 Xt_app_con
= XtCreateApplicationContext ();
12826 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
12829 /* Note that there is no real way portable across R3/R4 to get the
12830 original error handler. */
12831 XSetErrorHandler (x_error_handler
);
12832 XSetIOErrorHandler (x_io_error_quitter
);
12834 /* Disable Window Change signals; they are handled by X events. */
12836 signal (SIGWINCH
, SIG_DFL
);
12837 #endif /* ! defined (SIGWINCH) */
12839 signal (SIGPIPE
, x_connection_signal
);
12846 staticpro (&x_error_message_string
);
12847 x_error_message_string
= Qnil
;
12849 staticpro (&x_display_name_list
);
12850 x_display_name_list
= Qnil
;
12852 staticpro (&last_mouse_scroll_bar
);
12853 last_mouse_scroll_bar
= Qnil
;
12855 staticpro (&Qvendor_specific_keysyms
);
12856 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
12858 staticpro (&last_mouse_press_frame
);
12859 last_mouse_press_frame
= Qnil
;
12861 staticpro (&help_echo
);
12863 staticpro (&previous_help_echo
);
12864 previous_help_echo
= Qnil
;
12866 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
12867 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
12868 For example, if a block cursor is over a tab, it will be drawn as\n\
12869 wide as that tab on the display.");
12870 x_stretch_cursor_p
= 0;
12872 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p
,
12873 "If not nil, Emacs uses toolkit scroll bars.");
12874 #if USE_TOOLKIT_SCROLL_BARS
12875 x_toolkit_scroll_bars_p
= 1;
12877 x_toolkit_scroll_bars_p
= 0;
12880 defsubr (&Sxt_process_timeouts
);
12881 staticpro (&last_mouse_motion_frame
);
12882 last_mouse_motion_frame
= Qnil
;
12885 #endif /* not HAVE_X_WINDOWS */