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 #else /* !USE_MOTIF i.e. use Xaw */
124 #include <X11/Xaw3d/Simple.h>
125 #include <X11/Xaw3d/Scrollbar.h>
126 #define ARROW_SCROLLBAR
127 #include <X11/Xaw3d/ScrollbarP.h>
128 #else /* !HAVE_XAW3D */
129 #include <X11/Xaw/Simple.h>
130 #include <X11/Xaw/Scrollbar.h>
131 #endif /* !HAVE_XAW3D */
133 #define XtNpickTop "pickTop"
134 #endif /* !XtNpickTop */
135 #endif /* !USE_MOTIF */
136 #endif /* USE_TOOLKIT_SCROLL_BARS */
138 #endif /* USE_X_TOOLKIT */
140 #ifndef USE_X_TOOLKIT
141 #define x_any_window_to_frame x_window_to_frame
142 #define x_top_window_to_frame x_window_to_frame
147 #ifndef XtNinitialState
148 #define XtNinitialState "initialState"
153 /* memmove will be defined as a macro in Xfuncs.h unless
154 <string.h> is included beforehand. The declaration for memmove in
155 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
160 #define min(a,b) ((a) < (b) ? (a) : (b))
163 #define max(a,b) ((a) > (b) ? (a) : (b))
166 #define abs(x) ((x) < 0 ? -(x) : (x))
168 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
171 /* Bitmaps for truncated lines. */
176 LEFT_TRUNCATION_BITMAP
,
177 RIGHT_TRUNCATION_BITMAP
,
178 OVERLAY_ARROW_BITMAP
,
179 CONTINUED_LINE_BITMAP
,
180 CONTINUATION_LINE_BITMAP
,
184 /* Bitmap drawn to indicate lines not displaying text if
185 `indicate-empty-lines' is non-nil. */
189 static unsigned char zv_bits
[] = {
190 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
192 /* An arrow like this: `<-'. */
195 #define left_height 8
196 static unsigned char left_bits
[] = {
197 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
199 /* Right truncation arrow bitmap `->'. */
201 #define right_width 8
202 #define right_height 8
203 static unsigned char right_bits
[] = {
204 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
206 /* Marker for continued lines. */
208 #define continued_width 8
209 #define continued_height 8
210 static unsigned char continued_bits
[] = {
211 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
213 /* Marker for continuation lines. */
215 #define continuation_width 8
216 #define continuation_height 8
217 static unsigned char continuation_bits
[] = {
218 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
220 /* Overlay arrow bitmap. */
226 static unsigned char ov_bits
[] = {
227 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
229 /* A triangular arrow. */
232 static unsigned char ov_bits
[] = {
233 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
237 extern Lisp_Object Qhelp_echo
;
240 /* Non-zero means Emacs uses toolkit scroll bars. */
242 int x_toolkit_scroll_bars_p
;
244 /* If a string, XTread_socket generates an event to display that string.
245 (The display is done in read_char.) */
247 static Lisp_Object help_echo
;
249 /* Temporary variable for XTread_socket. */
251 static Lisp_Object previous_help_echo
;
253 /* Non-zero means that a HELP_EVENT has been generated since Emacs
256 static int any_help_event_p
;
258 /* Non-zero means draw block and hollow cursor as wide as the glyph
259 under it. For example, if a block cursor is over a tab, it will be
260 drawn as wide as that tab on the display. */
262 int x_stretch_cursor_p
;
264 /* This is a chain of structures for all the X displays currently in
267 struct x_display_info
*x_display_list
;
269 /* This is a list of cons cells, each of the form (NAME
270 . FONT-LIST-CACHE), one for each element of x_display_list and in
271 the same order. NAME is the name of the frame. FONT-LIST-CACHE
272 records previous values returned by x-list-fonts. */
274 Lisp_Object x_display_name_list
;
276 /* Frame being updated by update_frame. This is declared in term.c.
277 This is set by update_begin and looked at by all the XT functions.
278 It is zero while not inside an update. In that case, the XT
279 functions assume that `selected_frame' is the frame to apply to. */
281 extern struct frame
*updating_frame
;
283 extern int waiting_for_input
;
285 /* This is a frame waiting to be auto-raised, within XTread_socket. */
287 struct frame
*pending_autoraise_frame
;
290 /* The application context for Xt use. */
291 XtAppContext Xt_app_con
;
292 static String Xt_default_resources
[] = {0};
293 #endif /* USE_X_TOOLKIT */
295 /* Nominal cursor position -- where to draw output.
296 HPOS and VPOS are window relative glyph matrix coordinates.
297 X and Y are window relative pixel coordinates. */
299 struct cursor_pos output_cursor
;
304 Formerly, we used PointerMotionHintMask (in standard_event_mask)
305 so that we would have to call XQueryPointer after each MotionNotify
306 event to ask for another such event. However, this made mouse tracking
307 slow, and there was a bug that made it eventually stop.
309 Simply asking for MotionNotify all the time seems to work better.
311 In order to avoid asking for motion events and then throwing most
312 of them away or busy-polling the server for mouse positions, we ask
313 the server for pointer motion hints. This means that we get only
314 one event per group of mouse movements. "Groups" are delimited by
315 other kinds of events (focus changes and button clicks, for
316 example), or by XQueryPointer calls; when one of these happens, we
317 get another MotionNotify event the next time the mouse moves. This
318 is at least as efficient as getting motion events when mouse
319 tracking is on, and I suspect only negligibly worse when tracking
322 /* Where the mouse was last time we reported a mouse event. */
324 FRAME_PTR last_mouse_frame
;
325 static XRectangle last_mouse_glyph
;
326 static Lisp_Object last_mouse_press_frame
;
328 /* The scroll bar in which the last X motion event occurred.
330 If the last X motion event occurred in a scroll bar, we set this so
331 XTmouse_position can know whether to report a scroll bar motion or
334 If the last X motion event didn't occur in a scroll bar, we set
335 this to Qnil, to tell XTmouse_position to return an ordinary motion
338 static Lisp_Object last_mouse_scroll_bar
;
340 /* This is a hack. We would really prefer that XTmouse_position would
341 return the time associated with the position it returns, but there
342 doesn't seem to be any way to wrest the time-stamp from the server
343 along with the position query. So, we just keep track of the time
344 of the last movement we received, and return that in hopes that
345 it's somewhat accurate. */
347 static Time last_mouse_movement_time
;
349 /* Incremented by XTread_socket whenever it really tries to read
353 static int volatile input_signal_count
;
355 static int input_signal_count
;
358 /* Used locally within XTread_socket. */
360 static int x_noop_count
;
362 /* Initial values of argv and argc. */
364 extern char **initial_argv
;
365 extern int initial_argc
;
367 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
369 /* Tells if a window manager is present or not. */
371 extern Lisp_Object Vx_no_window_manager
;
373 extern Lisp_Object Qface
, Qmouse_face
;
377 /* A mask of extra modifier bits to put into every keyboard char. */
379 extern int extra_keyboard_modifiers
;
381 static Lisp_Object Qvendor_specific_keysyms
;
383 extern XrmDatabase
x_load_resources ();
384 extern Lisp_Object
x_icon_type ();
387 /* Enumeration for overriding/changing the face to use for drawing
388 glyphs in x_draw_glyphs. */
390 enum draw_glyphs_face
400 static void x_update_window_end
P_ ((struct window
*, int));
401 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
402 void x_delete_display
P_ ((struct x_display_info
*));
403 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
405 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
407 static void set_output_cursor
P_ ((struct cursor_pos
*));
408 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
409 int *, int *, int *));
410 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
411 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
412 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
413 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
414 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
415 static void show_mouse_face
P_ ((struct x_display_info
*,
416 enum draw_glyphs_face
));
417 static int x_io_error_quitter
P_ ((Display
*));
418 int x_catch_errors
P_ ((Display
*));
419 void x_uncatch_errors
P_ ((Display
*, int));
420 void x_lower_frame
P_ ((struct frame
*));
421 void x_scroll_bar_clear
P_ ((struct frame
*));
422 int x_had_errors_p
P_ ((Display
*));
423 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
424 void x_raise_frame
P_ ((struct frame
*));
425 void x_set_window_size
P_ ((struct frame
*, int, int, int));
426 void x_wm_set_window_state
P_ ((struct frame
*, int));
427 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
428 void x_initialize
P_ ((void));
429 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
430 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
431 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
433 enum draw_glyphs_face
));
434 static void x_update_end
P_ ((struct frame
*));
435 static void XTframe_up_to_date
P_ ((struct frame
*));
436 static void XTreassert_line_highlight
P_ ((int, int));
437 static void x_change_line_highlight
P_ ((int, int, int, int));
438 static void XTset_terminal_modes
P_ ((void));
439 static void XTreset_terminal_modes
P_ ((void));
440 static void XTcursor_to
P_ ((int, int, int, int));
441 static void x_write_glyphs
P_ ((struct glyph
*, int));
442 static void x_clear_end_of_line
P_ ((int));
443 static void x_clear_frame
P_ ((void));
444 static void x_clear_cursor
P_ ((struct window
*));
445 static void frame_highlight
P_ ((struct frame
*));
446 static void frame_unhighlight
P_ ((struct frame
*));
447 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
448 static void XTframe_rehighlight
P_ ((struct frame
*));
449 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
450 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
451 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*));
452 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
454 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
455 static void expose_window_tree
P_ ((struct window
*, XRectangle
*));
456 static void expose_window
P_ ((struct window
*, XRectangle
*));
457 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
458 XRectangle
*, enum glyph_row_area
));
459 static void expose_line
P_ ((struct window
*, struct glyph_row
*,
461 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
462 static void x_update_window_cursor
P_ ((struct window
*, int));
463 static void x_erase_phys_cursor
P_ ((struct window
*));
464 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
465 static void x_draw_bitmap
P_ ((struct window
*, struct glyph_row
*,
468 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
470 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
471 static void x_draw_row_bitmaps
P_ ((struct window
*, struct glyph_row
*));
472 static void note_overwritten_text_cursor
P_ ((struct window
*, int, int));
473 static void x_flush
P_ ((struct frame
*f
));
476 /* Flush display of frame F, or of all frames if F is null. */
485 Lisp_Object rest
, frame
;
486 FOR_EACH_FRAME (rest
, frame
)
487 x_flush (XFRAME (frame
));
489 else if (FRAME_X_P (f
))
490 XFlush (FRAME_X_DISPLAY (f
));
495 /* Remove calls to XFlush by defining XFlush to an empty replacement.
496 Calls to XFlush should be unnecessary because the X output buffer
497 is flushed automatically as needed by calls to XPending,
498 XNextEvent, or XWindowEvent according to the XFlush man page.
499 XTread_socket calls XPending. Removing XFlush improves
502 #define XFlush(DISPLAY) (void) 0
505 /***********************************************************************
507 ***********************************************************************/
511 /* This is a function useful for recording debugging information about
512 the sequence of occurrences in this file. */
520 struct record event_record
[100];
522 int event_record_index
;
524 record_event (locus
, type
)
528 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
529 event_record_index
= 0;
531 event_record
[event_record_index
].locus
= locus
;
532 event_record
[event_record_index
].type
= type
;
533 event_record_index
++;
540 /* Return the struct x_display_info corresponding to DPY. */
542 struct x_display_info
*
543 x_display_info_for_display (dpy
)
546 struct x_display_info
*dpyinfo
;
548 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
549 if (dpyinfo
->display
== dpy
)
557 /***********************************************************************
558 Starting and ending an update
559 ***********************************************************************/
561 /* Start an update of frame F. This function is installed as a hook
562 for update_begin, i.e. it is called when update_begin is called.
563 This function is called prior to calls to x_update_window_begin for
564 each window being updated. Currently, there is nothing to do here
565 because all interesting stuff is done on a window basis. */
575 /* Start update of window W. Set the global variable updated_window
576 to the window being updated and set output_cursor to the cursor
580 x_update_window_begin (w
)
583 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
584 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
587 set_output_cursor (&w
->cursor
);
591 if (f
== display_info
->mouse_face_mouse_frame
)
593 /* Don't do highlighting for mouse motion during the update. */
594 display_info
->mouse_face_defer
= 1;
596 /* If F needs to be redrawn, simply forget about any prior mouse
598 if (FRAME_GARBAGED_P (f
))
599 display_info
->mouse_face_window
= Qnil
;
601 /* Can we tell that this update does not affect the window
602 where the mouse highlight is? If so, no need to turn off.
603 Likewise, don't do anything if the frame is garbaged;
604 in that case, the frame's current matrix that we would use
605 is all wrong, and we will redisplay that line anyway. */
606 if (!NILP (display_info
->mouse_face_window
)
607 && w
== XWINDOW (display_info
->mouse_face_window
))
611 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
612 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
615 if (i
< w
->desired_matrix
->nrows
)
616 clear_mouse_face (display_info
);
624 /* Draw a vertical window border to the right of window W if W doesn't
625 have vertical scroll bars. */
628 x_draw_vertical_border (w
)
631 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
633 /* Redraw borders between horizontally adjacent windows. Don't
634 do it for frames with vertical scroll bars because either the
635 right scroll bar of a window, or the left scroll bar of its
636 neighbor will suffice as a border. */
637 if (!WINDOW_RIGHTMOST_P (w
)
638 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
642 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
643 x1
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
);
646 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
647 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
652 /* End update of window W (which is equal to updated_window). Draw
653 vertical borders between horizontally adjacent windows, and display
654 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
655 pseudo-window in case we don't have X toolkit support. Such
656 windows don't have a cursor, so don't display it here. */
659 x_update_window_end (w
, cursor_on_p
)
663 if (!w
->pseudo_window_p
)
667 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
669 output_cursor
.x
, output_cursor
.y
);
670 x_draw_vertical_border (w
);
674 updated_window
= NULL
;
678 /* End update of frame F. This function is installed as a hook in
685 /* Mouse highlight may be displayed again. */
686 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
689 XFlush (FRAME_X_DISPLAY (f
));
694 /* This function is called from various places in xdisp.c whenever a
695 complete update has been performed. The global variable
696 updated_window is not available here. */
699 XTframe_up_to_date (f
)
704 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
705 if (dpyinfo
->mouse_face_deferred_gc
706 || f
== dpyinfo
->mouse_face_mouse_frame
)
709 if (dpyinfo
->mouse_face_mouse_frame
)
710 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
711 dpyinfo
->mouse_face_mouse_x
,
712 dpyinfo
->mouse_face_mouse_y
);
713 dpyinfo
->mouse_face_deferred_gc
= 0;
720 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
721 arrow bitmaps, or clear the areas where they would be displayed
722 before DESIRED_ROW is made current. The window being updated is
723 found in updated_window. This function It is called from
724 update_window_line only if it is known that there are differences
725 between bitmaps to be drawn between current row and DESIRED_ROW. */
728 x_after_update_window_line (desired_row
)
729 struct glyph_row
*desired_row
;
731 struct window
*w
= updated_window
;
735 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
738 x_draw_row_bitmaps (w
, desired_row
);
740 /* When a window has disappeared, make sure that no rest of
741 full-width rows stays visible in the internal border. */
742 if (windows_or_buffers_changed
)
744 struct frame
*f
= XFRAME (w
->frame
);
745 int width
= FRAME_INTERNAL_BORDER_WIDTH (f
);
746 int height
= desired_row
->visible_height
;
747 int x
= (window_box_right (w
, -1)
748 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
));
749 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
751 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
752 x
, y
, width
, height
, False
);
760 /* Draw the bitmap WHICH in one of the areas to the left or right of
761 window W. ROW is the glyph row for which to display the bitmap; it
762 determines the vertical position at which the bitmap has to be
766 x_draw_bitmap (w
, row
, which
)
768 struct glyph_row
*row
;
769 enum bitmap_type which
;
771 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
772 Display
*display
= FRAME_X_DISPLAY (f
);
773 Window window
= FRAME_X_WINDOW (f
);
777 GC gc
= f
->output_data
.x
->normal_gc
;
779 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
781 /* Must clip because of partially visible lines. */
782 x_clip_to_row (w
, row
, gc
, 1);
786 case LEFT_TRUNCATION_BITMAP
:
790 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
792 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
795 case OVERLAY_ARROW_BITMAP
:
799 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
801 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
804 case RIGHT_TRUNCATION_BITMAP
:
808 x
= window_box_right (w
, -1);
809 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
812 case CONTINUED_LINE_BITMAP
:
815 bits
= continued_bits
;
816 x
= window_box_right (w
, -1);
817 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
820 case CONTINUATION_LINE_BITMAP
:
821 wd
= continuation_width
;
822 h
= continuation_height
;
823 bits
= continuation_bits
;
824 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
826 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
833 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
835 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
842 /* Convert to frame coordinates. Set dy to the offset in the row to
843 start drawing the bitmap. */
844 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
845 dy
= (row
->height
- h
) / 2;
847 /* Draw the bitmap. I believe these small pixmaps can be cached
849 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
850 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
852 face
->background
, depth
);
853 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
854 XFreePixmap (display
, pixmap
);
855 XSetClipMask (display
, gc
, None
);
859 /* Draw flags bitmaps for glyph row ROW on window W. Call this
860 function with input blocked. */
863 x_draw_row_bitmaps (w
, row
)
865 struct glyph_row
*row
;
867 struct frame
*f
= XFRAME (w
->frame
);
868 enum bitmap_type bitmap
;
870 int header_line_height
= -1;
872 xassert (interrupt_input_blocked
);
874 /* If row is completely invisible, because of vscrolling, we
875 don't have to draw anything. */
876 if (row
->visible_height
<= 0)
879 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
880 PREPARE_FACE_FOR_DISPLAY (f
, face
);
882 /* Decide which bitmap to draw at the left side. */
883 if (row
->overlay_arrow_p
)
884 bitmap
= OVERLAY_ARROW_BITMAP
;
885 else if (row
->truncated_on_left_p
)
886 bitmap
= LEFT_TRUNCATION_BITMAP
;
887 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
888 bitmap
= CONTINUATION_LINE_BITMAP
;
889 else if (row
->indicate_empty_line_p
)
890 bitmap
= ZV_LINE_BITMAP
;
894 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
896 if (bitmap
== NO_BITMAP
897 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
898 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
900 /* If W has a vertical border to its left, don't draw over it. */
901 int border
= ((XFASTINT (w
->left
) > 0
902 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
904 int left
= window_box_left (w
, -1);
906 if (header_line_height
< 0)
907 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
909 /* In case the same realized face is used for bitmap areas and
910 for something displayed in the text (e.g. face `region' on
911 mono-displays, the fill style may have been changed to
912 FillSolid in x_draw_glyph_string_background. */
914 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
916 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
918 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
921 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
923 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
925 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - border
,
926 row
->visible_height
);
928 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
931 /* Draw the left bitmap. */
932 if (bitmap
!= NO_BITMAP
)
933 x_draw_bitmap (w
, row
, bitmap
);
935 /* Decide which bitmap to draw at the right side. */
936 if (row
->truncated_on_right_p
)
937 bitmap
= RIGHT_TRUNCATION_BITMAP
;
938 else if (row
->continued_p
)
939 bitmap
= CONTINUED_LINE_BITMAP
;
943 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
945 if (bitmap
== NO_BITMAP
946 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
)
947 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
949 int right
= window_box_right (w
, -1);
951 if (header_line_height
< 0)
952 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
954 /* In case the same realized face is used for bitmap areas and
955 for something displayed in the text (e.g. face `region' on
956 mono-displays, the fill style may have been changed to
957 FillSolid in x_draw_glyph_string_background. */
959 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
961 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
962 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
965 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
967 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
),
968 row
->visible_height
);
970 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
973 /* Draw the right bitmap. */
974 if (bitmap
!= NO_BITMAP
)
975 x_draw_bitmap (w
, row
, bitmap
);
979 /***********************************************************************
981 ***********************************************************************/
983 /* External interface to control of standout mode. Not used for X
984 frames. Aborts when called. */
987 XTreassert_line_highlight (new, vpos
)
994 /* Call this when about to modify line at position VPOS and change
995 whether it is highlighted. Not used for X frames. Aborts when
999 x_change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
1000 int new_highlight
, vpos
, y
, first_unused_hpos
;
1006 /* This is called when starting Emacs and when restarting after
1007 suspend. When starting Emacs, no X window is mapped. And nothing
1008 must be done to Emacs's own window if it is suspended (though that
1012 XTset_terminal_modes ()
1016 /* This is called when exiting or suspending Emacs. Exiting will make
1017 the X-windows go away, and suspending requires no action. */
1020 XTreset_terminal_modes ()
1026 /***********************************************************************
1028 ***********************************************************************/
1030 /* Set the global variable output_cursor to CURSOR. All cursor
1031 positions are relative to updated_window. */
1034 set_output_cursor (cursor
)
1035 struct cursor_pos
*cursor
;
1037 output_cursor
.hpos
= cursor
->hpos
;
1038 output_cursor
.vpos
= cursor
->vpos
;
1039 output_cursor
.x
= cursor
->x
;
1040 output_cursor
.y
= cursor
->y
;
1044 /* Set a nominal cursor position.
1046 HPOS and VPOS are column/row positions in a window glyph matrix. X
1047 and Y are window text area relative pixel positions.
1049 If this is done during an update, updated_window will contain the
1050 window that is being updated and the position is the future output
1051 cursor position for that window. If updated_window is null, use
1052 selected_window and display the cursor at the given position. */
1055 XTcursor_to (vpos
, hpos
, y
, x
)
1056 int vpos
, hpos
, y
, x
;
1060 /* If updated_window is not set, work on selected_window. */
1064 w
= XWINDOW (selected_window
);
1066 /* Set the output cursor. */
1067 output_cursor
.hpos
= hpos
;
1068 output_cursor
.vpos
= vpos
;
1069 output_cursor
.x
= x
;
1070 output_cursor
.y
= y
;
1072 /* If not called as part of an update, really display the cursor.
1073 This will also set the cursor position of W. */
1074 if (updated_window
== NULL
)
1077 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1078 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1085 /***********************************************************************
1087 ***********************************************************************/
1089 /* Function prototypes of this page. */
1091 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1094 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1095 int, XChar2b
*, int));
1096 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1097 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1098 static void x_append_glyph
P_ ((struct it
*));
1099 static void x_append_composite_glyph
P_ ((struct it
*));
1100 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1102 static void x_produce_glyphs
P_ ((struct it
*));
1103 static void x_produce_image_glyph
P_ ((struct it
*it
));
1106 /* Return a pointer to per-char metric information in FONT of a
1107 character pointed by B which is a pointer to an XChar2b. */
1109 #define PER_CHAR_METRIC(font, b) \
1111 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1112 + (((font)->min_byte1 || (font)->max_byte1) \
1113 ? (((b)->byte1 - (font)->min_byte1) \
1114 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1116 : &((font)->max_bounds))
1119 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1120 If CHAR2B is not contained in FONT, the font's default character
1121 metric is returned. */
1123 static INLINE XCharStruct
*
1124 x_per_char_metric (font
, char2b
)
1128 /* The result metric information. */
1129 XCharStruct
*pcm
= NULL
;
1131 xassert (font
&& char2b
);
1133 if (font
->per_char
!= NULL
)
1135 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1137 /* min_char_or_byte2 specifies the linear character index
1138 corresponding to the first element of the per_char array,
1139 max_char_or_byte2 is the index of the last character. A
1140 character with non-zero CHAR2B->byte1 is not in the font.
1141 A character with byte2 less than min_char_or_byte2 or
1142 greater max_char_or_byte2 is not in the font. */
1143 if (char2b
->byte1
== 0
1144 && char2b
->byte2
>= font
->min_char_or_byte2
1145 && char2b
->byte2
<= font
->max_char_or_byte2
)
1146 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1150 /* If either min_byte1 or max_byte1 are nonzero, both
1151 min_char_or_byte2 and max_char_or_byte2 are less than
1152 256, and the 2-byte character index values corresponding
1153 to the per_char array element N (counting from 0) are:
1155 byte1 = N/D + min_byte1
1156 byte2 = N\D + min_char_or_byte2
1160 D = max_char_or_byte2 - min_char_or_byte2 + 1
1161 / = integer division
1162 \ = integer modulus */
1163 if (char2b
->byte1
>= font
->min_byte1
1164 && char2b
->byte1
<= font
->max_byte1
1165 && char2b
->byte2
>= font
->min_char_or_byte2
1166 && char2b
->byte2
<= font
->max_char_or_byte2
)
1168 pcm
= (font
->per_char
1169 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1170 * (char2b
->byte1
- font
->min_byte1
))
1171 + (char2b
->byte2
- font
->min_char_or_byte2
));
1177 /* If the per_char pointer is null, all glyphs between the first
1178 and last character indexes inclusive have the same
1179 information, as given by both min_bounds and max_bounds. */
1180 if (char2b
->byte2
>= font
->min_char_or_byte2
1181 && char2b
->byte2
<= font
->max_char_or_byte2
)
1182 pcm
= &font
->max_bounds
;
1186 if (pcm
== NULL
|| pcm
->width
== 0)
1188 /* Character not contained in the font. FONT->default_char
1189 gives the character that will be printed. FONT->default_char
1190 is a 16-bit character code with byte1 in the most significant
1191 byte and byte2 in the least significant byte. */
1192 XChar2b default_char
;
1193 default_char
.byte1
= (font
->default_char
>> BITS_PER_CHAR
) & 0xff;
1194 default_char
.byte2
= font
->default_char
& 0xff;
1196 /* Avoid an endless recursion if FONT->default_char itself
1197 hasn't per char metrics. handa@etl.go.jp reports that some
1198 fonts have this problem. */
1199 if (default_char
.byte1
!= char2b
->byte1
1200 || default_char
.byte2
!= char2b
->byte2
)
1201 pcm
= x_per_char_metric (font
, &default_char
);
1203 pcm
= &font
->max_bounds
;
1210 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1211 the two-byte form of C. Encoding is returned in *CHAR2B. */
1214 x_encode_char (c
, char2b
, font_info
)
1217 struct font_info
*font_info
;
1219 int charset
= CHAR_CHARSET (c
);
1220 XFontStruct
*font
= font_info
->font
;
1222 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1223 This may be either a program in a special encoder language or a
1225 if (font_info
->font_encoder
)
1227 /* It's a program. */
1228 struct ccl_program
*ccl
= font_info
->font_encoder
;
1230 if (CHARSET_DIMENSION (charset
) == 1)
1232 ccl
->reg
[0] = charset
;
1233 ccl
->reg
[1] = char2b
->byte2
;
1237 ccl
->reg
[0] = charset
;
1238 ccl
->reg
[1] = char2b
->byte1
;
1239 ccl
->reg
[2] = char2b
->byte2
;
1242 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1244 /* We assume that MSBs are appropriately set/reset by CCL
1246 if (font
->max_byte1
== 0) /* 1-byte font */
1247 char2b
->byte2
= ccl
->reg
[1];
1249 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1251 else if (font_info
->encoding
[charset
])
1253 /* Fixed encoding scheme. See fontset.h for the meaning of the
1254 encoding numbers. */
1255 int enc
= font_info
->encoding
[charset
];
1257 if ((enc
== 1 || enc
== 2)
1258 && CHARSET_DIMENSION (charset
) == 2)
1259 char2b
->byte1
|= 0x80;
1261 if (enc
== 1 || enc
== 3)
1262 char2b
->byte2
|= 0x80;
1267 /* Get face and two-byte form of character C in face FACE_ID on frame
1268 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1269 means we want to display multibyte text. Value is a pointer to a
1270 realized face that is ready for display. */
1272 static INLINE
struct face
*
1273 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1279 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1283 /* Unibyte case. We don't have to encode, but we have to make
1284 sure to use a face suitable for unibyte. */
1288 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, -1))
1290 face_id
= FACE_FOR_CHARSET (f
, face_id
, -1);
1291 face
= FACE_FROM_ID (f
, face_id
);
1294 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1296 /* Case of ASCII in a face known to fit ASCII. */
1302 int c1
, c2
, charset
;
1304 /* Split characters into bytes. If c2 is -1 afterwards, C is
1305 really a one-byte character so that byte1 is zero. */
1306 SPLIT_CHAR (c
, charset
, c1
, c2
);
1308 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1310 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1312 /* Get the face for displaying C. If `face' is not suitable for
1313 charset, get the one that fits. (This can happen for the
1314 translations of a composition where the glyph
1315 specifies a face for the first component, but the other
1316 components have a different charset.) */
1317 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, charset
))
1319 face_id
= FACE_FOR_CHARSET (f
, face_id
, charset
);
1320 face
= FACE_FROM_ID (f
, face_id
);
1323 /* Maybe encode the character in *CHAR2B. */
1324 if (charset
!= CHARSET_ASCII
)
1326 struct font_info
*font_info
1327 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1330 x_encode_char (c
, char2b
, font_info
);
1331 if (charset
== charset_latin_iso8859_1
)
1333 xassert (((XFontStruct
*) font_info
->font
)->max_char_or_byte2
1335 char2b
->byte2
|= 0x80;
1341 /* Make sure X resources of the face are allocated. */
1342 xassert (face
!= NULL
);
1343 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1349 /* Get face and two-byte form of character glyph GLYPH on frame F.
1350 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1351 a pointer to a realized face that is ready for display. */
1353 static INLINE
struct face
*
1354 x_get_glyph_face_and_encoding (f
, glyph
, char2b
)
1356 struct glyph
*glyph
;
1361 xassert (glyph
->type
== CHAR_GLYPH
);
1362 face
= FACE_FROM_ID (f
, glyph
->u
.ch
.face_id
);
1364 if (!glyph
->multibyte_p
)
1366 /* Unibyte case. We don't have to encode, but we have to make
1367 sure to use a face suitable for unibyte. */
1369 char2b
->byte2
= glyph
->u
.ch
.code
;
1371 else if (glyph
->u
.ch
.code
< 128
1372 && glyph
->u
.ch
.face_id
< BASIC_FACE_ID_SENTINEL
)
1374 /* Case of ASCII in a face known to fit ASCII. */
1376 char2b
->byte2
= glyph
->u
.ch
.code
;
1380 int c1
, c2
, charset
;
1382 /* Split characters into bytes. If c2 is -1 afterwards, C is
1383 really a one-byte character so that byte1 is zero. */
1384 SPLIT_CHAR (glyph
->u
.ch
.code
, charset
, c1
, c2
);
1386 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1388 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1390 /* Maybe encode the character in *CHAR2B. */
1391 if (charset
!= CHARSET_ASCII
)
1393 struct font_info
*font_info
1394 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1397 x_encode_char (glyph
->u
.ch
.code
, char2b
, font_info
);
1398 if (charset
== charset_latin_iso8859_1
)
1399 char2b
->byte2
|= 0x80;
1404 /* Make sure X resources of the face are allocated. */
1405 xassert (face
!= NULL
);
1406 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1411 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1412 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1418 struct glyph
*glyph
;
1419 enum glyph_row_area area
= it
->area
;
1421 xassert (it
->glyph_row
);
1422 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1424 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1425 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1427 /* Play it safe. If sub-structures of the glyph are not all the
1428 same size, it otherwise be that some bits stay set. This
1429 would prevent a comparison with GLYPH_EQUAL_P. */
1432 glyph
->type
= CHAR_GLYPH
;
1433 glyph
->pixel_width
= it
->pixel_width
;
1434 glyph
->u
.ch
.code
= it
->char_to_display
;
1435 glyph
->u
.ch
.face_id
= it
->face_id
;
1436 glyph
->charpos
= CHARPOS (it
->position
);
1437 glyph
->object
= it
->object
;
1438 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1439 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1440 glyph
->voffset
= it
->voffset
;
1441 glyph
->multibyte_p
= it
->multibyte_p
;
1442 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1443 || it
->phys_descent
> it
->descent
);
1444 ++it
->glyph_row
->used
[area
];
1448 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1449 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1452 x_append_composite_glyph (it
)
1455 struct glyph
*glyph
;
1456 enum glyph_row_area area
= it
->area
;
1458 xassert (it
->glyph_row
);
1460 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1461 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1463 /* Play it safe. If sub-structures of the glyph are not all the
1464 same size, it otherwise be that some bits stay set. This
1465 would prevent a comparison with GLYPH_EQUAL_P. */
1468 glyph
->type
= COMPOSITE_GLYPH
;
1469 glyph
->pixel_width
= it
->pixel_width
;
1470 glyph
->u
.cmp
.id
= it
->cmp_id
;
1471 glyph
->u
.cmp
.face_id
= it
->face_id
;
1472 glyph
->charpos
= CHARPOS (it
->position
);
1473 glyph
->object
= it
->object
;
1474 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1475 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1476 glyph
->voffset
= it
->voffset
;
1477 glyph
->multibyte_p
= it
->multibyte_p
;
1478 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1479 || it
->phys_descent
> it
->descent
);
1480 ++it
->glyph_row
->used
[area
];
1485 /* Change IT->ascent and IT->height according to the setting of
1489 take_vertical_position_into_account (it
)
1494 if (it
->voffset
< 0)
1495 /* Increase the ascent so that we can display the text higher
1497 it
->ascent
+= abs (it
->voffset
);
1499 /* Increase the descent so that we can display the text lower
1501 it
->descent
+= it
->voffset
;
1506 /* Produce glyphs/get display metrics for the image IT is loaded with.
1507 See the description of struct display_iterator in dispextern.h for
1508 an overview of struct display_iterator. */
1511 x_produce_image_glyph (it
)
1517 xassert (it
->what
== IT_IMAGE
);
1519 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1520 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1523 /* Make sure X resources of the face and image are loaded. */
1524 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1525 prepare_image_for_display (it
->f
, img
);
1527 it
->ascent
= it
->phys_ascent
= IMAGE_ASCENT (img
);
1528 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->margin
- it
->ascent
;
1529 it
->pixel_width
= img
->width
+ 2 * img
->margin
;
1533 if (face
->box
!= FACE_NO_BOX
)
1535 it
->ascent
+= face
->box_line_width
;
1536 it
->descent
+= face
->box_line_width
;
1538 if (it
->start_of_box_run_p
)
1539 it
->pixel_width
+= face
->box_line_width
;
1540 if (it
->end_of_box_run_p
)
1541 it
->pixel_width
+= face
->box_line_width
;
1544 take_vertical_position_into_account (it
);
1548 struct glyph
*glyph
;
1549 enum glyph_row_area area
= it
->area
;
1551 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1552 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1554 glyph
->type
= IMAGE_GLYPH
;
1555 glyph
->u
.img
.id
= img
->id
;
1556 glyph
->u
.img
.face_id
= it
->face_id
;
1557 glyph
->pixel_width
= it
->pixel_width
;
1558 glyph
->charpos
= CHARPOS (it
->position
);
1559 glyph
->object
= it
->object
;
1560 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1561 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1562 glyph
->voffset
= it
->voffset
;
1563 glyph
->multibyte_p
= it
->multibyte_p
;
1564 ++it
->glyph_row
->used
[area
];
1570 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1571 of the glyph, WIDTH and HEIGHT are the width and height of the
1572 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1573 ascent of the glyph (0 <= ASCENT <= 1). */
1576 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1582 struct glyph
*glyph
;
1583 enum glyph_row_area area
= it
->area
;
1585 xassert (ascent
>= 0 && ascent
<= 1);
1587 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1588 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1590 glyph
->type
= STRETCH_GLYPH
;
1591 glyph
->u
.stretch
.ascent
= height
* ascent
;
1592 glyph
->u
.stretch
.height
= height
;
1593 glyph
->u
.stretch
.face_id
= it
->face_id
;
1594 glyph
->pixel_width
= width
;
1595 glyph
->charpos
= CHARPOS (it
->position
);
1596 glyph
->object
= object
;
1597 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1598 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1599 glyph
->voffset
= it
->voffset
;
1600 glyph
->multibyte_p
= it
->multibyte_p
;
1601 ++it
->glyph_row
->used
[area
];
1606 /* Produce a stretch glyph for iterator IT. IT->object is the value
1607 of the glyph property displayed. The value must be a list
1608 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1611 1. `:width WIDTH' specifies that the space should be WIDTH *
1612 canonical char width wide. WIDTH may be an integer or floating
1615 2. `:relative-width FACTOR' specifies that the width of the stretch
1616 should be computed from the width of the first character having the
1617 `glyph' property, and should be FACTOR times that width.
1619 3. `:align-to HPOS' specifies that the space should be wide enough
1620 to reach HPOS, a value in canonical character units.
1622 Exactly one of the above pairs must be present.
1624 4. `:height HEIGHT' specifies that the height of the stretch produced
1625 should be HEIGHT, measured in canonical character units.
1627 5. `:relative-height FACTOR' specifies that the height of the the
1628 stretch should be FACTOR times the height of the characters having
1631 Either none or exactly one of 4 or 5 must be present.
1633 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1634 of the stretch should be used for the ascent of the stretch.
1635 ASCENT must be in the range 0 <= ASCENT <= 100. */
1638 ((INTEGERP (X) || FLOATP (X)) \
1644 x_produce_stretch_glyph (it
)
1647 /* (space :width WIDTH :height HEIGHT. */
1648 extern Lisp_Object QCwidth
, QCheight
, QCascent
, Qspace
;
1649 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1650 extern Lisp_Object QCalign_to
;
1651 Lisp_Object prop
, plist
;
1652 double width
= 0, height
= 0, ascent
= 0;
1653 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1654 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1656 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1658 /* List should start with `space'. */
1659 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1660 plist
= XCDR (it
->object
);
1662 /* Compute the width of the stretch. */
1663 if (prop
= Fplist_get (plist
, QCwidth
),
1665 /* Absolute width `:width WIDTH' specified and valid. */
1666 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1667 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1670 /* Relative width `:relative-width FACTOR' specified and valid.
1671 Compute the width of the characters having the `glyph'
1674 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1677 if (it
->multibyte_p
)
1679 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1680 - IT_BYTEPOS (*it
));
1681 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1684 it2
.c
= *p
, it2
.len
= 1;
1686 it2
.glyph_row
= NULL
;
1687 it2
.what
= IT_CHARACTER
;
1688 x_produce_glyphs (&it2
);
1689 width
= NUMVAL (prop
) * it2
.pixel_width
;
1691 else if (prop
= Fplist_get (plist
, QCalign_to
),
1693 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1695 /* Nothing specified -> width defaults to canonical char width. */
1696 width
= CANON_X_UNIT (it
->f
);
1698 /* Compute height. */
1699 if (prop
= Fplist_get (plist
, QCheight
),
1701 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1702 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1704 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1706 height
= FONT_HEIGHT (font
);
1708 /* Compute percentage of height used for ascent. If
1709 `:ascent ASCENT' is present and valid, use that. Otherwise,
1710 derive the ascent from the font in use. */
1711 if (prop
= Fplist_get (plist
, QCascent
),
1712 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1713 ascent
= NUMVAL (prop
) / 100.0;
1715 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1724 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1725 if (!STRINGP (object
))
1726 object
= it
->w
->buffer
;
1727 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1730 it
->pixel_width
= width
;
1731 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1732 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1735 if (face
->box
!= FACE_NO_BOX
)
1737 it
->ascent
+= face
->box_line_width
;
1738 it
->descent
+= face
->box_line_width
;
1740 if (it
->start_of_box_run_p
)
1741 it
->pixel_width
+= face
->box_line_width
;
1742 if (it
->end_of_box_run_p
)
1743 it
->pixel_width
+= face
->box_line_width
;
1746 take_vertical_position_into_account (it
);
1749 /* Return proper value to be used as baseline offset of font that has
1750 ASCENT and DESCENT to draw characters by the font at the vertical
1751 center of the line of frame F.
1753 Here, out task is to find the value of BOFF in the following figure;
1755 -------------------------+-----------+-
1756 -+-+---------+-+ | |
1758 | | | | F_ASCENT F_HEIGHT
1761 | | |-|-+------+-----------|------- baseline
1763 | |---------|-+-+ | |
1765 -+-+---------+-+ F_DESCENT |
1766 -------------------------+-----------+-
1768 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1769 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1770 DESCENT = FONT->descent
1771 HEIGHT = FONT_HEIGHT (FONT)
1772 F_DESCENT = (F->output_data.x->font->descent
1773 - F->output_data.x->baseline_offset)
1774 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1777 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1779 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1780 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1782 /* Produce glyphs/get display metrics for the display element IT is
1783 loaded with. See the description of struct display_iterator in
1784 dispextern.h for an overview of struct display_iterator. */
1787 x_produce_glyphs (it
)
1790 if (it
->what
== IT_CHARACTER
)
1796 int font_not_found_p
;
1797 struct font_info
*font_info
;
1798 int boff
; /* baseline offset */
1800 /* Maybe translate single-byte characters to multibyte. */
1801 it
->char_to_display
= it
->c
;
1802 if (unibyte_display_via_language_environment
1803 && SINGLE_BYTE_CHAR_P (it
->c
)
1806 && !NILP (Vnonascii_translation_table
))))
1808 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1809 it
->charset
= CHAR_CHARSET (it
->char_to_display
);
1812 /* Get face and font to use. Encode IT->char_to_display. */
1813 face
= x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1814 it
->face_id
, &char2b
,
1818 /* When no suitable font found, use the default font. */
1819 font_not_found_p
= font
== NULL
;
1820 if (font_not_found_p
)
1822 font
= FRAME_FONT (it
->f
);
1823 boff
= it
->f
->output_data
.x
->baseline_offset
;
1828 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
1829 boff
= font_info
->baseline_offset
;
1830 if (font_info
->vertical_centering
)
1831 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
1834 if (it
->char_to_display
>= ' '
1835 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1837 /* Either unibyte or ASCII. */
1842 pcm
= x_per_char_metric (font
, &char2b
);
1843 it
->ascent
= font
->ascent
+ boff
;
1844 it
->descent
= font
->descent
- boff
;
1845 it
->phys_ascent
= pcm
->ascent
+ boff
;
1846 it
->phys_descent
= pcm
->descent
- boff
;
1847 it
->pixel_width
= pcm
->width
;
1849 /* If this is a space inside a region of text with
1850 `space-width' property, change its width. */
1851 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1853 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1855 /* If face has a box, add the box thickness to the character
1856 height. If character has a box line to the left and/or
1857 right, add the box line width to the character's width. */
1858 if (face
->box
!= FACE_NO_BOX
)
1860 int thick
= face
->box_line_width
;
1862 it
->ascent
+= thick
;
1863 it
->descent
+= thick
;
1865 if (it
->start_of_box_run_p
)
1866 it
->pixel_width
+= thick
;
1867 if (it
->end_of_box_run_p
)
1868 it
->pixel_width
+= thick
;
1871 /* If face has an overline, add the height of the overline
1872 (1 pixel) and a 1 pixel margin to the character height. */
1873 if (face
->overline_p
)
1876 take_vertical_position_into_account (it
);
1878 /* If we have to actually produce glyphs, do it. */
1883 /* Translate a space with a `space-width' property
1884 into a stretch glyph. */
1885 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1886 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1887 it
->ascent
+ it
->descent
, ascent
);
1890 x_append_glyph (it
);
1892 /* If characters with lbearing or rbearing are displayed
1893 in this line, record that fact in a flag of the
1894 glyph row. This is used to optimize X output code. */
1895 if (pcm
->lbearing
< 0
1896 || pcm
->rbearing
> pcm
->width
)
1897 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1900 else if (it
->char_to_display
== '\n')
1902 /* A newline has no width but we need the height of the line. */
1903 it
->pixel_width
= 0;
1905 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1906 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1908 if (face
->box
!= FACE_NO_BOX
)
1910 int thick
= face
->box_line_width
;
1911 it
->ascent
+= thick
;
1912 it
->descent
+= thick
;
1915 else if (it
->char_to_display
== '\t')
1917 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1918 int x
= (it
->current_x
1920 + it
->continuation_lines_width
);
1921 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1923 it
->pixel_width
= next_tab_x
- x
;
1925 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1926 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1930 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1931 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1932 it
->ascent
+ it
->descent
, ascent
);
1937 /* A multi-byte character. Assume that the display width of the
1938 character is the width of the character multiplied by the
1939 width of the font. */
1941 /* If we found a font, this font should give us the right
1942 metrics. If we didn't find a font, use the frame's
1943 default font and calculate the width of the character
1944 from the charset width; this is what old redisplay code
1946 pcm
= x_per_char_metric (font
, &char2b
);
1947 it
->pixel_width
= pcm
->width
;
1948 if (font_not_found_p
)
1949 it
->pixel_width
*= CHARSET_WIDTH (it
->charset
);
1951 it
->ascent
= font
->ascent
+ boff
;
1952 it
->descent
= font
->descent
- boff
;
1953 it
->phys_ascent
= pcm
->ascent
+ boff
;
1954 it
->phys_descent
= pcm
->descent
- boff
;
1956 && (pcm
->lbearing
< 0
1957 || pcm
->rbearing
> pcm
->width
))
1958 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1960 if (face
->box
!= FACE_NO_BOX
)
1962 int thick
= face
->box_line_width
;
1963 it
->ascent
+= thick
;
1964 it
->descent
+= thick
;
1966 if (it
->start_of_box_run_p
)
1967 it
->pixel_width
+= thick
;
1968 if (it
->end_of_box_run_p
)
1969 it
->pixel_width
+= thick
;
1972 /* If face has an overline, add the height of the overline
1973 (1 pixel) and a 1 pixel margin to the character height. */
1974 if (face
->overline_p
)
1977 take_vertical_position_into_account (it
);
1980 x_append_glyph (it
);
1983 else if (it
->what
== IT_COMPOSITION
)
1985 /* Note: A composition is represented as one glyph in the
1986 glyph matrix. There are no padding glyphs. */
1991 int font_not_found_p
;
1992 struct font_info
*font_info
;
1993 int boff
; /* baseline offset */
1994 struct composition
*cmp
= composition_table
[it
->cmp_id
];
1996 /* Maybe translate single-byte characters to multibyte. */
1997 it
->char_to_display
= it
->c
;
1998 if (unibyte_display_via_language_environment
1999 && SINGLE_BYTE_CHAR_P (it
->c
)
2002 && !NILP (Vnonascii_translation_table
))))
2004 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2005 it
->charset
= CHAR_CHARSET (it
->char_to_display
);
2008 /* Get face and font to use. Encode IT->char_to_display. */
2009 face
= x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2010 it
->face_id
, &char2b
,
2014 /* When no suitable font found, use the default font. */
2015 font_not_found_p
= font
== NULL
;
2016 if (font_not_found_p
)
2018 font
= FRAME_FONT (it
->f
);
2019 boff
= it
->f
->output_data
.x
->baseline_offset
;
2024 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2025 boff
= font_info
->baseline_offset
;
2026 if (font_info
->vertical_centering
)
2027 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2030 /* There are no padding glyphs, so there is only one glyph to
2031 produce for the composition. Important is that pixel_width,
2032 ascent and descent are the values of what is drawn by
2033 draw_glyphs (i.e. the values of the overall glyphs composed). */
2036 /* If we have not yet calculated pixel size data of glyphs of
2037 the composition for the current face font, calculate them
2038 now. Theoretically, we have to check all fonts for the
2039 glyphs, but that requires much time and memory space. So,
2040 here we check only the font of the first glyph. This leads
2041 to incorrect display very rarely, and C-l (recenter) can
2042 correct the display anyway. */
2043 if (cmp
->font
!= (void *) font
)
2045 /* Ascent and descent of the font of the first character of
2046 this composition (adjusted by baseline offset). Ascent
2047 and descent of overall glyphs should not be less than
2048 them respectively. */
2049 int font_ascent
= font
->ascent
+ boff
;
2050 int font_descent
= font
->descent
- boff
;
2051 /* Bounding box of the overall glyphs. */
2052 int leftmost
, rightmost
, lowest
, highest
;
2055 cmp
->font
= (void *) font
;
2057 /* Initialize the bounding box. */
2058 pcm
= x_per_char_metric (font
, &char2b
);
2060 rightmost
= pcm
->width
;
2061 lowest
= - pcm
->descent
+ boff
;
2062 highest
= pcm
->ascent
+ boff
;
2064 && font_info
->default_ascent
2065 && CHAR_TABLE_P (Vuse_default_ascent
)
2066 && !NILP (Faref (Vuse_default_ascent
,
2067 make_number (it
->char_to_display
))))
2068 highest
= font_info
->default_ascent
+ boff
;
2070 /* Draw the first glyph at the normal position. It may be
2071 shifted to right later if some other glyphs are drawn at
2073 cmp
->offsets
[0] = 0;
2074 cmp
->offsets
[1] = boff
;
2076 /* Set cmp->offsets for the remaining glyphs. */
2077 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2079 int left
, right
, btm
, top
;
2080 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2082 face
= x_get_char_face_and_encoding (it
->f
, ch
,
2083 it
->face_id
, &char2b
,
2088 font
= FRAME_FONT (it
->f
);
2089 boff
= it
->f
->output_data
.x
->baseline_offset
;
2095 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2096 boff
= font_info
->baseline_offset
;
2097 if (font_info
->vertical_centering
)
2098 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2101 pcm
= x_per_char_metric (font
, &char2b
);
2103 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2105 /* Relative composition with or without
2107 left
= (leftmost
+ rightmost
- pcm
->width
) / 2;
2108 btm
= - pcm
->descent
+ boff
;
2109 if (font_info
&& font_info
->relative_compose
2110 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2111 || NILP (Faref (Vignore_relative_composition
,
2112 make_number (ch
)))))
2116 >= font_info
->relative_compose
)
2117 /* One extra pixel between two glyphs. */
2119 else if (pcm
->ascent
<= 0)
2120 /* One extra pixel between two glyphs. */
2121 btm
= lowest
- 1 - pcm
->ascent
- pcm
->descent
;
2126 /* A composition rule is specified by an integer
2127 value that encodes global and new reference
2128 points (GREF and NREF). GREF and NREF are
2129 specified by numbers as below:
2137 ---3---4---5--- baseline
2139 6---7---8 -- descent
2141 int rule
= COMPOSITION_RULE (cmp
, i
);
2142 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2144 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2145 grefx
= gref
% 3, nrefx
= nref
% 3;
2146 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2149 + grefx
* (rightmost
- leftmost
) / 2
2150 - nrefx
* pcm
->width
/ 2);
2151 btm
= ((grefy
== 0 ? highest
2153 : grefy
== 2 ? lowest
2154 : (highest
+ lowest
) / 2)
2155 - (nrefy
== 0 ? pcm
->ascent
+ pcm
->descent
2156 : nrefy
== 1 ? pcm
->descent
- boff
2158 : (pcm
->ascent
+ pcm
->descent
) / 2));
2161 cmp
->offsets
[i
* 2] = left
;
2162 cmp
->offsets
[i
* 2 + 1] = btm
+ pcm
->descent
;
2164 /* Update the bounding box of the overall glyphs. */
2165 right
= left
+ pcm
->width
;
2166 top
= btm
+ pcm
->descent
+ pcm
->ascent
;
2167 if (left
< leftmost
)
2169 if (right
> rightmost
)
2177 /* If there are glyphs whose x-offsets are negative,
2178 shift all glyphs to the right and make all x-offsets
2182 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2183 cmp
->offsets
[i
* 2] -= leftmost
;
2184 rightmost
-= leftmost
;
2187 cmp
->pixel_width
= rightmost
;
2188 cmp
->ascent
= highest
;
2189 cmp
->descent
= - lowest
;
2190 if (cmp
->ascent
< font_ascent
)
2191 cmp
->ascent
= font_ascent
;
2192 if (cmp
->descent
< font_descent
)
2193 cmp
->descent
= font_descent
;
2196 it
->pixel_width
= cmp
->pixel_width
;
2197 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2198 it
->descent
= it
->phys_descent
= cmp
->descent
;
2200 if (face
->box
!= FACE_NO_BOX
)
2202 int thick
= face
->box_line_width
;
2203 it
->ascent
+= thick
;
2204 it
->descent
+= thick
;
2206 if (it
->start_of_box_run_p
)
2207 it
->pixel_width
+= thick
;
2208 if (it
->end_of_box_run_p
)
2209 it
->pixel_width
+= thick
;
2212 /* If face has an overline, add the height of the overline
2213 (1 pixel) and a 1 pixel margin to the character height. */
2214 if (face
->overline_p
)
2217 take_vertical_position_into_account (it
);
2220 x_append_composite_glyph (it
);
2222 else if (it
->what
== IT_IMAGE
)
2223 x_produce_image_glyph (it
);
2224 else if (it
->what
== IT_STRETCH
)
2225 x_produce_stretch_glyph (it
);
2227 /* Accumulate dimensions. */
2228 xassert (it
->ascent
>= 0 && it
->descent
> 0);
2229 if (it
->area
== TEXT_AREA
)
2230 it
->current_x
+= it
->pixel_width
;
2232 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2233 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2234 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2235 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
2239 /* Estimate the pixel height of the mode or top line on frame F.
2240 FACE_ID specifies what line's height to estimate. */
2243 x_estimate_mode_line_height (f
, face_id
)
2245 enum face_id face_id
;
2249 /* This function is called so early when Emacs starts that the face
2250 cache and mode line face are not yet initialized. */
2251 if (FRAME_FACE_CACHE (f
))
2253 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2255 height
= FONT_HEIGHT (face
->font
) + 2 * face
->box_line_width
;
2262 /***********************************************************************
2264 ***********************************************************************/
2266 /* A sequence of glyphs to be drawn in the same face.
2268 This data structure is not really completely X specific, so it
2269 could possibly, at least partially, be useful for other systems. It
2270 is currently not part of the external redisplay interface because
2271 it's not clear what other systems will need. */
2275 /* X-origin of the string. */
2278 /* Y-origin and y-position of the base line of this string. */
2281 /* The width of the string, not including a face extension. */
2284 /* The width of the string, including a face extension. */
2285 int background_width
;
2287 /* The height of this string. This is the height of the line this
2288 string is drawn in, and can be different from the height of the
2289 font the string is drawn in. */
2292 /* Number of pixels this string overwrites in front of its x-origin.
2293 This number is zero if the string has an lbearing >= 0; it is
2294 -lbearing, if the string has an lbearing < 0. */
2297 /* Number of pixels this string overwrites past its right-most
2298 nominal x-position, i.e. x + width. Zero if the string's
2299 rbearing is <= its nominal width, rbearing - width otherwise. */
2302 /* The frame on which the glyph string is drawn. */
2305 /* The window on which the glyph string is drawn. */
2308 /* X display and window for convenience. */
2312 /* The glyph row for which this string was built. It determines the
2313 y-origin and height of the string. */
2314 struct glyph_row
*row
;
2316 /* The area within row. */
2317 enum glyph_row_area area
;
2319 /* Characters to be drawn, and number of characters. */
2323 /* Character set of this glyph string. */
2326 /* A face-override for drawing cursors, mouse face and similar. */
2327 enum draw_glyphs_face hl
;
2329 /* Face in which this string is to be drawn. */
2332 /* Font in which this string is to be drawn. */
2335 /* Font info for this string. */
2336 struct font_info
*font_info
;
2338 /* Non-null means this string describes (part of) a composition.
2339 All characters from char2b are drawn composed. */
2340 struct composition
*cmp
;
2342 /* Index of this glyph string's first character in the glyph
2343 definition of CMP. If this is zero, this glyph string describes
2344 the first character of a composition. */
2347 /* 1 means this glyph strings face has to be drawn to the right end
2348 of the window's drawing area. */
2349 unsigned extends_to_end_of_line_p
: 1;
2351 /* 1 means the background of this string has been drawn. */
2352 unsigned background_filled_p
: 1;
2354 /* 1 means glyph string must be drawn with 16-bit functions. */
2355 unsigned two_byte_p
: 1;
2357 /* 1 means that the original font determined for drawing this glyph
2358 string could not be loaded. The member `font' has been set to
2359 the frame's default font in this case. */
2360 unsigned font_not_found_p
: 1;
2362 /* 1 means that the face in which this glyph string is drawn has a
2364 unsigned stippled_p
: 1;
2366 /* 1 means only the foreground of this glyph string must be drawn,
2367 and we should use the physical height of the line this glyph
2368 string appears in as clip rect. */
2369 unsigned for_overlaps_p
: 1;
2371 /* The GC to use for drawing this glyph string. */
2374 /* A pointer to the first glyph in the string. This glyph
2375 corresponds to char2b[0]. Needed to draw rectangles if
2376 font_not_found_p is 1. */
2377 struct glyph
*first_glyph
;
2379 /* Image, if any. */
2382 struct glyph_string
*next
, *prev
;
2389 x_dump_glyph_string (s
)
2390 struct glyph_string
*s
;
2392 fprintf (stderr
, "glyph string\n");
2393 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2394 s
->x
, s
->y
, s
->width
, s
->height
);
2395 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2396 fprintf (stderr
, " hl = %d\n", s
->hl
);
2397 fprintf (stderr
, " left overhang = %d, right = %d\n",
2398 s
->left_overhang
, s
->right_overhang
);
2399 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2400 fprintf (stderr
, " extends to end of line = %d\n",
2401 s
->extends_to_end_of_line_p
);
2402 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2403 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2406 #endif /* GLYPH_DEBUG */
2410 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2411 struct glyph_string
**,
2412 struct glyph_string
*,
2413 struct glyph_string
*));
2414 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2415 struct glyph_string
**,
2416 struct glyph_string
*,
2417 struct glyph_string
*));
2418 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2419 struct glyph_string
**,
2420 struct glyph_string
*));
2421 static int x_left_overwritten
P_ ((struct glyph_string
*));
2422 static int x_left_overwriting
P_ ((struct glyph_string
*));
2423 static int x_right_overwritten
P_ ((struct glyph_string
*));
2424 static int x_right_overwriting
P_ ((struct glyph_string
*));
2425 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2427 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2428 XChar2b
*, struct window
*,
2430 enum glyph_row_area
, int,
2431 enum draw_glyphs_face
));
2432 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2433 enum glyph_row_area
, int, int,
2434 enum draw_glyphs_face
, int *, int *, int));
2435 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2436 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2437 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2439 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2440 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2441 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2442 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2443 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2444 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2445 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2446 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2447 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2449 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2450 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2451 unsigned long *, double, int));
2452 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2453 double, int, unsigned long));
2454 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2455 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2456 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2457 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2458 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2459 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2460 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2462 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2463 int, int, int, int, XRectangle
*));
2464 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2465 int, int, int, XRectangle
*));
2466 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2467 enum glyph_row_area
));
2470 /* Append the list of glyph strings with head H and tail T to the list
2471 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2474 x_append_glyph_string_lists (head
, tail
, h
, t
)
2475 struct glyph_string
**head
, **tail
;
2476 struct glyph_string
*h
, *t
;
2490 /* Prepend the list of glyph strings with head H and tail T to the
2491 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2495 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2496 struct glyph_string
**head
, **tail
;
2497 struct glyph_string
*h
, *t
;
2511 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2512 Set *HEAD and *TAIL to the resulting list. */
2515 x_append_glyph_string (head
, tail
, s
)
2516 struct glyph_string
**head
, **tail
;
2517 struct glyph_string
*s
;
2519 s
->next
= s
->prev
= NULL
;
2520 x_append_glyph_string_lists (head
, tail
, s
, s
);
2524 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2529 struct glyph_string
*s
;
2531 if (s
->font
== FRAME_FONT (s
->f
)
2532 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2533 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2535 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2538 /* Cursor on non-default face: must merge. */
2542 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2543 xgcv
.foreground
= s
->face
->background
;
2545 /* If the glyph would be invisible, try a different foreground. */
2546 if (xgcv
.foreground
== xgcv
.background
)
2547 xgcv
.foreground
= s
->face
->foreground
;
2548 if (xgcv
.foreground
== xgcv
.background
)
2549 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2550 if (xgcv
.foreground
== xgcv
.background
)
2551 xgcv
.foreground
= s
->face
->foreground
;
2553 /* Make sure the cursor is distinct from text in this face. */
2554 if (xgcv
.background
== s
->face
->background
2555 && xgcv
.foreground
== s
->face
->foreground
)
2557 xgcv
.background
= s
->face
->foreground
;
2558 xgcv
.foreground
= s
->face
->background
;
2561 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2562 xgcv
.font
= s
->font
->fid
;
2563 xgcv
.graphics_exposures
= False
;
2564 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2566 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2567 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2570 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2571 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2573 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2578 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2581 x_set_mouse_face_gc (s
)
2582 struct glyph_string
*s
;
2586 /* What face has to be used for the mouse face? */
2587 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2588 face_id
= FACE_FOR_CHARSET (s
->f
, face_id
, s
->charset
);
2589 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2590 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2592 /* If font in this face is same as S->font, use it. */
2593 if (s
->font
== s
->face
->font
)
2594 s
->gc
= s
->face
->gc
;
2597 /* Otherwise construct scratch_cursor_gc with values from FACE
2602 xgcv
.background
= s
->face
->background
;
2603 xgcv
.foreground
= s
->face
->foreground
;
2604 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2605 xgcv
.font
= s
->font
->fid
;
2606 xgcv
.graphics_exposures
= False
;
2607 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2609 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2610 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2613 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2614 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2616 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2619 xassert (s
->gc
!= 0);
2623 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2624 Faces to use in the mode line have already been computed when the
2625 matrix was built, so there isn't much to do, here. */
2628 x_set_mode_line_face_gc (s
)
2629 struct glyph_string
*s
;
2631 s
->gc
= s
->face
->gc
;
2632 xassert (s
->gc
!= 0);
2636 /* Set S->gc of glyph string S for drawing that glyph string. Set
2637 S->stippled_p to a non-zero value if the face of S has a stipple
2641 x_set_glyph_string_gc (s
)
2642 struct glyph_string
*s
;
2644 if (s
->hl
== DRAW_NORMAL_TEXT
)
2646 s
->gc
= s
->face
->gc
;
2647 s
->stippled_p
= s
->face
->stipple
!= 0;
2649 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2651 x_set_mode_line_face_gc (s
);
2652 s
->stippled_p
= s
->face
->stipple
!= 0;
2654 else if (s
->hl
== DRAW_CURSOR
)
2656 x_set_cursor_gc (s
);
2659 else if (s
->hl
== DRAW_MOUSE_FACE
)
2661 x_set_mouse_face_gc (s
);
2662 s
->stippled_p
= s
->face
->stipple
!= 0;
2664 else if (s
->hl
== DRAW_IMAGE_RAISED
2665 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2667 s
->gc
= s
->face
->gc
;
2668 s
->stippled_p
= s
->face
->stipple
!= 0;
2672 s
->gc
= s
->face
->gc
;
2673 s
->stippled_p
= s
->face
->stipple
!= 0;
2676 /* GC must have been set. */
2677 xassert (s
->gc
!= 0);
2681 /* Return in *R the clipping rectangle for glyph string S. */
2684 x_get_glyph_string_clip_rect (s
, r
)
2685 struct glyph_string
*s
;
2688 if (s
->row
->full_width_p
)
2690 /* Draw full-width. X coordinates are relative to S->w->left. */
2691 int canon_x
= CANON_X_UNIT (s
->f
);
2693 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2694 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2696 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2698 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2699 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2703 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2705 /* Unless displaying a mode or menu bar line, which are always
2706 fully visible, clip to the visible part of the row. */
2707 if (s
->w
->pseudo_window_p
)
2708 r
->height
= s
->row
->visible_height
;
2710 r
->height
= s
->height
;
2714 /* This is a text line that may be partially visible. */
2715 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2716 r
->width
= window_box_width (s
->w
, s
->area
);
2717 r
->height
= s
->row
->visible_height
;
2720 /* Don't use S->y for clipping because it doesn't take partially
2721 visible lines into account. For example, it can be negative for
2722 partially visible lines at the top of a window. */
2723 if (!s
->row
->full_width_p
2724 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2725 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2727 r
->y
= max (0, s
->row
->y
);
2729 /* If drawing a tool-bar window, draw it over the internal border
2730 at the top of the window. */
2731 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2732 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2734 /* If S draws overlapping rows, it's sufficient to use the top and
2735 bottom of the window for clipping because this glyph string
2736 intentionally draws over other lines. */
2737 if (s
->for_overlaps_p
)
2739 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2740 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2743 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2747 /* Set clipping for output of glyph string S. S may be part of a mode
2748 line or menu if we don't have X toolkit support. */
2751 x_set_glyph_string_clipping (s
)
2752 struct glyph_string
*s
;
2755 x_get_glyph_string_clip_rect (s
, &r
);
2756 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2760 /* Compute left and right overhang of glyph string S. If S is a glyph
2761 string for a composition, assume overhangs don't exist. */
2764 x_compute_glyph_string_overhangs (s
)
2765 struct glyph_string
*s
;
2768 && s
->first_glyph
->type
== CHAR_GLYPH
)
2771 int direction
, font_ascent
, font_descent
;
2772 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2773 &font_ascent
, &font_descent
, &cs
);
2774 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2775 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2780 /* Compute overhangs and x-positions for glyph string S and its
2781 predecessors, or successors. X is the starting x-position for S.
2782 BACKWARD_P non-zero means process predecessors. */
2785 x_compute_overhangs_and_x (s
, x
, backward_p
)
2786 struct glyph_string
*s
;
2794 x_compute_glyph_string_overhangs (s
);
2804 x_compute_glyph_string_overhangs (s
);
2813 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2814 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2815 assumed to be zero. */
2818 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2819 struct glyph
*glyph
;
2827 if (glyph
->type
== CHAR_GLYPH
)
2831 struct font_info
*font_info
;
2834 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
);
2836 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2839 XCharStruct
*pcm
= x_per_char_metric (font
, &char2b
);
2841 if (pcm
->rbearing
> pcm
->width
)
2842 *right
= pcm
->rbearing
- pcm
->width
;
2843 if (pcm
->lbearing
< 0)
2844 *left
= -pcm
->lbearing
;
2850 /* Return the index of the first glyph preceding glyph string S that
2851 is overwritten by S because of S's left overhang. Value is -1
2852 if no glyphs are overwritten. */
2855 x_left_overwritten (s
)
2856 struct glyph_string
*s
;
2860 if (s
->left_overhang
)
2863 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2864 int first
= s
->first_glyph
- glyphs
;
2866 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2867 x
-= glyphs
[i
].pixel_width
;
2878 /* Return the index of the first glyph preceding glyph string S that
2879 is overwriting S because of its right overhang. Value is -1 if no
2880 glyph in front of S overwrites S. */
2883 x_left_overwriting (s
)
2884 struct glyph_string
*s
;
2887 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2888 int first
= s
->first_glyph
- glyphs
;
2892 for (i
= first
- 1; i
>= 0; --i
)
2895 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2898 x
-= glyphs
[i
].pixel_width
;
2905 /* Return the index of the last glyph following glyph string S that is
2906 not overwritten by S because of S's right overhang. Value is -1 if
2907 no such glyph is found. */
2910 x_right_overwritten (s
)
2911 struct glyph_string
*s
;
2915 if (s
->right_overhang
)
2918 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2919 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
2920 int end
= s
->row
->used
[s
->area
];
2922 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
2923 x
+= glyphs
[i
].pixel_width
;
2932 /* Return the index of the last glyph following glyph string S that
2933 overwrites S because of its left overhang. Value is negative
2934 if no such glyph is found. */
2937 x_right_overwriting (s
)
2938 struct glyph_string
*s
;
2941 int end
= s
->row
->used
[s
->area
];
2942 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2943 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
2947 for (i
= first
; i
< end
; ++i
)
2950 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2953 x
+= glyphs
[i
].pixel_width
;
2960 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2963 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2964 struct glyph_string
*s
;
2968 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
2969 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2970 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2971 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2975 /* Draw the background of glyph_string S. If S->background_filled_p
2976 is non-zero don't draw it. FORCE_P non-zero means draw the
2977 background even if it wouldn't be drawn normally. This is used
2978 when a string preceding S draws into the background of S, or S
2979 contains the first component of a composition. */
2982 x_draw_glyph_string_background (s
, force_p
)
2983 struct glyph_string
*s
;
2986 /* Nothing to do if background has already been drawn or if it
2987 shouldn't be drawn in the first place. */
2988 if (!s
->background_filled_p
)
2992 /* Fill background with a stipple pattern. */
2993 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2994 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2995 s
->y
+ s
->face
->box_line_width
,
2996 s
->background_width
,
2997 s
->height
- 2 * s
->face
->box_line_width
);
2998 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2999 s
->background_filled_p
= 1;
3001 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * s
->face
->box_line_width
3002 || s
->font_not_found_p
3003 || s
->extends_to_end_of_line_p
3006 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ s
->face
->box_line_width
,
3007 s
->background_width
,
3008 s
->height
- 2 * s
->face
->box_line_width
);
3009 s
->background_filled_p
= 1;
3015 /* Draw the foreground of glyph string S. */
3018 x_draw_glyph_string_foreground (s
)
3019 struct glyph_string
*s
;
3023 /* If first glyph of S has a left box line, start drawing the text
3024 of S to the right of that box line. */
3025 if (s
->face
->box
!= FACE_NO_BOX
3026 && s
->first_glyph
->left_box_line_p
)
3027 x
= s
->x
+ s
->face
->box_line_width
;
3031 /* Draw characters of S as rectangles if S's font could not be
3033 if (s
->font_not_found_p
)
3035 for (i
= 0; i
< s
->nchars
; ++i
)
3037 struct glyph
*g
= s
->first_glyph
+ i
;
3038 XDrawRectangle (s
->display
, s
->window
,
3039 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3041 x
+= g
->pixel_width
;
3046 char *char1b
= (char *) s
->char2b
;
3047 int boff
= s
->font_info
->baseline_offset
;
3049 if (s
->font_info
->vertical_centering
)
3050 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3052 /* If we can use 8-bit functions, condense S->char2b. */
3054 for (i
= 0; i
< s
->nchars
; ++i
)
3055 char1b
[i
] = s
->char2b
[i
].byte2
;
3057 /* Draw text with XDrawString if background has already been
3058 filled. Otherwise, use XDrawImageString. (Note that
3059 XDrawImageString is usually faster than XDrawString.) Always
3060 use XDrawImageString when drawing the cursor so that there is
3061 no chance that characters under a box cursor are invisible. */
3062 if (s
->for_overlaps_p
3063 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3065 /* Draw characters with 16-bit or 8-bit functions. */
3067 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3068 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3070 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3071 s
->ybase
- boff
, char1b
, s
->nchars
);
3076 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3077 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3079 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3080 s
->ybase
- boff
, char1b
, s
->nchars
);
3085 /* Draw the foreground of composite glyph string S. */
3088 x_draw_composite_glyph_string_foreground (s
)
3089 struct glyph_string
*s
;
3093 /* If first glyph of S has a left box line, start drawing the text
3094 of S to the right of that box line. */
3095 if (s
->face
->box
!= FACE_NO_BOX
3096 && s
->first_glyph
->left_box_line_p
)
3097 x
= s
->x
+ s
->face
->box_line_width
;
3101 /* S is a glyph string for a composition. S->gidx is the index of
3102 the first character drawn for glyphs of this composition.
3103 S->gidx == 0 means we are drawing the very first character of
3104 this composition. */
3106 /* Draw a rectangle for the composition if the font for the very
3107 first character of the composition could not be loaded. */
3108 if (s
->font_not_found_p
)
3111 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3112 s
->width
- 1, s
->height
- 1);
3116 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3117 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3118 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3119 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3125 #ifdef USE_X_TOOLKIT
3127 /* Allocate the color COLOR->pixel on the screen and display of
3128 widget WIDGET in colormap CMAP. If an exact match cannot be
3129 allocated, try the nearest color available. Value is non-zero
3130 if successful. This is called from lwlib. */
3133 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3139 struct x_display_info
*dpyinfo
;
3142 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3144 /* Find the top-level shell of the widget. Note that this function
3145 can be called when the widget is not yet realized, so XtWindow
3146 (widget) == 0. That's the reason we can't simply use
3147 x_any_window_to_frame. */
3148 while (!XtIsTopLevelShell (widget
))
3149 widget
= XtParent (widget
);
3151 /* Look for a frame with that top-level widget. Allocate the color
3152 on that frame to get the right gamma correction value. */
3153 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3154 if (GC_FRAMEP (XCAR (tail
))
3155 && (f
= XFRAME (XCAR (tail
)),
3156 (f
->output_data
.nothing
!= 1
3157 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3158 && f
->output_data
.x
->widget
== widget
)
3159 return x_alloc_nearest_color (f
, cmap
, color
);
3164 #endif /* USE_X_TOOLKIT */
3167 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3168 CMAP. If an exact match can't be allocated, try the nearest color
3169 available. Value is non-zero if successful. Set *COLOR to the
3173 x_alloc_nearest_color (f
, cmap
, color
)
3178 Display
*display
= FRAME_X_DISPLAY (f
);
3179 Screen
*screen
= FRAME_X_SCREEN (f
);
3182 gamma_correct (f
, color
);
3183 rc
= XAllocColor (display
, cmap
, color
);
3186 /* If we got to this point, the colormap is full, so we're going
3187 to try to get the next closest color. The algorithm used is
3188 a least-squares matching, which is what X uses for closest
3189 color matching with StaticColor visuals. */
3191 unsigned long nearest_delta
= ~0;
3192 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3193 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3195 for (i
= 0; i
< ncells
; ++i
)
3197 XQueryColors (display
, cmap
, cells
, ncells
);
3199 for (nearest
= i
= 0; i
< ncells
; ++i
)
3201 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3202 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3203 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3204 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3206 if (delta
< nearest_delta
)
3209 nearest_delta
= delta
;
3213 color
->red
= cells
[nearest
].red
;
3214 color
->green
= cells
[nearest
].green
;
3215 color
->blue
= cells
[nearest
].blue
;
3216 rc
= XAllocColor (display
, cmap
, color
);
3223 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3224 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3225 If this produces the same color as PIXEL, try a color where all RGB
3226 values have DELTA added. Return the allocated color in *PIXEL.
3227 DISPLAY is the X display, CMAP is the colormap to operate on.
3228 Value is non-zero if successful. */
3231 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3235 unsigned long *pixel
;
3242 /* Get RGB color values. */
3243 color
.pixel
= *pixel
;
3244 XQueryColor (display
, cmap
, &color
);
3246 /* Change RGB values by specified FACTOR. Avoid overflow! */
3247 xassert (factor
>= 0);
3248 new.red
= min (0xffff, factor
* color
.red
);
3249 new.green
= min (0xffff, factor
* color
.green
);
3250 new.blue
= min (0xffff, factor
* color
.blue
);
3252 /* Try to allocate the color. */
3253 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3256 if (new.pixel
== *pixel
)
3258 /* If we end up with the same color as before, try adding
3259 delta to the RGB values. */
3260 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
3262 /* If display has an immutable color map, freeing colors is
3263 not necessary and some servers don't allow it. So don't
3265 if (class != StaticColor
3266 && class != StaticGray
3267 && class != TrueColor
)
3268 XFreeColors (display
, cmap
, &new.pixel
, 1, 0);
3270 new.red
= min (0xffff, delta
+ color
.red
);
3271 new.green
= min (0xffff, delta
+ color
.green
);
3272 new.blue
= min (0xffff, delta
+ color
.blue
);
3273 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3284 /* Set up the foreground color for drawing relief lines of glyph
3285 string S. RELIEF is a pointer to a struct relief containing the GC
3286 with which lines will be drawn. Use a color that is FACTOR or
3287 DELTA lighter or darker than the relief's background which is found
3288 in S->f->output_data.x->relief_background. If such a color cannot
3289 be allocated, use DEFAULT_PIXEL, instead. */
3292 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3294 struct relief
*relief
;
3297 unsigned long default_pixel
;
3300 struct x_output
*di
= f
->output_data
.x
;
3301 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3302 unsigned long pixel
;
3303 unsigned long background
= di
->relief_background
;
3304 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3305 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3306 Display
*dpy
= FRAME_X_DISPLAY (f
);
3308 xgcv
.graphics_exposures
= False
;
3309 xgcv
.line_width
= 1;
3311 /* Free previously allocated color. The color cell will be reused
3312 when it has been freed as many times as it was allocated, so this
3313 doesn't affect faces using the same colors. */
3315 && relief
->allocated_p
)
3317 /* If display has an immutable color map, freeing colors is not
3318 necessary and some servers don't allow it. So don't do it. */
3319 int class = dpyinfo
->visual
->class;
3320 if (class != StaticColor
3321 && class != StaticGray
3322 && class != TrueColor
)
3323 XFreeColors (dpy
, cmap
, &relief
->pixel
, 1, 0);
3324 relief
->allocated_p
= 0;
3327 /* Allocate new color. */
3328 xgcv
.foreground
= default_pixel
;
3330 if (dpyinfo
->n_planes
!= 1
3331 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3333 relief
->allocated_p
= 1;
3334 xgcv
.foreground
= relief
->pixel
= pixel
;
3337 if (relief
->gc
== 0)
3339 xgcv
.stipple
= dpyinfo
->gray
;
3341 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3344 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3348 /* Set up colors for the relief lines around glyph string S. */
3351 x_setup_relief_colors (s
)
3352 struct glyph_string
*s
;
3354 struct x_output
*di
= s
->f
->output_data
.x
;
3355 unsigned long color
;
3357 if (s
->face
->use_box_color_for_shadows_p
)
3358 color
= s
->face
->box_color
;
3363 /* Get the background color of the face. */
3364 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3365 color
= xgcv
.background
;
3368 if (di
->white_relief
.gc
== 0
3369 || color
!= di
->relief_background
)
3371 di
->relief_background
= color
;
3372 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3373 WHITE_PIX_DEFAULT (s
->f
));
3374 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3375 BLACK_PIX_DEFAULT (s
->f
));
3380 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3381 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3382 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3383 relief. LEFT_P non-zero means draw a relief on the left side of
3384 the rectangle. RIGHT_P non-zero means draw a relief on the right
3385 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3389 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3390 raised_p
, left_p
, right_p
, clip_rect
)
3392 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3393 XRectangle
*clip_rect
;
3399 gc
= f
->output_data
.x
->white_relief
.gc
;
3401 gc
= f
->output_data
.x
->black_relief
.gc
;
3402 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3405 for (i
= 0; i
< width
; ++i
)
3406 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3407 left_x
+ i
* left_p
, top_y
+ i
,
3408 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3412 for (i
= 0; i
< width
; ++i
)
3413 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3414 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3416 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3418 gc
= f
->output_data
.x
->black_relief
.gc
;
3420 gc
= f
->output_data
.x
->white_relief
.gc
;
3421 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3424 for (i
= 0; i
< width
; ++i
)
3425 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3426 left_x
+ i
* left_p
, bottom_y
- i
,
3427 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3431 for (i
= 0; i
< width
; ++i
)
3432 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3433 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3435 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3439 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3440 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3441 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3442 left side of the rectangle. RIGHT_P non-zero means draw a line
3443 on the right side of the rectangle. CLIP_RECT is the clipping
3444 rectangle to use when drawing. */
3447 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3448 left_p
, right_p
, clip_rect
)
3449 struct glyph_string
*s
;
3450 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3451 XRectangle
*clip_rect
;
3455 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3456 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3457 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3460 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3461 left_x
, top_y
, right_x
- left_x
, width
);
3465 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3466 left_x
, top_y
, width
, bottom_y
- top_y
);
3469 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3470 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
3474 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3475 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
3477 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3478 XSetClipMask (s
->display
, s
->gc
, None
);
3482 /* Draw a box around glyph string S. */
3485 x_draw_glyph_string_box (s
)
3486 struct glyph_string
*s
;
3488 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3489 int left_p
, right_p
;
3490 struct glyph
*last_glyph
;
3491 XRectangle clip_rect
;
3493 last_x
= window_box_right (s
->w
, s
->area
);
3494 if (s
->row
->full_width_p
3495 && !s
->w
->pseudo_window_p
)
3497 last_x
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s
->f
);
3498 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3499 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3502 /* The glyph that may have a right box line. */
3503 last_glyph
= (s
->cmp
|| s
->img
3505 : s
->first_glyph
+ s
->nchars
- 1);
3507 width
= s
->face
->box_line_width
;
3508 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3510 right_x
= ((s
->row
->full_width_p
3512 : min (last_x
, s
->x
+ s
->background_width
) - 1));
3514 bottom_y
= top_y
+ s
->height
- 1;
3516 left_p
= (s
->first_glyph
->left_box_line_p
3517 || (s
->hl
== DRAW_MOUSE_FACE
3519 || s
->prev
->hl
!= s
->hl
)));
3520 right_p
= (last_glyph
->right_box_line_p
3521 || (s
->hl
== DRAW_MOUSE_FACE
3523 || s
->next
->hl
!= s
->hl
)));
3525 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3527 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3528 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3529 left_p
, right_p
, &clip_rect
);
3532 x_setup_relief_colors (s
);
3533 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3534 width
, raised_p
, left_p
, right_p
, &clip_rect
);
3539 /* Draw foreground of image glyph string S. */
3542 x_draw_image_foreground (s
)
3543 struct glyph_string
*s
;
3546 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3548 /* If first glyph of S has a left box line, start drawing it to the
3549 right of that line. */
3550 if (s
->face
->box
!= FACE_NO_BOX
3551 && s
->first_glyph
->left_box_line_p
)
3552 x
= s
->x
+ s
->face
->box_line_width
;
3556 /* If there is a margin around the image, adjust x- and y-position
3560 x
+= s
->img
->margin
;
3561 y
+= s
->img
->margin
;
3568 /* We can't set both a clip mask and use XSetClipRectangles
3569 because the latter also sets a clip mask. We also can't
3570 trust on the shape extension to be available
3571 (XShapeCombineRegion). So, compute the rectangle to draw
3573 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3576 XRectangle clip_rect
, image_rect
, r
;
3578 xgcv
.clip_mask
= s
->img
->mask
;
3579 xgcv
.clip_x_origin
= x
;
3580 xgcv
.clip_y_origin
= y
;
3581 xgcv
.function
= GXcopy
;
3582 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3584 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3587 image_rect
.width
= s
->img
->width
;
3588 image_rect
.height
= s
->img
->height
;
3589 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3590 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3591 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3595 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3596 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3598 /* When the image has a mask, we can expect that at
3599 least part of a mouse highlight or a block cursor will
3600 be visible. If the image doesn't have a mask, make
3601 a block cursor visible by drawing a rectangle around
3602 the image. I believe it's looking better if we do
3603 nothing here for mouse-face. */
3604 if (s
->hl
== DRAW_CURSOR
)
3605 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3606 s
->img
->width
- 1, s
->img
->height
- 1);
3610 /* Draw a rectangle if image could not be loaded. */
3611 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3612 s
->img
->width
- 1, s
->img
->height
- 1);
3616 /* Draw a relief around the image glyph string S. */
3619 x_draw_image_relief (s
)
3620 struct glyph_string
*s
;
3622 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3625 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3627 /* If first glyph of S has a left box line, start drawing it to the
3628 right of that line. */
3629 if (s
->face
->box
!= FACE_NO_BOX
3630 && s
->first_glyph
->left_box_line_p
)
3631 x
= s
->x
+ s
->face
->box_line_width
;
3635 /* If there is a margin around the image, adjust x- and y-position
3639 x
+= s
->img
->margin
;
3640 y
+= s
->img
->margin
;
3643 if (s
->hl
== DRAW_IMAGE_SUNKEN
3644 || s
->hl
== DRAW_IMAGE_RAISED
)
3646 thick
= tool_bar_button_relief
> 0 ? tool_bar_button_relief
: 3;
3647 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3651 thick
= abs (s
->img
->relief
);
3652 raised_p
= s
->img
->relief
> 0;
3657 x1
= x
+ s
->img
->width
+ thick
- 1;
3658 y1
= y
+ s
->img
->height
+ thick
- 1;
3660 x_setup_relief_colors (s
);
3661 x_get_glyph_string_clip_rect (s
, &r
);
3662 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
3666 /* Draw the foreground of image glyph string S to PIXMAP. */
3669 x_draw_image_foreground_1 (s
, pixmap
)
3670 struct glyph_string
*s
;
3674 int y
= s
->ybase
- s
->y
- IMAGE_ASCENT (s
->img
);
3676 /* If first glyph of S has a left box line, start drawing it to the
3677 right of that line. */
3678 if (s
->face
->box
!= FACE_NO_BOX
3679 && s
->first_glyph
->left_box_line_p
)
3680 x
= s
->face
->box_line_width
;
3684 /* If there is a margin around the image, adjust x- and y-position
3688 x
+= s
->img
->margin
;
3689 y
+= s
->img
->margin
;
3696 /* We can't set both a clip mask and use XSetClipRectangles
3697 because the latter also sets a clip mask. We also can't
3698 trust on the shape extension to be available
3699 (XShapeCombineRegion). So, compute the rectangle to draw
3701 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3705 xgcv
.clip_mask
= s
->img
->mask
;
3706 xgcv
.clip_x_origin
= x
;
3707 xgcv
.clip_y_origin
= y
;
3708 xgcv
.function
= GXcopy
;
3709 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3711 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3712 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3713 XSetClipMask (s
->display
, s
->gc
, None
);
3717 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3718 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3720 /* When the image has a mask, we can expect that at
3721 least part of a mouse highlight or a block cursor will
3722 be visible. If the image doesn't have a mask, make
3723 a block cursor visible by drawing a rectangle around
3724 the image. I believe it's looking better if we do
3725 nothing here for mouse-face. */
3726 if (s
->hl
== DRAW_CURSOR
)
3727 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3728 s
->img
->width
- 1, s
->img
->height
- 1);
3732 /* Draw a rectangle if image could not be loaded. */
3733 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3734 s
->img
->width
- 1, s
->img
->height
- 1);
3738 /* Draw part of the background of glyph string S. X, Y, W, and H
3739 give the rectangle to draw. */
3742 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3743 struct glyph_string
*s
;
3748 /* Fill background with a stipple pattern. */
3749 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3750 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3751 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3754 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3758 /* Draw image glyph string S.
3761 s->x +-------------------------
3764 | +-------------------------
3767 | | +-------------------
3773 x_draw_image_glyph_string (s
)
3774 struct glyph_string
*s
;
3777 int box_line_width
= s
->face
->box_line_width
;
3778 int margin
= s
->img
->margin
;
3780 Pixmap pixmap
= None
;
3782 height
= s
->height
- 2 * box_line_width
;
3784 /* Fill background with face under the image. Do it only if row is
3785 taller than image or if image has a clip mask to reduce
3787 s
->stippled_p
= s
->face
->stipple
!= 0;
3788 if (height
> s
->img
->height
3791 || s
->img
->pixmap
== 0
3792 || s
->width
!= s
->background_width
)
3794 if (box_line_width
&& s
->first_glyph
->left_box_line_p
)
3795 x
= s
->x
+ box_line_width
;
3799 y
= s
->y
+ box_line_width
;
3803 /* Create a pixmap as large as the glyph string Fill it with
3804 the background color. Copy the image to it, using its
3805 mask. Copy the temporary pixmap to the display. */
3806 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
3807 int depth
= DefaultDepthOfScreen (screen
);
3809 /* Create a pixmap as large as the glyph string. */
3810 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3811 s
->background_width
,
3814 /* Don't clip in the following because we're working on the
3816 XSetClipMask (s
->display
, s
->gc
, None
);
3818 /* Fill the pixmap with the background color/stipple. */
3821 /* Fill background with a stipple pattern. */
3822 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3823 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3824 0, 0, s
->background_width
, s
->height
);
3825 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3830 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3832 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3833 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3834 0, 0, s
->background_width
, s
->height
);
3835 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3839 /* Implementation idea: Is it possible to construct a mask?
3840 We could look at the color at the margins of the image, and
3841 say that this color is probably the background color of the
3843 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3845 s
->background_filled_p
= 1;
3848 /* Draw the foreground. */
3851 x_draw_image_foreground_1 (s
, pixmap
);
3852 x_set_glyph_string_clipping (s
);
3853 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
3854 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3855 XFreePixmap (s
->display
, pixmap
);
3858 x_draw_image_foreground (s
);
3860 /* If we must draw a relief around the image, do it. */
3862 || s
->hl
== DRAW_IMAGE_RAISED
3863 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3864 x_draw_image_relief (s
);
3868 /* Draw stretch glyph string S. */
3871 x_draw_stretch_glyph_string (s
)
3872 struct glyph_string
*s
;
3874 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3875 s
->stippled_p
= s
->face
->stipple
!= 0;
3877 if (s
->hl
== DRAW_CURSOR
3878 && !x_stretch_cursor_p
)
3880 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3881 as wide as the stretch glyph. */
3882 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
3885 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3887 /* Clear rest using the GC of the original non-cursor face. */
3888 if (width
< s
->background_width
)
3890 GC gc
= s
->face
->gc
;
3891 int x
= s
->x
+ width
, y
= s
->y
;
3892 int w
= s
->background_width
- width
, h
= s
->height
;
3895 x_get_glyph_string_clip_rect (s
, &r
);
3896 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
3898 if (s
->face
->stipple
)
3900 /* Fill background with a stipple pattern. */
3901 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3902 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3903 XSetFillStyle (s
->display
, gc
, FillSolid
);
3908 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3909 XSetForeground (s
->display
, gc
, xgcv
.background
);
3910 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3911 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3916 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3919 s
->background_filled_p
= 1;
3923 /* Draw glyph string S. */
3926 x_draw_glyph_string (s
)
3927 struct glyph_string
*s
;
3929 /* If S draws into the background of its successor, draw the
3930 background of the successor first so that S can draw into it.
3931 This makes S->next use XDrawString instead of XDrawImageString. */
3932 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3934 xassert (s
->next
->img
== NULL
);
3935 x_set_glyph_string_gc (s
->next
);
3936 x_set_glyph_string_clipping (s
->next
);
3937 x_draw_glyph_string_background (s
->next
, 1);
3940 /* Set up S->gc, set clipping and draw S. */
3941 x_set_glyph_string_gc (s
);
3942 x_set_glyph_string_clipping (s
);
3944 switch (s
->first_glyph
->type
)
3947 x_draw_image_glyph_string (s
);
3951 x_draw_stretch_glyph_string (s
);
3955 if (s
->for_overlaps_p
)
3956 s
->background_filled_p
= 1;
3958 x_draw_glyph_string_background (s
, 0);
3959 x_draw_glyph_string_foreground (s
);
3962 case COMPOSITE_GLYPH
:
3963 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3964 s
->background_filled_p
= 1;
3966 x_draw_glyph_string_background (s
, 1);
3967 x_draw_composite_glyph_string_foreground (s
);
3974 if (!s
->for_overlaps_p
)
3976 /* Draw underline. */
3977 if (s
->face
->underline_p
)
3979 unsigned long dy
, h
;
3981 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3983 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &dy
))
3986 if (s
->face
->underline_defaulted_p
)
3987 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3992 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3993 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3994 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3996 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4000 /* Draw overline. */
4001 if (s
->face
->overline_p
)
4003 unsigned long dy
= 0, h
= 1;
4005 if (s
->face
->overline_color_defaulted_p
)
4006 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4011 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4012 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4013 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4015 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4019 /* Draw strike-through. */
4020 if (s
->face
->strike_through_p
)
4022 unsigned long h
= 1;
4023 unsigned long dy
= (s
->height
- h
) / 2;
4025 if (s
->face
->strike_through_color_defaulted_p
)
4026 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4031 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4032 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4033 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4035 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4040 if (s
->face
->box
!= FACE_NO_BOX
)
4041 x_draw_glyph_string_box (s
);
4044 /* Reset clipping. */
4045 XSetClipMask (s
->display
, s
->gc
, None
);
4049 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4050 struct face
**, int));
4053 /* Load glyph string S with a composition components specified by S->cmp.
4054 FACES is an array of faces for all components of this composition.
4055 S->gidx is the index of the first component for S.
4056 OVERLAPS_P non-zero means S should draw the foreground only, and
4057 use its lines physical height for clipping.
4059 Value is the index of a component not in S. */
4062 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4063 struct glyph_string
*s
;
4064 struct face
**faces
;
4071 s
->for_overlaps_p
= overlaps_p
;
4073 s
->face
= faces
[s
->gidx
];
4074 s
->font
= s
->face
->font
;
4075 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4077 /* For all glyphs of this composition, starting at the offset
4078 S->gidx, until we reach the end of the definition or encounter a
4079 glyph that requires the different face, add it to S. */
4081 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4084 /* All glyph strings for the same composition has the same width,
4085 i.e. the width set for the first component of the composition. */
4087 s
->width
= s
->first_glyph
->pixel_width
;
4089 /* If the specified font could not be loaded, use the frame's
4090 default font, but record the fact that we couldn't load it in
4091 the glyph string so that we can draw rectangles for the
4092 characters of the glyph string. */
4093 if (s
->font
== NULL
)
4095 s
->font_not_found_p
= 1;
4096 s
->font
= FRAME_FONT (s
->f
);
4099 /* Adjust base line for subscript/superscript text. */
4100 s
->ybase
+= s
->first_glyph
->voffset
;
4102 xassert (s
->face
&& s
->face
->gc
);
4104 /* This glyph string must always be drawn with 16-bit functions. */
4107 return s
->gidx
+ s
->nchars
;
4111 /* Load glyph string S with a sequence characters.
4112 FACE_ID is the face id of the string. START is the index of the
4113 first glyph to consider, END is the index of the last + 1.
4114 OVERLAPS_P non-zero means S should draw the foreground only, and
4115 use its lines physical height for clipping.
4117 Value is the index of the first glyph not in S. */
4120 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4121 struct glyph_string
*s
;
4123 int start
, end
, overlaps_p
;
4125 struct glyph
*glyph
, *last
;
4128 xassert (s
->f
== XFRAME (s
->w
->frame
));
4129 xassert (s
->nchars
== 0);
4130 xassert (start
>= 0 && end
> start
);
4132 s
->for_overlaps_p
= overlaps_p
,
4133 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4134 last
= s
->row
->glyphs
[s
->area
] + end
;
4135 voffset
= glyph
->voffset
;
4138 && glyph
->type
== CHAR_GLYPH
4139 && glyph
->voffset
== voffset
4140 /* Same face id implies same charset, nowadays. */
4141 && glyph
->u
.ch
.face_id
== face_id
)
4143 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
4144 s
->char2b
+ s
->nchars
);
4145 if (s
->char2b
[s
->nchars
].byte2
!= 0)
4149 xassert (s
->nchars
<= end
- start
);
4150 s
->width
+= glyph
->pixel_width
;
4154 s
->font
= s
->face
->font
;
4155 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4157 /* If the specified font could not be loaded, use the frame's font,
4158 but record the fact that we couldn't load it in
4159 S->font_not_found_p so that we can draw rectangles for the
4160 characters of the glyph string. */
4161 if (s
->font
== NULL
)
4163 s
->font_not_found_p
= 1;
4164 s
->font
= FRAME_FONT (s
->f
);
4167 /* Adjust base line for subscript/superscript text. */
4168 s
->ybase
+= voffset
;
4170 xassert (s
->face
&& s
->face
->gc
);
4171 return glyph
- s
->row
->glyphs
[s
->area
];
4175 /* Fill glyph string S from image glyph S->first_glyph. */
4178 x_fill_image_glyph_string (s
)
4179 struct glyph_string
*s
;
4181 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4182 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.id
);
4184 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.face_id
);
4185 s
->font
= s
->face
->font
;
4186 s
->width
= s
->first_glyph
->pixel_width
;
4188 /* Adjust base line for subscript/superscript text. */
4189 s
->ybase
+= s
->first_glyph
->voffset
;
4193 /* Fill glyph string S from stretch glyph S->first_glyph. */
4196 x_fill_stretch_glyph_string (s
)
4197 struct glyph_string
*s
;
4199 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4200 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.stretch
.face_id
);
4201 s
->font
= s
->face
->font
;
4202 s
->width
= s
->first_glyph
->pixel_width
;
4204 /* Adjust base line for subscript/superscript text. */
4205 s
->ybase
+= s
->first_glyph
->voffset
;
4209 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4210 of XChar2b structures for S; it can't be allocated in
4211 x_init_glyph_string because it must be allocated via `alloca'. W
4212 is the window on which S is drawn. ROW and AREA are the glyph row
4213 and area within the row from which S is constructed. START is the
4214 index of the first glyph structure covered by S. HL is a
4215 face-override for drawing S. */
4218 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4219 struct glyph_string
*s
;
4222 struct glyph_row
*row
;
4223 enum glyph_row_area area
;
4225 enum draw_glyphs_face hl
;
4227 bzero (s
, sizeof *s
);
4229 s
->f
= XFRAME (w
->frame
);
4230 s
->display
= FRAME_X_DISPLAY (s
->f
);
4231 s
->window
= FRAME_X_WINDOW (s
->f
);
4236 s
->first_glyph
= row
->glyphs
[area
] + start
;
4237 s
->height
= row
->height
;
4238 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4240 /* Display the internal border below the tool-bar window. */
4241 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4242 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4244 s
->ybase
= s
->y
+ row
->ascent
;
4248 /* Set background width of glyph string S. START is the index of the
4249 first glyph following S. LAST_X is the right-most x-position + 1
4250 in the drawing area. */
4253 x_set_glyph_string_background_width (s
, start
, last_x
)
4254 struct glyph_string
*s
;
4258 /* If the face of this glyph string has to be drawn to the end of
4259 the drawing area, set S->extends_to_end_of_line_p. */
4260 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4262 if (start
== s
->row
->used
[s
->area
]
4263 && s
->hl
== DRAW_NORMAL_TEXT
4264 && ((s
->area
== TEXT_AREA
&& s
->row
->fill_line_p
)
4265 || s
->face
->background
!= default_face
->background
4266 || s
->face
->stipple
!= default_face
->stipple
))
4267 s
->extends_to_end_of_line_p
= 1;
4269 /* If S extends its face to the end of the line, set its
4270 background_width to the distance to the right edge of the drawing
4272 if (s
->extends_to_end_of_line_p
)
4273 s
->background_width
= last_x
- s
->x
+ 1;
4275 s
->background_width
= s
->width
;
4279 /* Add a glyph string for a stretch glyph to the list of strings
4280 between HEAD and TAIL. START is the index of the stretch glyph in
4281 row area AREA of glyph row ROW. END is the index of the last glyph
4282 in that glyph row area. X is the current output position assigned
4283 to the new glyph string constructed. HL overrides that face of the
4284 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4285 is the right-most x-position of the drawing area. */
4287 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4288 and below -- keep them on one line. */
4289 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4292 s = (struct glyph_string *) alloca (sizeof *s); \
4293 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4294 x_fill_stretch_glyph_string (s); \
4295 x_append_glyph_string (&HEAD, &TAIL, s); \
4302 /* Add a glyph string for an image glyph to the list of strings
4303 between HEAD and TAIL. START is the index of the image glyph in
4304 row area AREA of glyph row ROW. END is the index of the last glyph
4305 in that glyph row area. X is the current output position assigned
4306 to the new glyph string constructed. HL overrides that face of the
4307 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4308 is the right-most x-position of the drawing area. */
4310 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4313 s = (struct glyph_string *) alloca (sizeof *s); \
4314 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4315 x_fill_image_glyph_string (s); \
4316 x_append_glyph_string (&HEAD, &TAIL, s); \
4323 /* Add a glyph string for a sequence of character glyphs to the list
4324 of strings between HEAD and TAIL. START is the index of the first
4325 glyph in row area AREA of glyph row ROW that is part of the new
4326 glyph string. END is the index of the last glyph in that glyph row
4327 area. X is the current output position assigned to the new glyph
4328 string constructed. HL overrides that face of the glyph; e.g. it
4329 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4330 right-most x-position of the drawing area. */
4332 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4335 int c, charset, face_id; \
4338 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4339 charset = CHAR_CHARSET (c); \
4340 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4342 s = (struct glyph_string *) alloca (sizeof *s); \
4343 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4344 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4345 x_append_glyph_string (&HEAD, &TAIL, s); \
4346 s->charset = charset; \
4348 START = x_fill_glyph_string (s, face_id, START, END, \
4354 /* Add a glyph string for a composite sequence to the list of strings
4355 between HEAD and TAIL. START is the index of the first glyph in
4356 row area AREA of glyph row ROW that is part of the new glyph
4357 string. END is the index of the last glyph in that glyph row area.
4358 X is the current output position assigned to the new glyph string
4359 constructed. HL overrides that face of the glyph; e.g. it is
4360 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4361 x-position of the drawing area. */
4363 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, \
4364 TAIL, HL, X, LAST_X, OVERLAPS_P) \
4366 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp.id; \
4367 int face_id = (ROW)->glyphs[AREA][START].u.cmp.face_id; \
4368 struct composition *cmp = composition_table[cmp_id]; \
4369 int glyph_len = cmp->glyph_len; \
4371 struct face **faces; \
4372 struct glyph_string *first_s = NULL; \
4375 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4376 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4377 /* At first, fill in `char2b' and `faces'. */ \
4378 for (n = 0; n < glyph_len; n++) \
4380 int c = FAST_GLYPH_CHAR (COMPOSITION_GLYPH (cmp, n)); \
4381 faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4382 face_id, char2b + n, 1); \
4385 /* Make glyph_strings for each glyph sequence that is drawable by \
4386 the same face, and append them to HEAD/TAIL. */ \
4387 for (n = 0; n < cmp->glyph_len;) \
4389 s = (struct glyph_string *) alloca (sizeof *s); \
4390 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4391 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4400 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4408 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4409 of AREA of glyph row ROW on window W between indices START and END.
4410 HL overrides the face for drawing glyph strings, e.g. it is
4411 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4412 x-positions of the drawing area.
4414 This is an ugly monster macro construct because we must use alloca
4415 to allocate glyph strings (because x_draw_glyphs can be called
4418 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4421 HEAD = TAIL = NULL; \
4422 while (START < END) \
4424 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4425 switch (first_glyph->type) \
4428 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4429 TAIL, HL, X, LAST_X, \
4433 case COMPOSITE_GLYPH: \
4434 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4435 HEAD, TAIL, HL, X, LAST_X,\
4439 case STRETCH_GLYPH: \
4440 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4441 HEAD, TAIL, HL, X, LAST_X); \
4445 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4446 TAIL, HL, X, LAST_X); \
4453 x_set_glyph_string_background_width (s, START, LAST_X); \
4460 /* Draw glyphs between START and END in AREA of ROW on window W,
4461 starting at x-position X. X is relative to AREA in W. HL is a
4462 face-override with the following meaning:
4464 DRAW_NORMAL_TEXT draw normally
4465 DRAW_CURSOR draw in cursor face
4466 DRAW_MOUSE_FACE draw in mouse face.
4467 DRAW_INVERSE_VIDEO draw in mode line face
4468 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4469 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4471 If REAL_START is non-null, return in *REAL_START the real starting
4472 position for display. This can be different from START in case
4473 overlapping glyphs must be displayed. If REAL_END is non-null,
4474 return in *REAL_END the real end position for display. This can be
4475 different from END in case overlapping glyphs must be displayed.
4477 If OVERLAPS_P is non-zero, draw only the foreground of characters
4478 and clip to the physical height of ROW.
4480 Value is the x-position reached, relative to AREA of W. */
4483 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, real_start
, real_end
,
4487 struct glyph_row
*row
;
4488 enum glyph_row_area area
;
4490 enum draw_glyphs_face hl
;
4491 int *real_start
, *real_end
;
4494 struct glyph_string
*head
, *tail
;
4495 struct glyph_string
*s
;
4496 int last_x
, area_width
;
4500 /* Let's rather be paranoid than getting a SEGV. */
4501 start
= max (0, start
);
4502 end
= min (end
, row
->used
[area
]);
4504 *real_start
= start
;
4508 /* Translate X to frame coordinates. Set last_x to the right
4509 end of the drawing area. */
4510 if (row
->full_width_p
)
4512 /* X is relative to the left edge of W, without scroll bars
4514 struct frame
*f
= XFRAME (w
->frame
);
4515 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4516 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
4519 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4520 last_x
= window_left_x
+ area_width
;
4522 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4524 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4525 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4531 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
4532 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
4536 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
4537 area_width
= window_box_width (w
, area
);
4538 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
4541 /* Build a doubly-linked list of glyph_string structures between
4542 head and tail from what we have to draw. Note that the macro
4543 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4544 the reason we use a separate variable `i'. */
4546 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
4549 x_reached
= tail
->x
+ tail
->background_width
;
4553 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4554 the row, redraw some glyphs in front or following the glyph
4555 strings built above. */
4556 if (!overlaps_p
&& row
->contains_overlapping_glyphs_p
)
4559 struct glyph_string
*h
, *t
;
4561 /* Compute overhangs for all glyph strings. */
4562 for (s
= head
; s
; s
= s
->next
)
4563 x_compute_glyph_string_overhangs (s
);
4565 /* Prepend glyph strings for glyphs in front of the first glyph
4566 string that are overwritten because of the first glyph
4567 string's left overhang. The background of all strings
4568 prepended must be drawn because the first glyph string
4570 i
= x_left_overwritten (head
);
4574 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
4575 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4579 *real_start
= start
;
4580 x_compute_overhangs_and_x (t
, head
->x
, 1);
4581 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4584 /* Prepend glyph strings for glyphs in front of the first glyph
4585 string that overwrite that glyph string because of their
4586 right overhang. For these strings, only the foreground must
4587 be drawn, because it draws over the glyph string at `head'.
4588 The background must not be drawn because this would overwrite
4589 right overhangs of preceding glyphs for which no glyph
4591 i
= x_left_overwriting (head
);
4594 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
4595 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4597 for (s
= h
; s
; s
= s
->next
)
4598 s
->background_filled_p
= 1;
4601 x_compute_overhangs_and_x (t
, head
->x
, 1);
4602 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4605 /* Append glyphs strings for glyphs following the last glyph
4606 string tail that are overwritten by tail. The background of
4607 these strings has to be drawn because tail's foreground draws
4609 i
= x_right_overwritten (tail
);
4612 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4613 DRAW_NORMAL_TEXT
, x
, last_x
,
4615 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4616 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4621 /* Append glyph strings for glyphs following the last glyph
4622 string tail that overwrite tail. The foreground of such
4623 glyphs has to be drawn because it writes into the background
4624 of tail. The background must not be drawn because it could
4625 paint over the foreground of following glyphs. */
4626 i
= x_right_overwriting (tail
);
4629 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4630 DRAW_NORMAL_TEXT
, x
, last_x
,
4632 for (s
= h
; s
; s
= s
->next
)
4633 s
->background_filled_p
= 1;
4634 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4635 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4641 /* Draw all strings. */
4642 for (s
= head
; s
; s
= s
->next
)
4643 x_draw_glyph_string (s
);
4645 /* Value is the x-position up to which drawn, relative to AREA of W.
4646 This doesn't include parts drawn because of overhangs. */
4647 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
4648 if (!row
->full_width_p
)
4650 if (area
> LEFT_MARGIN_AREA
)
4651 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
4652 if (area
> TEXT_AREA
)
4653 x_reached
-= window_box_width (w
, TEXT_AREA
);
4659 /* Fix the display of area AREA of overlapping row ROW in window W. */
4662 x_fix_overlapping_area (w
, row
, area
)
4664 struct glyph_row
*row
;
4665 enum glyph_row_area area
;
4671 if (area
== LEFT_MARGIN_AREA
)
4673 else if (area
== TEXT_AREA
)
4674 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
4676 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
4677 + window_box_width (w
, TEXT_AREA
));
4679 for (i
= 0; i
< row
->used
[area
];)
4681 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
4683 int start
= i
, start_x
= x
;
4687 x
+= row
->glyphs
[area
][i
].pixel_width
;
4690 while (i
< row
->used
[area
]
4691 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
4693 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
4695 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4700 x
+= row
->glyphs
[area
][i
].pixel_width
;
4709 /* Output LEN glyphs starting at START at the nominal cursor position.
4710 Advance the nominal cursor over the text. The global variable
4711 updated_window contains the window being updated, updated_row is
4712 the glyph row being updated, and updated_area is the area of that
4713 row being updated. */
4716 x_write_glyphs (start
, len
)
4717 struct glyph
*start
;
4720 int x
, hpos
, real_start
, real_end
;
4722 xassert (updated_window
&& updated_row
);
4727 hpos
= start
- updated_row
->glyphs
[updated_area
];
4728 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
4729 updated_row
, updated_area
,
4731 (updated_row
->inverse_p
4732 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4733 &real_start
, &real_end
, 0);
4735 /* If we drew over the cursor, note that it is not visible any more. */
4736 note_overwritten_text_cursor (updated_window
, real_start
,
4737 real_end
- real_start
);
4741 /* Advance the output cursor. */
4742 output_cursor
.hpos
+= len
;
4743 output_cursor
.x
= x
;
4747 /* Insert LEN glyphs from START at the nominal cursor position. */
4750 x_insert_glyphs (start
, len
)
4751 struct glyph
*start
;
4756 int line_height
, shift_by_width
, shifted_region_width
;
4757 struct glyph_row
*row
;
4758 struct glyph
*glyph
;
4759 int frame_x
, frame_y
, hpos
, real_start
, real_end
;
4761 xassert (updated_window
&& updated_row
);
4764 f
= XFRAME (WINDOW_FRAME (w
));
4766 /* Get the height of the line we are in. */
4768 line_height
= row
->height
;
4770 /* Get the width of the glyphs to insert. */
4772 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
4773 shift_by_width
+= glyph
->pixel_width
;
4775 /* Get the width of the region to shift right. */
4776 shifted_region_width
= (window_box_width (w
, updated_area
)
4781 frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, output_cursor
.x
);
4782 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
4783 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4784 f
->output_data
.x
->normal_gc
,
4786 shifted_region_width
, line_height
,
4787 frame_x
+ shift_by_width
, frame_y
);
4789 /* Write the glyphs. */
4790 hpos
= start
- row
->glyphs
[updated_area
];
4791 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
4792 DRAW_NORMAL_TEXT
, &real_start
, &real_end
, 0);
4793 note_overwritten_text_cursor (w
, real_start
, real_end
- real_start
);
4795 /* Advance the output cursor. */
4796 output_cursor
.hpos
+= len
;
4797 output_cursor
.x
+= shift_by_width
;
4802 /* Delete N glyphs at the nominal cursor position. Not implemented
4813 /* Erase the current text line from the nominal cursor position
4814 (inclusive) to pixel column TO_X (exclusive). The idea is that
4815 everything from TO_X onward is already erased.
4817 TO_X is a pixel position relative to updated_area of
4818 updated_window. TO_X == -1 means clear to the end of this area. */
4821 x_clear_end_of_line (to_x
)
4825 struct window
*w
= updated_window
;
4826 int max_x
, min_y
, max_y
;
4827 int from_x
, from_y
, to_y
;
4829 xassert (updated_window
&& updated_row
);
4830 f
= XFRAME (w
->frame
);
4832 if (updated_row
->full_width_p
)
4834 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4835 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4836 && !w
->pseudo_window_p
)
4837 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4840 max_x
= window_box_width (w
, updated_area
);
4841 max_y
= window_text_bottom_y (w
);
4843 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4844 of window. For TO_X > 0, truncate to end of drawing area. */
4850 to_x
= min (to_x
, max_x
);
4852 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
4854 /* Notice if the cursor will be cleared by this operation. */
4855 if (!updated_row
->full_width_p
)
4856 note_overwritten_text_cursor (w
, output_cursor
.hpos
, -1);
4858 from_x
= output_cursor
.x
;
4860 /* Translate to frame coordinates. */
4861 if (updated_row
->full_width_p
)
4863 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
4864 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
4868 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
4869 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
4872 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
4873 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
4874 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
4876 /* Prevent inadvertently clearing to end of the X window. */
4877 if (to_x
> from_x
&& to_y
> from_y
)
4880 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4881 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
4888 /* Clear entire frame. If updating_frame is non-null, clear that
4889 frame. Otherwise clear the selected frame. */
4899 f
= SELECTED_FRAME ();
4901 /* Clearing the frame will erase any cursor, so mark them all as no
4903 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4904 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4905 output_cursor
.x
= -1;
4907 /* We don't set the output cursor here because there will always
4908 follow an explicit cursor_to. */
4910 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4912 /* We have to clear the scroll bars, too. If we have changed
4913 colors or something like that, then they should be notified. */
4914 x_scroll_bar_clear (f
);
4916 XFlush (FRAME_X_DISPLAY (f
));
4922 /* Invert the middle quarter of the frame for .15 sec. */
4924 /* We use the select system call to do the waiting, so we have to make
4925 sure it's available. If it isn't, we just won't do visual bells. */
4927 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4930 /* Subtract the `struct timeval' values X and Y, storing the result in
4931 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4934 timeval_subtract (result
, x
, y
)
4935 struct timeval
*result
, x
, y
;
4937 /* Perform the carry for the later subtraction by updating y. This
4938 is safer because on some systems the tv_sec member is unsigned. */
4939 if (x
.tv_usec
< y
.tv_usec
)
4941 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4942 y
.tv_usec
-= 1000000 * nsec
;
4946 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4948 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4949 y
.tv_usec
+= 1000000 * nsec
;
4953 /* Compute the time remaining to wait. tv_usec is certainly
4955 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4956 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4958 /* Return indication of whether the result should be considered
4960 return x
.tv_sec
< y
.tv_sec
;
4972 /* Create a GC that will use the GXxor function to flip foreground
4973 pixels into background pixels. */
4977 values
.function
= GXxor
;
4978 values
.foreground
= (f
->output_data
.x
->foreground_pixel
4979 ^ f
->output_data
.x
->background_pixel
);
4981 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4982 GCFunction
| GCForeground
, &values
);
4986 /* Get the height not including a menu bar widget. */
4987 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
4988 /* Height of each line to flash. */
4989 int flash_height
= FRAME_LINE_HEIGHT (f
);
4990 /* These will be the left and right margins of the rectangles. */
4991 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4992 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4996 /* Don't flash the area between a scroll bar and the frame
4997 edge it is next to. */
4998 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
5000 case vertical_scroll_bar_left
:
5001 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5004 case vertical_scroll_bar_right
:
5005 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5012 width
= flash_right
- flash_left
;
5014 /* If window is tall, flash top and bottom line. */
5015 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5017 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5019 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5020 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5021 width
, flash_height
);
5022 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5024 (height
- flash_height
5025 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5026 width
, flash_height
);
5029 /* If it is short, flash it all. */
5030 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5031 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5032 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5037 struct timeval wakeup
;
5039 EMACS_GET_TIME (wakeup
);
5041 /* Compute time to wait until, propagating carry from usecs. */
5042 wakeup
.tv_usec
+= 150000;
5043 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5044 wakeup
.tv_usec
%= 1000000;
5046 /* Keep waiting until past the time wakeup. */
5049 struct timeval timeout
;
5051 EMACS_GET_TIME (timeout
);
5053 /* In effect, timeout = wakeup - timeout.
5054 Break if result would be negative. */
5055 if (timeval_subtract (&timeout
, wakeup
, timeout
))
5058 /* Try to wait that long--but we might wake up sooner. */
5059 select (0, NULL
, NULL
, NULL
, &timeout
);
5063 /* If window is tall, flash top and bottom line. */
5064 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5066 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5068 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5069 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5070 width
, flash_height
);
5071 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5073 (height
- flash_height
5074 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5075 width
, flash_height
);
5078 /* If it is short, flash it all. */
5079 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5080 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5081 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5083 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5091 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5094 /* Make audible bell. */
5099 struct frame
*f
= SELECTED_FRAME ();
5101 if (FRAME_X_DISPLAY (f
))
5103 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5110 XBell (FRAME_X_DISPLAY (f
), 0);
5111 XFlush (FRAME_X_DISPLAY (f
));
5118 /* Specify how many text lines, from the top of the window,
5119 should be affected by insert-lines and delete-lines operations.
5120 This, and those operations, are used only within an update
5121 that is bounded by calls to x_update_begin and x_update_end. */
5124 XTset_terminal_window (n
)
5127 /* This function intentionally left blank. */
5132 /***********************************************************************
5134 ***********************************************************************/
5136 /* Perform an insert-lines or delete-lines operation, inserting N
5137 lines or deleting -N lines at vertical position VPOS. */
5140 x_ins_del_lines (vpos
, n
)
5147 /* Scroll part of the display as described by RUN. */
5150 x_scroll_run (w
, run
)
5154 struct frame
*f
= XFRAME (w
->frame
);
5155 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5157 /* Get frame-relative bounding box of the text display area of W,
5158 without mode lines. Include in this box the flags areas to the
5159 left and right of W. */
5160 window_box (w
, -1, &x
, &y
, &width
, &height
);
5161 width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
5162 x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
5164 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5165 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5166 bottom_y
= y
+ height
;
5170 /* Scrolling up. Make sure we don't copy part of the mode
5171 line at the bottom. */
5172 if (from_y
+ run
->height
> bottom_y
)
5173 height
= bottom_y
- from_y
;
5175 height
= run
->height
;
5179 /* Scolling down. Make sure we don't copy over the mode line.
5181 if (to_y
+ run
->height
> bottom_y
)
5182 height
= bottom_y
- to_y
;
5184 height
= run
->height
;
5189 /* Cursor off. Will be switched on again in x_update_window_end. */
5193 XCopyArea (FRAME_X_DISPLAY (f
),
5194 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5195 f
->output_data
.x
->normal_gc
,
5205 /***********************************************************************
5207 ***********************************************************************/
5209 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5210 corner of the exposed rectangle. W and H are width and height of
5211 the exposed area. All are pixel values. W or H zero means redraw
5212 the entire frame. */
5215 expose_frame (f
, x
, y
, w
, h
)
5221 TRACE ((stderr
, "expose_frame "));
5223 /* No need to redraw if frame will be redrawn soon. */
5224 if (FRAME_GARBAGED_P (f
))
5226 TRACE ((stderr
, " garbaged\n"));
5230 /* If basic faces haven't been realized yet, there is no point in
5231 trying to redraw anything. This can happen when we get an expose
5232 event while Emacs is starting, e.g. by moving another window. */
5233 if (FRAME_FACE_CACHE (f
) == NULL
5234 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5236 TRACE ((stderr
, " no faces\n"));
5240 if (w
== 0 || h
== 0)
5243 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5244 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5254 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5255 expose_window_tree (XWINDOW (f
->root_window
), &r
);
5257 if (WINDOWP (f
->tool_bar_window
))
5259 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5260 XRectangle window_rect
;
5261 XRectangle intersection_rect
;
5262 int window_x
, window_y
, window_width
, window_height
;
5265 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5266 window_rect
.x
= window_x
;
5267 window_rect
.y
= window_y
;
5268 window_rect
.width
= window_width
;
5269 window_rect
.height
= window_height
;
5271 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5272 expose_window (w
, &intersection_rect
);
5275 #ifndef USE_X_TOOLKIT
5276 if (WINDOWP (f
->menu_bar_window
))
5278 struct window
*w
= XWINDOW (f
->menu_bar_window
);
5279 XRectangle window_rect
;
5280 XRectangle intersection_rect
;
5281 int window_x
, window_y
, window_width
, window_height
;
5284 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5285 window_rect
.x
= window_x
;
5286 window_rect
.y
= window_y
;
5287 window_rect
.width
= window_width
;
5288 window_rect
.height
= window_height
;
5290 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5291 expose_window (w
, &intersection_rect
);
5293 #endif /* not USE_X_TOOLKIT */
5297 /* Redraw (parts) of all windows in the window tree rooted at W that
5298 intersect R. R contains frame pixel coordinates. */
5301 expose_window_tree (w
, r
)
5307 if (!NILP (w
->hchild
))
5308 expose_window_tree (XWINDOW (w
->hchild
), r
);
5309 else if (!NILP (w
->vchild
))
5310 expose_window_tree (XWINDOW (w
->vchild
), r
);
5313 XRectangle window_rect
;
5314 XRectangle intersection_rect
;
5315 struct frame
*f
= XFRAME (w
->frame
);
5316 int window_x
, window_y
, window_width
, window_height
;
5318 /* Frame-relative pixel rectangle of W. */
5319 window_box (w
, -1, &window_x
, &window_y
, &window_width
,
5323 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
5324 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5325 window_rect
.y
= window_y
;
5328 + FRAME_X_FLAGS_AREA_WIDTH (f
)
5329 + FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5331 = window_height
+ CURRENT_MODE_LINE_HEIGHT (w
);
5333 if (x_intersect_rectangles (r
, &window_rect
, &intersection_rect
))
5334 expose_window (w
, &intersection_rect
);
5337 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5342 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5343 which intersects rectangle R. R is in window-relative coordinates. */
5346 expose_area (w
, row
, r
, area
)
5348 struct glyph_row
*row
;
5350 enum glyph_row_area area
;
5353 struct glyph
*first
= row
->glyphs
[area
];
5354 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5358 /* Set x to the window-relative start position for drawing glyphs of
5359 AREA. The first glyph of the text area can be partially visible.
5360 The first glyphs of other areas cannot. */
5361 if (area
== LEFT_MARGIN_AREA
)
5363 else if (area
== TEXT_AREA
)
5364 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5366 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5367 + window_box_width (w
, TEXT_AREA
));
5369 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5370 /* If row extends face to end of line write the whole line. */
5371 x_draw_glyphs (w
, x
, row
, area
,
5373 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5377 /* Find the first glyph that must be redrawn. */
5379 && x
+ first
->pixel_width
< r
->x
)
5381 x
+= first
->pixel_width
;
5385 /* Find the last one. */
5389 && x
< r
->x
+ r
->width
)
5391 x
+= last
->pixel_width
;
5397 x_draw_glyphs (w
, first_x
, row
, area
,
5398 first
- row
->glyphs
[area
],
5399 last
- row
->glyphs
[area
],
5400 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5406 /* Redraw the parts of the glyph row ROW on window W intersecting
5407 rectangle R. R is in window-relative coordinates. */
5410 expose_line (w
, row
, r
)
5412 struct glyph_row
*row
;
5415 xassert (row
->enabled_p
);
5417 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5418 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5419 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5423 if (row
->used
[LEFT_MARGIN_AREA
])
5424 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5425 if (row
->used
[TEXT_AREA
])
5426 expose_area (w
, row
, r
, TEXT_AREA
);
5427 if (row
->used
[RIGHT_MARGIN_AREA
])
5428 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5429 x_draw_row_bitmaps (w
, row
);
5434 /* Return non-zero if W's cursor intersects rectangle R. */
5437 x_phys_cursor_in_rect_p (w
, r
)
5441 XRectangle cr
, result
;
5442 struct glyph
*cursor_glyph
;
5444 cursor_glyph
= get_phys_cursor_glyph (w
);
5447 cr
.x
= w
->phys_cursor
.x
;
5448 cr
.y
= w
->phys_cursor
.y
;
5449 cr
.width
= cursor_glyph
->pixel_width
;
5450 cr
.height
= w
->phys_cursor_height
;
5451 return x_intersect_rectangles (&cr
, r
, &result
);
5458 /* Redraw a rectangle of window W. R is a rectangle in window
5459 relative coordinates. Call this function with input blocked. */
5462 expose_window (w
, r
)
5466 struct glyph_row
*row
;
5468 int yb
= window_text_bottom_y (w
);
5469 int cursor_cleared_p
;
5471 /* If window is not yet fully initialized, do nothing. This can
5472 happen when toolkit scroll bars are used and a window is split.
5473 Reconfiguring the scroll bar will generate an expose for a newly
5475 if (w
->current_matrix
== NULL
)
5478 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
5479 r
->x
, r
->y
, r
->width
, r
->height
));
5481 /* Convert to window coordinates. */
5482 r
->x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
->x
);
5483 r
->y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
->y
);
5485 /* Turn off the cursor. */
5486 if (!w
->pseudo_window_p
5487 && x_phys_cursor_in_rect_p (w
, r
))
5490 cursor_cleared_p
= 1;
5493 cursor_cleared_p
= 0;
5495 /* Find the first row intersecting the rectangle R. */
5496 row
= w
->current_matrix
->rows
;
5498 while (row
->enabled_p
5500 && y
+ row
->height
< r
->y
)
5506 /* Display the text in the rectangle, one text line at a time. */
5507 while (row
->enabled_p
5509 && y
< r
->y
+ r
->height
)
5511 expose_line (w
, row
, r
);
5516 /* Display the mode line if there is one. */
5517 if (WINDOW_WANTS_MODELINE_P (w
)
5518 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
5520 && row
->y
< r
->y
+ r
->height
)
5521 expose_line (w
, row
, r
);
5523 if (!w
->pseudo_window_p
)
5525 /* Draw border between windows. */
5526 x_draw_vertical_border (w
);
5528 /* Turn the cursor on again. */
5529 if (cursor_cleared_p
)
5530 x_update_window_cursor (w
, 1);
5535 /* Determine the intersection of two rectangles R1 and R2. Return
5536 the intersection in *RESULT. Value is non-zero if RESULT is not
5540 x_intersect_rectangles (r1
, r2
, result
)
5541 XRectangle
*r1
, *r2
, *result
;
5543 XRectangle
*left
, *right
;
5544 XRectangle
*upper
, *lower
;
5545 int intersection_p
= 0;
5547 /* Rearrange so that R1 is the left-most rectangle. */
5549 left
= r1
, right
= r2
;
5551 left
= r2
, right
= r1
;
5553 /* X0 of the intersection is right.x0, if this is inside R1,
5554 otherwise there is no intersection. */
5555 if (right
->x
<= left
->x
+ left
->width
)
5557 result
->x
= right
->x
;
5559 /* The right end of the intersection is the minimum of the
5560 the right ends of left and right. */
5561 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
5564 /* Same game for Y. */
5566 upper
= r1
, lower
= r2
;
5568 upper
= r2
, lower
= r1
;
5570 /* The upper end of the intersection is lower.y0, if this is inside
5571 of upper. Otherwise, there is no intersection. */
5572 if (lower
->y
<= upper
->y
+ upper
->height
)
5574 result
->y
= lower
->y
;
5576 /* The lower end of the intersection is the minimum of the lower
5577 ends of upper and lower. */
5578 result
->height
= (min (lower
->y
+ lower
->height
,
5579 upper
->y
+ upper
->height
)
5585 return intersection_p
;
5596 /* We used to only do this if Vx_no_window_manager was non-nil, but
5597 the ICCCM (section 4.1.6) says that the window's border pixmap
5598 and border pixel are window attributes which are "private to the
5599 client", so we can always change it to whatever we want. */
5601 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5602 f
->output_data
.x
->border_pixel
);
5604 x_update_cursor (f
, 1);
5608 frame_unhighlight (f
)
5611 /* We used to only do this if Vx_no_window_manager was non-nil, but
5612 the ICCCM (section 4.1.6) says that the window's border pixmap
5613 and border pixel are window attributes which are "private to the
5614 client", so we can always change it to whatever we want. */
5616 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5617 f
->output_data
.x
->border_tile
);
5619 x_update_cursor (f
, 1);
5622 /* The focus has changed. Update the frames as necessary to reflect
5623 the new situation. Note that we can't change the selected frame
5624 here, because the Lisp code we are interrupting might become confused.
5625 Each event gets marked with the frame in which it occurred, so the
5626 Lisp code can tell when the switch took place by examining the events. */
5629 x_new_focus_frame (dpyinfo
, frame
)
5630 struct x_display_info
*dpyinfo
;
5631 struct frame
*frame
;
5633 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5635 if (frame
!= dpyinfo
->x_focus_frame
)
5637 /* Set this before calling other routines, so that they see
5638 the correct value of x_focus_frame. */
5639 dpyinfo
->x_focus_frame
= frame
;
5641 if (old_focus
&& old_focus
->auto_lower
)
5642 x_lower_frame (old_focus
);
5645 selected_frame
= frame
;
5646 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
5648 Fselect_window (selected_frame
->selected_window
);
5649 choose_minibuf_frame ();
5652 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
5653 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
5655 pending_autoraise_frame
= 0;
5658 x_frame_rehighlight (dpyinfo
);
5661 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5664 x_mouse_leave (dpyinfo
)
5665 struct x_display_info
*dpyinfo
;
5667 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
5670 /* The focus has changed, or we have redirected a frame's focus to
5671 another frame (this happens when a frame uses a surrogate
5672 mini-buffer frame). Shift the highlight as appropriate.
5674 The FRAME argument doesn't necessarily have anything to do with which
5675 frame is being highlighted or un-highlighted; we only use it to find
5676 the appropriate X display info. */
5679 XTframe_rehighlight (frame
)
5680 struct frame
*frame
;
5682 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
5686 x_frame_rehighlight (dpyinfo
)
5687 struct x_display_info
*dpyinfo
;
5689 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
5691 if (dpyinfo
->x_focus_frame
)
5693 dpyinfo
->x_highlight_frame
5694 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
5695 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
5696 : dpyinfo
->x_focus_frame
);
5697 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
5699 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
5700 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
5704 dpyinfo
->x_highlight_frame
= 0;
5706 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
5709 frame_unhighlight (old_highlight
);
5710 if (dpyinfo
->x_highlight_frame
)
5711 frame_highlight (dpyinfo
->x_highlight_frame
);
5717 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5719 /* Initialize mode_switch_bit and modifier_meaning. */
5721 x_find_modifier_meanings (dpyinfo
)
5722 struct x_display_info
*dpyinfo
;
5724 int min_code
, max_code
;
5727 XModifierKeymap
*mods
;
5729 dpyinfo
->meta_mod_mask
= 0;
5730 dpyinfo
->shift_lock_mask
= 0;
5731 dpyinfo
->alt_mod_mask
= 0;
5732 dpyinfo
->super_mod_mask
= 0;
5733 dpyinfo
->hyper_mod_mask
= 0;
5736 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
5738 min_code
= dpyinfo
->display
->min_keycode
;
5739 max_code
= dpyinfo
->display
->max_keycode
;
5742 syms
= XGetKeyboardMapping (dpyinfo
->display
,
5743 min_code
, max_code
- min_code
+ 1,
5745 mods
= XGetModifierMapping (dpyinfo
->display
);
5747 /* Scan the modifier table to see which modifier bits the Meta and
5748 Alt keysyms are on. */
5750 int row
, col
; /* The row and column in the modifier table. */
5752 for (row
= 3; row
< 8; row
++)
5753 for (col
= 0; col
< mods
->max_keypermod
; col
++)
5756 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
5758 /* Zeroes are used for filler. Skip them. */
5762 /* Are any of this keycode's keysyms a meta key? */
5766 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
5768 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
5774 dpyinfo
->meta_mod_mask
|= (1 << row
);
5779 dpyinfo
->alt_mod_mask
|= (1 << row
);
5784 dpyinfo
->hyper_mod_mask
|= (1 << row
);
5789 dpyinfo
->super_mod_mask
|= (1 << row
);
5793 /* Ignore this if it's not on the lock modifier. */
5794 if ((1 << row
) == LockMask
)
5795 dpyinfo
->shift_lock_mask
= LockMask
;
5803 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5804 if (! dpyinfo
->meta_mod_mask
)
5806 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
5807 dpyinfo
->alt_mod_mask
= 0;
5810 /* If some keys are both alt and meta,
5811 make them just meta, not alt. */
5812 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
5814 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
5817 XFree ((char *) syms
);
5818 XFreeModifiermap (mods
);
5821 /* Convert between the modifier bits X uses and the modifier bits
5825 x_x_to_emacs_modifiers (dpyinfo
, state
)
5826 struct x_display_info
*dpyinfo
;
5829 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
5830 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
5831 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
5832 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
5833 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
5834 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
5838 x_emacs_to_x_modifiers (dpyinfo
, state
)
5839 struct x_display_info
*dpyinfo
;
5842 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
5843 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
5844 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
5845 | ((state
& shift_modifier
) ? ShiftMask
: 0)
5846 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
5847 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
5850 /* Convert a keysym to its name. */
5853 x_get_keysym_name (keysym
)
5859 value
= XKeysymToString (keysym
);
5867 /* Mouse clicks and mouse movement. Rah. */
5869 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5870 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5871 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5872 not force the value into range. */
5875 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
5877 register int pix_x
, pix_y
;
5878 register int *x
, *y
;
5882 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5883 even for negative values. */
5885 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
5887 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
5889 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
5890 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
5894 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
5895 bounds
->height
= f
->output_data
.x
->line_height
;
5896 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
5897 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
5904 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
5905 pix_x
= FRAME_WINDOW_WIDTH (f
);
5909 else if (pix_y
> f
->height
)
5918 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5919 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5920 can't tell the positions because W's display is not up to date,
5924 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
5927 int *frame_x
, *frame_y
;
5931 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
5932 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
5934 if (display_completed
)
5936 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
5937 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
5938 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
5944 *frame_x
+= glyph
->pixel_width
;
5952 *frame_y
= *frame_x
= 0;
5956 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
5957 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
5962 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5964 If the event is a button press, then note that we have grabbed
5968 construct_mouse_click (result
, event
, f
)
5969 struct input_event
*result
;
5970 XButtonEvent
*event
;
5973 /* Make the event type no_event; we'll change that when we decide
5975 result
->kind
= mouse_click
;
5976 result
->code
= event
->button
- Button1
;
5977 result
->timestamp
= event
->time
;
5978 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5980 | (event
->type
== ButtonRelease
5984 XSETINT (result
->x
, event
->x
);
5985 XSETINT (result
->y
, event
->y
);
5986 XSETFRAME (result
->frame_or_window
, f
);
5990 #if 0 /* This function isn't called. --gerd */
5992 /* Prepare a menu-event in *RESULT for placement in the input queue. */
5995 construct_menu_click (result
, event
, f
)
5996 struct input_event
*result
;
5997 XButtonEvent
*event
;
6000 /* Make the event type no_event; we'll change that when we decide
6002 result
->kind
= mouse_click
;
6003 result
->code
= event
->button
- Button1
;
6004 result
->timestamp
= event
->time
;
6005 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6007 | (event
->type
== ButtonRelease
6011 XSETINT (result
->x
, event
->x
);
6012 XSETINT (result
->y
, -1);
6013 XSETFRAME (result
->frame_or_window
, f
);
6019 /* Function to report a mouse movement to the mainstream Emacs code.
6020 The input handler calls this.
6022 We have received a mouse movement event, which is given in *event.
6023 If the mouse is over a different glyph than it was last time, tell
6024 the mainstream emacs code by setting mouse_moved. If not, ask for
6025 another motion event, so we can check again the next time it moves. */
6027 static XMotionEvent last_mouse_motion_event
;
6028 static Lisp_Object last_mouse_motion_frame
;
6031 note_mouse_movement (frame
, event
)
6033 XMotionEvent
*event
;
6035 last_mouse_movement_time
= event
->time
;
6036 last_mouse_motion_event
= *event
;
6037 XSETFRAME (last_mouse_motion_frame
, frame
);
6039 if (event
->window
!= FRAME_X_WINDOW (frame
))
6041 frame
->mouse_moved
= 1;
6042 last_mouse_scroll_bar
= Qnil
;
6043 note_mouse_highlight (frame
, -1, -1);
6046 /* Has the mouse moved off the glyph it was on at the last sighting? */
6047 else if (event
->x
< last_mouse_glyph
.x
6048 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
6049 || event
->y
< last_mouse_glyph
.y
6050 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
6052 frame
->mouse_moved
= 1;
6053 last_mouse_scroll_bar
= Qnil
;
6054 note_mouse_highlight (frame
, event
->x
, event
->y
);
6058 /* This is used for debugging, to turn off note_mouse_highlight. */
6060 int disable_mouse_highlight
;
6064 /************************************************************************
6066 ************************************************************************/
6068 /* Find the glyph under window-relative coordinates X/Y in window W.
6069 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6070 strings. Return in *HPOS and *VPOS the row and column number of
6071 the glyph found. Return in *AREA the glyph area containing X.
6072 Value is a pointer to the glyph found or null if X/Y is not on
6073 text, or we can't tell because W's current matrix is not up to
6076 static struct glyph
*
6077 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
)
6080 int *hpos
, *vpos
, *area
;
6082 struct glyph
*glyph
, *end
;
6083 struct glyph_row
*row
;
6084 int x0
, i
, left_area_width
;
6086 /* Find row containing Y. Give up if some row is not enabled. */
6087 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6089 row
= MATRIX_ROW (w
->current_matrix
, i
);
6090 if (!row
->enabled_p
)
6092 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6099 /* Give up if Y is not in the window. */
6100 if (i
== w
->current_matrix
->nrows
)
6103 /* Get the glyph area containing X. */
6104 if (w
->pseudo_window_p
)
6111 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6112 if (x
< left_area_width
)
6114 *area
= LEFT_MARGIN_AREA
;
6117 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6120 x0
= row
->x
+ left_area_width
;
6124 *area
= RIGHT_MARGIN_AREA
;
6125 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6129 /* Find glyph containing X. */
6130 glyph
= row
->glyphs
[*area
];
6131 end
= glyph
+ row
->used
[*area
];
6134 if (x
< x0
+ glyph
->pixel_width
)
6136 if (w
->pseudo_window_p
)
6138 else if (BUFFERP (glyph
->object
))
6142 x0
+= glyph
->pixel_width
;
6149 *hpos
= glyph
- row
->glyphs
[*area
];
6154 /* Convert frame-relative x/y to coordinates relative to window W.
6155 Takes pseudo-windows into account. */
6158 frame_to_window_pixel_xy (w
, x
, y
)
6162 if (w
->pseudo_window_p
)
6164 /* A pseudo-window is always full-width, and starts at the
6165 left edge of the frame, plus a frame border. */
6166 struct frame
*f
= XFRAME (w
->frame
);
6167 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6168 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6172 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6173 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6178 /* Take proper action when mouse has moved to the mode or top line of
6179 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6180 mode line. X is relative to the start of the text display area of
6181 W, so the width of bitmap areas and scroll bars must be subtracted
6182 to get a position relative to the start of the mode line. */
6185 note_mode_line_highlight (w
, x
, mode_line_p
)
6189 struct frame
*f
= XFRAME (w
->frame
);
6190 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6191 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6192 struct glyph_row
*row
;
6195 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6197 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
6201 struct glyph
*glyph
, *end
;
6202 Lisp_Object help
, map
;
6205 /* Find the glyph under X. */
6206 glyph
= row
->glyphs
[TEXT_AREA
];
6207 end
= glyph
+ row
->used
[TEXT_AREA
];
6208 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
6209 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
));
6211 && x
>= x0
+ glyph
->pixel_width
)
6213 x0
+= glyph
->pixel_width
;
6218 && STRINGP (glyph
->object
)
6219 && XSTRING (glyph
->object
)->intervals
6220 && glyph
->charpos
>= 0
6221 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6223 /* If we're on a string with `help-echo' text property,
6224 arrange for the help to be displayed. This is done by
6225 setting the global variable help_echo to the help string. */
6226 help
= Fget_text_property (make_number (glyph
->charpos
),
6227 Qhelp_echo
, glyph
->object
);
6231 /* Change the mouse pointer according to what is under X/Y. */
6232 map
= Fget_text_property (make_number (glyph
->charpos
),
6233 Qlocal_map
, glyph
->object
);
6234 if (!NILP (Fkeymapp (map
)))
6235 cursor
= f
->output_data
.x
->nontext_cursor
;
6239 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
6243 /* Take proper action when the mouse has moved to position X, Y on
6244 frame F as regards highlighting characters that have mouse-face
6245 properties. Also de-highlighting chars where the mouse was before.
6246 X and Y can be negative or out of range. */
6249 note_mouse_highlight (f
, x
, y
)
6253 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6258 /* When a menu is active, don't highlight because this looks odd. */
6259 #ifdef USE_X_TOOLKIT
6260 if (popup_activated ())
6264 if (disable_mouse_highlight
)
6267 dpyinfo
->mouse_face_mouse_x
= x
;
6268 dpyinfo
->mouse_face_mouse_y
= y
;
6269 dpyinfo
->mouse_face_mouse_frame
= f
;
6271 if (dpyinfo
->mouse_face_defer
)
6276 dpyinfo
->mouse_face_deferred_gc
= 1;
6280 /* Which window is that in? */
6281 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
6283 /* If we were displaying active text in another window, clear that. */
6284 if (! EQ (window
, dpyinfo
->mouse_face_window
))
6285 clear_mouse_face (dpyinfo
);
6287 /* Not on a window -> return. */
6288 if (!WINDOWP (window
))
6291 /* Convert to window-relative pixel coordinates. */
6292 w
= XWINDOW (window
);
6293 frame_to_window_pixel_xy (w
, &x
, &y
);
6295 /* Handle tool-bar window differently since it doesn't display a
6297 if (EQ (window
, f
->tool_bar_window
))
6299 note_tool_bar_highlight (f
, x
, y
);
6303 if (portion
== 1 || portion
== 3)
6305 /* Mouse is on the mode or top line. */
6306 note_mode_line_highlight (w
, x
, portion
== 1);
6310 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6311 f
->output_data
.x
->text_cursor
);
6313 /* Are we in a window whose display is up to date?
6314 And verify the buffer's text has not changed. */
6315 if (/* Within text portion of the window. */
6317 && EQ (w
->window_end_valid
, w
->buffer
)
6318 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
6319 && (XFASTINT (w
->last_overlay_modified
)
6320 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
6322 int hpos
, vpos
, pos
, i
, area
;
6323 struct glyph
*glyph
;
6325 /* Find the glyph under X/Y. */
6326 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
);
6328 /* Clear mouse face if X/Y not over text. */
6330 || area
!= TEXT_AREA
6331 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6333 clear_mouse_face (dpyinfo
);
6337 pos
= glyph
->charpos
;
6338 xassert (w
->pseudo_window_p
|| BUFFERP (glyph
->object
));
6340 /* Check for mouse-face and help-echo. */
6342 Lisp_Object mouse_face
, overlay
, position
;
6343 Lisp_Object
*overlay_vec
;
6345 struct buffer
*obuf
;
6348 /* If we get an out-of-range value, return now; avoid an error. */
6349 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
6352 /* Make the window's buffer temporarily current for
6353 overlays_at and compute_char_face. */
6354 obuf
= current_buffer
;
6355 current_buffer
= XBUFFER (w
->buffer
);
6361 /* Is this char mouse-active or does it have help-echo? */
6362 XSETINT (position
, pos
);
6364 /* Put all the overlays we want in a vector in overlay_vec.
6365 Store the length in len. If there are more than 10, make
6366 enough space for all, and try again. */
6368 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6369 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6370 if (noverlays
> len
)
6373 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6374 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6377 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
6379 /* Check mouse-face highlighting. */
6380 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
6381 && vpos
>= dpyinfo
->mouse_face_beg_row
6382 && vpos
<= dpyinfo
->mouse_face_end_row
6383 && (vpos
> dpyinfo
->mouse_face_beg_row
6384 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6385 && (vpos
< dpyinfo
->mouse_face_end_row
6386 || hpos
< dpyinfo
->mouse_face_end_col
6387 || dpyinfo
->mouse_face_past_end
)))
6389 /* Clear the display of the old active region, if any. */
6390 clear_mouse_face (dpyinfo
);
6392 /* Find the highest priority overlay that has a mouse-face prop. */
6394 for (i
= 0; i
< noverlays
; i
++)
6396 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
6397 if (!NILP (mouse_face
))
6399 overlay
= overlay_vec
[i
];
6404 /* If no overlay applies, get a text property. */
6406 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
6408 /* Handle the overlay case. */
6409 if (! NILP (overlay
))
6411 /* Find the range of text around this char that
6412 should be active. */
6413 Lisp_Object before
, after
;
6416 before
= Foverlay_start (overlay
);
6417 after
= Foverlay_end (overlay
);
6418 /* Record this as the current active region. */
6419 fast_find_position (w
, XFASTINT (before
),
6420 &dpyinfo
->mouse_face_beg_col
,
6421 &dpyinfo
->mouse_face_beg_row
,
6422 &dpyinfo
->mouse_face_beg_x
,
6423 &dpyinfo
->mouse_face_beg_y
);
6424 dpyinfo
->mouse_face_past_end
6425 = !fast_find_position (w
, XFASTINT (after
),
6426 &dpyinfo
->mouse_face_end_col
,
6427 &dpyinfo
->mouse_face_end_row
,
6428 &dpyinfo
->mouse_face_end_x
,
6429 &dpyinfo
->mouse_face_end_y
);
6430 dpyinfo
->mouse_face_window
= window
;
6431 dpyinfo
->mouse_face_face_id
6432 = face_at_buffer_position (w
, pos
, 0, 0,
6433 &ignore
, pos
+ 1, 1);
6435 /* Display it as active. */
6436 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6438 /* Handle the text property case. */
6439 else if (! NILP (mouse_face
))
6441 /* Find the range of text around this char that
6442 should be active. */
6443 Lisp_Object before
, after
, beginning
, end
;
6446 beginning
= Fmarker_position (w
->start
);
6447 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
6448 - XFASTINT (w
->window_end_pos
)));
6450 = Fprevious_single_property_change (make_number (pos
+ 1),
6452 w
->buffer
, beginning
);
6454 = Fnext_single_property_change (position
, Qmouse_face
,
6456 /* Record this as the current active region. */
6457 fast_find_position (w
, XFASTINT (before
),
6458 &dpyinfo
->mouse_face_beg_col
,
6459 &dpyinfo
->mouse_face_beg_row
,
6460 &dpyinfo
->mouse_face_beg_x
,
6461 &dpyinfo
->mouse_face_beg_y
);
6462 dpyinfo
->mouse_face_past_end
6463 = !fast_find_position (w
, XFASTINT (after
),
6464 &dpyinfo
->mouse_face_end_col
,
6465 &dpyinfo
->mouse_face_end_row
,
6466 &dpyinfo
->mouse_face_end_x
,
6467 &dpyinfo
->mouse_face_end_y
);
6468 dpyinfo
->mouse_face_window
= window
;
6469 dpyinfo
->mouse_face_face_id
6470 = face_at_buffer_position (w
, pos
, 0, 0,
6471 &ignore
, pos
+ 1, 1);
6473 /* Display it as active. */
6474 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6478 /* Look for a `help-echo' property. */
6482 /* Check overlays first. */
6484 for (i
= 0; i
< noverlays
&& !STRINGP (help
); ++i
)
6485 help
= Foverlay_get (overlay_vec
[i
], Qhelp_echo
);
6487 /* Try text properties. */
6489 && ((STRINGP (glyph
->object
)
6490 && glyph
->charpos
>= 0
6491 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6492 || (BUFFERP (glyph
->object
)
6493 && glyph
->charpos
>= BEGV
6494 && glyph
->charpos
< ZV
)))
6495 help
= Fget_text_property (make_number (glyph
->charpos
),
6496 Qhelp_echo
, glyph
->object
);
6504 current_buffer
= obuf
;
6510 redo_mouse_highlight ()
6512 if (!NILP (last_mouse_motion_frame
)
6513 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
6514 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
6515 last_mouse_motion_event
.x
,
6516 last_mouse_motion_event
.y
);
6521 /***********************************************************************
6523 ***********************************************************************/
6525 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
6526 struct glyph
**, int *, int *, int *));
6528 /* Tool-bar item index of the item on which a mouse button was pressed
6531 static int last_tool_bar_item
;
6534 /* Get information about the tool-bar item at position X/Y on frame F.
6535 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6536 the current matrix of the tool-bar window of F, or NULL if not
6537 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6538 item in F->current_tool_bar_items. Value is
6540 -1 if X/Y is not on a tool-bar item
6541 0 if X/Y is on the same item that was highlighted before.
6545 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
6548 struct glyph
**glyph
;
6549 int *hpos
, *vpos
, *prop_idx
;
6551 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6552 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6555 /* Find the glyph under X/Y. */
6556 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
);
6560 /* Get the start of this tool-bar item's properties in
6561 f->current_tool_bar_items. */
6562 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
6565 /* Is mouse on the highlighted item? */
6566 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
6567 && *vpos
>= dpyinfo
->mouse_face_beg_row
6568 && *vpos
<= dpyinfo
->mouse_face_end_row
6569 && (*vpos
> dpyinfo
->mouse_face_beg_row
6570 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
6571 && (*vpos
< dpyinfo
->mouse_face_end_row
6572 || *hpos
< dpyinfo
->mouse_face_end_col
6573 || dpyinfo
->mouse_face_past_end
))
6580 /* Handle mouse button event on the tool-bar of frame F, at
6581 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6585 x_handle_tool_bar_click (f
, button_event
)
6587 XButtonEvent
*button_event
;
6589 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6590 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6591 int hpos
, vpos
, prop_idx
;
6592 struct glyph
*glyph
;
6593 Lisp_Object enabled_p
;
6594 int x
= button_event
->x
;
6595 int y
= button_event
->y
;
6597 /* If not on the highlighted tool-bar item, return. */
6598 frame_to_window_pixel_xy (w
, &x
, &y
);
6599 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
6602 /* If item is disabled, do nothing. */
6603 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6604 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6605 if (NILP (enabled_p
))
6608 if (button_event
->type
== ButtonPress
)
6610 /* Show item in pressed state. */
6611 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
6612 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
6613 last_tool_bar_item
= prop_idx
;
6617 Lisp_Object key
, frame
;
6618 struct input_event event
;
6620 /* Show item in released state. */
6621 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
6622 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
6624 key
= (XVECTOR (f
->current_tool_bar_items
)
6625 ->contents
[prop_idx
+ TOOL_BAR_ITEM_KEY
]);
6627 XSETFRAME (frame
, f
);
6628 event
.kind
= TOOL_BAR_EVENT
;
6629 event
.frame_or_window
= Fcons (frame
, Fcons (Qtool_bar
, Qnil
));
6630 kbd_buffer_store_event (&event
);
6632 event
.kind
= TOOL_BAR_EVENT
;
6633 event
.frame_or_window
= Fcons (frame
, key
);
6634 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6635 button_event
->state
);
6636 kbd_buffer_store_event (&event
);
6637 last_tool_bar_item
= -1;
6642 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6643 tool-bar window-relative coordinates X/Y. Called from
6644 note_mouse_highlight. */
6647 note_tool_bar_highlight (f
, x
, y
)
6651 Lisp_Object window
= f
->tool_bar_window
;
6652 struct window
*w
= XWINDOW (window
);
6653 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6655 struct glyph
*glyph
;
6656 struct glyph_row
*row
;
6658 Lisp_Object enabled_p
;
6660 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
6661 int mouse_down_p
, rc
;
6663 /* Function note_mouse_highlight is called with negative x(y
6664 values when mouse moves outside of the frame. */
6665 if (x
<= 0 || y
<= 0)
6667 clear_mouse_face (dpyinfo
);
6671 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
6674 /* Not on tool-bar item. */
6675 clear_mouse_face (dpyinfo
);
6679 /* On same tool-bar item as before. */
6682 clear_mouse_face (dpyinfo
);
6684 /* Mouse is down, but on different tool-bar item? */
6685 mouse_down_p
= (dpyinfo
->grabbed
6686 && f
== last_mouse_frame
6687 && FRAME_LIVE_P (f
));
6689 && last_tool_bar_item
!= prop_idx
)
6692 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
6693 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
6695 /* If tool-bar item is not enabled, don't highlight it. */
6696 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6697 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6698 if (!NILP (enabled_p
))
6700 /* Compute the x-position of the glyph. In front and past the
6701 image is a space. We include this is the highlighted area. */
6702 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6703 for (i
= x
= 0; i
< hpos
; ++i
)
6704 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
6706 /* Record this as the current active region. */
6707 dpyinfo
->mouse_face_beg_col
= hpos
;
6708 dpyinfo
->mouse_face_beg_row
= vpos
;
6709 dpyinfo
->mouse_face_beg_x
= x
;
6710 dpyinfo
->mouse_face_beg_y
= row
->y
;
6711 dpyinfo
->mouse_face_past_end
= 0;
6713 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
6714 dpyinfo
->mouse_face_end_row
= vpos
;
6715 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
6716 dpyinfo
->mouse_face_end_y
= row
->y
;
6717 dpyinfo
->mouse_face_window
= window
;
6718 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
6720 /* Display it as active. */
6721 show_mouse_face (dpyinfo
, draw
);
6722 dpyinfo
->mouse_face_image_state
= draw
;
6727 /* Set help_echo to a help string.to display for this tool-bar item.
6728 XTread_socket does the rest. */
6729 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6730 ->contents
[prop_idx
+ TOOL_BAR_ITEM_HELP
]);
6731 if (!STRINGP (help_echo
))
6732 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6733 ->contents
[prop_idx
+ TOOL_BAR_ITEM_CAPTION
]);
6738 /* Find the glyph matrix position of buffer position POS in window W.
6739 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6740 current glyphs must be up to date. If POS is above window start
6741 return (0, 0, 0, 0). If POS is after end of W, return end of
6745 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
)
6748 int *hpos
, *vpos
, *x
, *y
;
6752 int maybe_next_line_p
= 0;
6753 int line_start_position
;
6754 int yb
= window_text_bottom_y (w
);
6755 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0);
6756 struct glyph_row
*best_row
= row
;
6757 int row_vpos
= 0, best_row_vpos
= 0;
6762 if (row
->used
[TEXT_AREA
])
6763 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
6765 line_start_position
= 0;
6767 if (line_start_position
> pos
)
6769 /* If the position sought is the end of the buffer,
6770 don't include the blank lines at the bottom of the window. */
6771 else if (line_start_position
== pos
6772 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
6774 maybe_next_line_p
= 1;
6777 else if (line_start_position
> 0)
6780 best_row_vpos
= row_vpos
;
6787 /* Find the right column within BEST_ROW. */
6789 current_x
= best_row
->x
;
6790 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
6792 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
6795 charpos
= glyph
->charpos
;
6799 *vpos
= best_row_vpos
;
6804 else if (charpos
> pos
)
6806 else if (charpos
> 0)
6809 current_x
+= glyph
->pixel_width
;
6812 /* If we're looking for the end of the buffer,
6813 and we didn't find it in the line we scanned,
6814 use the start of the following line. */
6815 if (maybe_next_line_p
)
6820 current_x
= best_row
->x
;
6823 *vpos
= best_row_vpos
;
6824 *hpos
= lastcol
+ 1;
6831 /* Display the active region described by mouse_face_*
6832 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6835 show_mouse_face (dpyinfo
, draw
)
6836 struct x_display_info
*dpyinfo
;
6837 enum draw_glyphs_face draw
;
6839 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
6840 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6842 int cursor_off_p
= 0;
6843 struct cursor_pos saved_cursor
;
6845 saved_cursor
= output_cursor
;
6847 /* If window is in the process of being destroyed, don't bother
6849 if (w
->current_matrix
== NULL
)
6852 /* Recognize when we are called to operate on rows that don't exist
6853 anymore. This can happen when a window is split. */
6854 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
6857 set_output_cursor (&w
->phys_cursor
);
6859 /* Note that mouse_face_beg_row etc. are window relative. */
6860 for (i
= dpyinfo
->mouse_face_beg_row
;
6861 i
<= dpyinfo
->mouse_face_end_row
;
6864 int start_hpos
, end_hpos
, start_x
;
6865 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
6867 /* Don't do anything if row doesn't have valid contents. */
6868 if (!row
->enabled_p
)
6871 /* For all but the first row, the highlight starts at column 0. */
6872 if (i
== dpyinfo
->mouse_face_beg_row
)
6874 start_hpos
= dpyinfo
->mouse_face_beg_col
;
6875 start_x
= dpyinfo
->mouse_face_beg_x
;
6883 if (i
== dpyinfo
->mouse_face_end_row
)
6884 end_hpos
= dpyinfo
->mouse_face_end_col
;
6886 end_hpos
= row
->used
[TEXT_AREA
];
6888 /* If the cursor's in the text we are about to rewrite, turn the
6890 if (!w
->pseudo_window_p
6891 && i
== output_cursor
.vpos
6892 && output_cursor
.hpos
>= start_hpos
- 1
6893 && output_cursor
.hpos
<= end_hpos
)
6895 x_update_window_cursor (w
, 0);
6899 if (end_hpos
> start_hpos
)
6900 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
6901 start_hpos
, end_hpos
, draw
, NULL
, NULL
, 0);
6904 /* If we turned the cursor off, turn it back on. */
6906 x_display_cursor (w
, 1,
6907 output_cursor
.hpos
, output_cursor
.vpos
,
6908 output_cursor
.x
, output_cursor
.y
);
6910 output_cursor
= saved_cursor
;
6914 /* Change the mouse cursor. */
6915 if (draw
== DRAW_NORMAL_TEXT
)
6916 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6917 f
->output_data
.x
->text_cursor
);
6918 else if (draw
== DRAW_MOUSE_FACE
)
6919 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6920 f
->output_data
.x
->cross_cursor
);
6922 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6923 f
->output_data
.x
->nontext_cursor
);
6926 /* Clear out the mouse-highlighted active region.
6927 Redraw it un-highlighted first. */
6930 clear_mouse_face (dpyinfo
)
6931 struct x_display_info
*dpyinfo
;
6936 if (! NILP (dpyinfo
->mouse_face_window
))
6937 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
6939 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6940 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6941 dpyinfo
->mouse_face_window
= Qnil
;
6944 /* Just discard the mouse face information for frame F, if any.
6945 This is used when the size of F is changed. */
6948 cancel_mouse_face (f
)
6952 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6954 window
= dpyinfo
->mouse_face_window
;
6955 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
6957 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6958 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6959 dpyinfo
->mouse_face_window
= Qnil
;
6963 static struct scroll_bar
*x_window_to_scroll_bar ();
6964 static void x_scroll_bar_report_motion ();
6966 /* Return the current position of the mouse.
6967 *fp should be a frame which indicates which display to ask about.
6969 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6970 and *part to the frame, window, and scroll bar part that the mouse
6971 is over. Set *x and *y to the portion and whole of the mouse's
6972 position on the scroll bar.
6974 If the mouse movement started elsewhere, set *fp to the frame the
6975 mouse is on, *bar_window to nil, and *x and *y to the character cell
6978 Set *time to the server time-stamp for the time at which the mouse
6979 was at this position.
6981 Don't store anything if we don't have a valid set of values to report.
6983 This clears the mouse_moved flag, so we can wait for the next mouse
6987 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
6990 Lisp_Object
*bar_window
;
6991 enum scroll_bar_part
*part
;
6993 unsigned long *time
;
6999 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
7000 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
7006 Window dummy_window
;
7009 Lisp_Object frame
, tail
;
7011 /* Clear the mouse-moved flag for every frame on this display. */
7012 FOR_EACH_FRAME (tail
, frame
)
7013 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
7014 XFRAME (frame
)->mouse_moved
= 0;
7016 last_mouse_scroll_bar
= Qnil
;
7018 /* Figure out which root window we're on. */
7019 XQueryPointer (FRAME_X_DISPLAY (*fp
),
7020 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
7022 /* The root window which contains the pointer. */
7025 /* Trash which we can't trust if the pointer is on
7026 a different screen. */
7029 /* The position on that root window. */
7032 /* More trash we can't trust. */
7035 /* Modifier keys and pointer buttons, about which
7037 (unsigned int *) &dummy
);
7039 /* Now we have a position on the root; find the innermost window
7040 containing the pointer. */
7044 int parent_x
= 0, parent_y
= 0;
7049 /* XTranslateCoordinates can get errors if the window
7050 structure is changing at the same time this function
7051 is running. So at least we must not crash from them. */
7053 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
7055 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
7056 && FRAME_LIVE_P (last_mouse_frame
))
7058 /* If mouse was grabbed on a frame, give coords for that frame
7059 even if the mouse is now outside it. */
7060 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7062 /* From-window, to-window. */
7063 root
, FRAME_X_WINDOW (last_mouse_frame
),
7065 /* From-position, to-position. */
7066 root_x
, root_y
, &win_x
, &win_y
,
7070 f1
= last_mouse_frame
;
7076 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7078 /* From-window, to-window. */
7081 /* From-position, to-position. */
7082 root_x
, root_y
, &win_x
, &win_y
,
7087 if (child
== None
|| child
== win
)
7095 /* Now we know that:
7096 win is the innermost window containing the pointer
7097 (XTC says it has no child containing the pointer),
7098 win_x and win_y are the pointer's position in it
7099 (XTC did this the last time through), and
7100 parent_x and parent_y are the pointer's position in win's parent.
7101 (They are what win_x and win_y were when win was child.
7102 If win is the root window, it has no parent, and
7103 parent_{x,y} are invalid, but that's okay, because we'll
7104 never use them in that case.) */
7106 /* Is win one of our frames? */
7107 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
7110 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
7113 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
7115 /* If not, is it one of our scroll bars? */
7118 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
7122 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7128 if (f1
== 0 && insist
> 0)
7129 f1
= SELECTED_FRAME ();
7133 /* Ok, we found a frame. Store all the values.
7134 last_mouse_glyph is a rectangle used to reduce the
7135 generation of mouse events. To not miss any motion
7136 events, we must divide the frame into rectangles of the
7137 size of the smallest character that could be displayed
7138 on it, i.e. into the same rectangles that matrices on
7139 the frame are divided into. */
7141 #if OLD_REDISPLAY_CODE
7142 int ignore1
, ignore2
;
7143 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
7145 FRAME_X_DISPLAY_INFO (f1
)->grabbed
7149 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
7150 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
7154 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7155 round down even for negative values. */
7161 last_mouse_glyph
.width
= width
;
7162 last_mouse_glyph
.height
= height
;
7163 last_mouse_glyph
.x
= (x
+ width
- 1) / width
* width
;
7164 last_mouse_glyph
.y
= (y
+ height
- 1) / height
* height
;
7171 XSETINT (*x
, win_x
);
7172 XSETINT (*y
, win_y
);
7173 *time
= last_mouse_movement_time
;
7182 DEFUN ("xt-process-timeouts", Fxt_process_timeouts
, Sxt_process_timeouts
,
7184 "Arrange for Xt timeout callbacks to be called.")
7187 #ifdef USE_X_TOOLKIT
7189 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
7190 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
7192 #endif /* USE_X_TOOLKIT */
7199 /* Scroll bar support. */
7201 /* Given an X window ID, find the struct scroll_bar which manages it.
7202 This can be called in GC, so we have to make sure to strip off mark
7204 static struct scroll_bar
*
7205 x_window_to_scroll_bar (window_id
)
7210 for (tail
= Vframe_list
;
7211 XGCTYPE (tail
) == Lisp_Cons
;
7214 Lisp_Object frame
, bar
, condemned
;
7216 frame
= XCAR (tail
);
7217 /* All elements of Vframe_list should be frames. */
7218 if (! GC_FRAMEP (frame
))
7221 /* Scan this frame's scroll bar list for a scroll bar with the
7223 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
7224 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
7225 /* This trick allows us to search both the ordinary and
7226 condemned scroll bar lists with one loop. */
7227 ! GC_NILP (bar
) || (bar
= condemned
,
7230 bar
= XSCROLL_BAR (bar
)->next
)
7231 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
7232 return XSCROLL_BAR (bar
);
7240 /************************************************************************
7242 ************************************************************************/
7244 #if USE_TOOLKIT_SCROLL_BARS
7246 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
7247 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
7248 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
7249 struct scroll_bar
*));
7250 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
7254 /* Id of action hook installed for scroll bars. */
7256 static XtActionHookId action_hook_id
;
7258 /* Lisp window being scrolled. Set when starting to interact with
7259 a toolkit scroll bar, reset to nil when ending the interaction. */
7261 static Lisp_Object window_being_scrolled
;
7263 /* Last scroll bar part sent in xm_scroll_callback. */
7265 static int last_scroll_bar_part
;
7267 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7268 that movements of 1/20 of the screen size are mapped to up/down. */
7270 static Boolean xaw3d_arrow_scroll
;
7272 /* Whether the drag scrolling maintains the mouse at the top of the
7273 thumb. If not, resizing the thumb needs to be done more carefully
7274 to avoid jerkyness. */
7276 static Boolean xaw3d_pick_top
;
7279 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7280 bars are used.. The hook is responsible for detecting when
7281 the user ends an interaction with the scroll bar, and generates
7282 a `end-scroll' scroll_bar_click' event if so. */
7285 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
7288 XtPointer client_data
;
7292 Cardinal
*num_params
;
7298 scroll_bar_p
= XmIsScrollBar (widget
);
7299 end_action
= "Release";
7300 #else /* !USE_MOTIF i.e. use Xaw */
7301 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
7302 end_action
= "EndScroll";
7303 #endif /* USE_MOTIF */
7305 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
7306 let Xt timeouts be processed doesn't work. */
7308 && strcmp (action_name
, end_action
) == 0
7309 && WINDOWP (window_being_scrolled
))
7313 x_send_scroll_bar_event (window_being_scrolled
,
7314 scroll_bar_end_scroll
, 0, 0);
7315 w
= XWINDOW (window_being_scrolled
);
7316 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
7317 window_being_scrolled
= Qnil
;
7318 last_scroll_bar_part
= -1;
7323 /* Send a client message with message type Xatom_Scrollbar for a
7324 scroll action to the frame of WINDOW. PART is a value identifying
7325 the part of the scroll bar that was clicked on. PORTION is the
7326 amount to scroll of a whole of WHOLE. */
7329 x_send_scroll_bar_event (window
, part
, portion
, whole
)
7331 int part
, portion
, whole
;
7334 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
7335 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7337 /* Construct a ClientMessage event to send to the frame. */
7338 ev
->type
= ClientMessage
;
7339 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
7340 ev
->display
= FRAME_X_DISPLAY (f
);
7341 ev
->window
= FRAME_X_WINDOW (f
);
7343 ev
->data
.l
[0] = (long) window
;
7344 ev
->data
.l
[1] = (long) part
;
7345 ev
->data
.l
[2] = (long) 0;
7346 ev
->data
.l
[3] = (long) portion
;
7347 ev
->data
.l
[4] = (long) whole
;
7349 /* Setting the event mask to zero means that the message will
7350 be sent to the client that created the window, and if that
7351 window no longer exists, no event will be sent. */
7353 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
7358 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7362 x_scroll_bar_to_input_event (event
, ievent
)
7364 struct input_event
*ievent
;
7366 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
7367 Lisp_Object window
= (Lisp_Object
) ev
->data
.l
[0];
7368 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7370 ievent
->kind
= scroll_bar_click
;
7371 ievent
->frame_or_window
= window
;
7372 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
7373 ievent
->part
= ev
->data
.l
[1];
7374 ievent
->code
= ev
->data
.l
[2];
7375 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
7376 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
7377 ievent
->modifiers
= 0;
7383 /* Minimum and maximum values used for Motif scroll bars. */
7386 #define XM_SB_MAX 10000000
7387 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7390 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7391 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7392 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7395 xm_scroll_callback (widget
, client_data
, call_data
)
7397 XtPointer client_data
, call_data
;
7399 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7400 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
7402 int part
= -1, whole
= 0, portion
= 0;
7406 case XmCR_DECREMENT
:
7407 bar
->dragging
= Qnil
;
7408 part
= scroll_bar_up_arrow
;
7411 case XmCR_INCREMENT
:
7412 bar
->dragging
= Qnil
;
7413 part
= scroll_bar_down_arrow
;
7416 case XmCR_PAGE_DECREMENT
:
7417 bar
->dragging
= Qnil
;
7418 part
= scroll_bar_above_handle
;
7421 case XmCR_PAGE_INCREMENT
:
7422 bar
->dragging
= Qnil
;
7423 part
= scroll_bar_below_handle
;
7427 bar
->dragging
= Qnil
;
7428 part
= scroll_bar_to_top
;
7431 case XmCR_TO_BOTTOM
:
7432 bar
->dragging
= Qnil
;
7433 part
= scroll_bar_to_bottom
;
7439 int dragging_down_p
= (INTEGERP (bar
->dragging
)
7440 && XINT (bar
->dragging
) <= cs
->value
);
7442 /* Get the slider size. */
7444 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
7447 /* At the max position of the scroll bar, do a line-wise
7448 movement. Without doing anything, the LessTif scroll bar
7449 calls us with the same cs->value again and again. If we
7450 want to make sure that we can reach the end of the buffer,
7451 we have to do something.
7453 Implementation note: setting bar->dragging always to
7454 cs->value gives a smoother movement at the max position.
7455 Setting it to nil when doing line-wise movement gives
7456 a better slider behavior. */
7458 if (cs
->value
+ slider_size
== XM_SB_MAX
7460 && last_scroll_bar_part
== scroll_bar_down_arrow
))
7462 part
= scroll_bar_down_arrow
;
7463 bar
->dragging
= Qnil
;
7467 whole
= XM_SB_RANGE
;
7468 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
7469 part
= scroll_bar_handle
;
7470 bar
->dragging
= make_number (cs
->value
);
7475 case XmCR_VALUE_CHANGED
:
7481 window_being_scrolled
= bar
->window
;
7482 last_scroll_bar_part
= part
;
7483 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7488 #else /* !USE_MOTIF, i.e. Xaw. */
7491 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7492 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7493 scroll bar struct. CALL_DATA is a pointer to a float saying where
7497 xaw_jump_callback (widget
, client_data
, call_data
)
7499 XtPointer client_data
, call_data
;
7501 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7502 float top
= *(float *) call_data
;
7504 int whole
, portion
, height
;
7507 /* Get the size of the thumb, a value between 0 and 1. */
7509 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
7513 portion
= shown
< 1 ? top
* whole
: 0;
7515 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
7516 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7517 the bottom, so we force the scrolling whenever we see that we're
7518 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7519 we try to ensure that we always stay two pixels away from the
7521 part
= scroll_bar_down_arrow
;
7523 part
= scroll_bar_handle
;
7525 window_being_scrolled
= bar
->window
;
7526 bar
->dragging
= make_number (portion
);
7527 last_scroll_bar_part
= part
;
7528 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7532 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7533 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7534 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7535 the scroll bar. CALL_DATA is an integer specifying the action that
7536 has taken place. It's magnitude is in the range 0..height of the
7537 scroll bar. Negative values mean scroll towards buffer start.
7538 Values < height of scroll bar mean line-wise movement. */
7541 xaw_scroll_callback (widget
, client_data
, call_data
)
7543 XtPointer client_data
, call_data
;
7545 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7546 int position
= (int) call_data
;
7550 /* Get the height of the scroll bar. */
7552 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
7555 if (abs (position
) >= height
)
7556 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
7558 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7559 it maps line-movement to call_data = max(5, height/20). */
7560 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
7561 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
7563 part
= scroll_bar_move_ratio
;
7565 window_being_scrolled
= bar
->window
;
7566 bar
->dragging
= Qnil
;
7567 last_scroll_bar_part
= part
;
7568 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
7572 #endif /* not USE_MOTIF */
7575 /* Create the widget for scroll bar BAR on frame F. Record the widget
7576 and X window of the scroll bar in BAR. */
7579 x_create_toolkit_scroll_bar (f
, bar
)
7581 struct scroll_bar
*bar
;
7587 char *scroll_bar_name
= "verticalScrollBar";
7588 unsigned long pixel
;
7593 /* LessTif 0.85, problems:
7595 1. When the mouse if over the scroll bar, the scroll bar will
7596 get keyboard events. I didn't find a way to turn this off.
7598 2. Do we have to explicitly set the cursor to get an arrow
7599 cursor (see below)? */
7601 /* Set resources. Create the widget. */
7602 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7603 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
7604 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
7605 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
7606 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
7607 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
7608 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
7610 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7613 XtSetArg (av
[ac
], XmNforeground
, pixel
);
7617 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7620 XtSetArg (av
[ac
], XmNbackground
, pixel
);
7624 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
7625 scroll_bar_name
, av
, ac
);
7627 /* Add one callback for everything that can happen. */
7628 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
7630 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
7632 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
7634 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
7636 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
7638 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
7640 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
7643 /* Realize the widget. Only after that is the X window created. */
7644 XtRealizeWidget (widget
);
7646 /* Set the cursor to an arrow. I didn't find a resource to do that.
7647 And I'm wondering why it hasn't an arrow cursor by default. */
7648 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
7649 f
->output_data
.x
->nontext_cursor
);
7651 #else /* !USE_MOTIF i.e. use Xaw */
7653 /* Set resources. Create the widget. The background of the
7654 Xaw3d scroll bar widget is a little bit light for my taste.
7655 We don't alter it here to let users change it according
7656 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7657 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7658 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
7659 /* For smoother scrolling with Xaw3d -sm */
7660 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7661 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7663 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7666 XtSetArg (av
[ac
], XtNforeground
, pixel
);
7670 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7673 XtSetArg (av
[ac
], XtNbackground
, pixel
);
7677 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
7678 f
->output_data
.x
->edit_widget
, av
, ac
);
7682 char *val
= initial
;
7683 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
7684 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
7686 { /* ARROW_SCROLL */
7687 xaw3d_arrow_scroll
= True
;
7688 /* Isn't that just a personal preference ? -sm */
7689 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
7693 /* Define callbacks. */
7694 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
7695 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
7698 /* Realize the widget. Only after that is the X window created. */
7699 XtRealizeWidget (widget
);
7701 #endif /* !USE_MOTIF */
7703 /* Install an action hook that let's us detect when the user
7704 finishes interacting with a scroll bar. */
7705 if (action_hook_id
== 0)
7706 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
7708 /* Remember X window and widget in the scroll bar vector. */
7709 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
7710 xwindow
= XtWindow (widget
);
7711 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
7717 /* Set the thumb size and position of scroll bar BAR. We are currently
7718 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7721 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
7722 struct scroll_bar
*bar
;
7723 int portion
, position
, whole
;
7726 Widget widget
= SCROLL_BAR_X_WIDGET (bar
);
7732 top
= (float) position
/ whole
;
7733 shown
= (float) portion
/ whole
;
7741 Boolean arrow1_selected
, arrow2_selected
;
7742 unsigned char flags
;
7743 XmScrollBarWidget sb
;
7745 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7746 is the scroll bar's maximum and MIN is the scroll bar's minimum
7748 size
= shown
* XM_SB_RANGE
;
7749 size
= min (size
, XM_SB_RANGE
);
7750 size
= max (size
, 1);
7752 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7753 value
= top
* XM_SB_RANGE
;
7754 value
= min (value
, XM_SB_MAX
- size
);
7755 value
= max (value
, XM_SB_MIN
);
7757 /* LessTif: Calling XmScrollBarSetValues after an increment or
7758 decrement turns off auto-repeat LessTif-internally. This can
7759 be seen in ScrollBar.c which resets Arrow1Selected and
7760 Arrow2Selected. It also sets internal flags so that LessTif
7761 believes the mouse is in the slider. We either have to change
7762 our code, or work around that by accessing private data. */
7764 sb
= (XmScrollBarWidget
) widget
;
7765 arrow1_selected
= sb
->scrollBar
.arrow1_selected
;
7766 arrow2_selected
= sb
->scrollBar
.arrow2_selected
;
7767 flags
= sb
->scrollBar
.flags
;
7769 if (NILP (bar
->dragging
))
7770 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
7771 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7772 /* This has the negative side effect that the slider value is
7773 not what it would be if we scrolled here using line-wise or
7774 page-wise movement. */
7775 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
7778 /* If currently dragging, only update the slider size.
7779 This reduces flicker effects. */
7780 int old_value
, old_size
, increment
, page_increment
;
7782 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
7783 &increment
, &page_increment
);
7784 XmScrollBarSetValues (widget
, old_value
,
7785 min (size
, XM_SB_RANGE
- old_value
),
7789 sb
->scrollBar
.arrow1_selected
= arrow1_selected
;
7790 sb
->scrollBar
.arrow2_selected
= arrow2_selected
;
7791 sb
->scrollBar
.flags
= flags
;
7793 #else /* !USE_MOTIF i.e. use Xaw */
7795 float old_top
, old_shown
;
7797 XtVaGetValues (widget
,
7798 XtNtopOfThumb
, &old_top
,
7799 XtNshown
, &old_shown
,
7803 /* Massage the top+shown values. */
7804 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
7805 top
= max (0, min (1, top
));
7808 /* Keep two pixels available for moving the thumb down. */
7809 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
7811 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7812 check that your system's configuration file contains a define
7813 for `NARROWPROTO'. See s/freebsd.h for an example. */
7814 if (top
!= old_top
|| shown
!= old_shown
)
7816 if (NILP (bar
->dragging
))
7817 XawScrollbarSetThumb (widget
, top
, shown
);
7821 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
7824 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7825 if (xaw3d_arrow_scroll
)
7827 /* Xaw3d stupidly ignores resize requests while dragging
7828 so we have to make it believe it's not in dragging mode. */
7829 scroll_mode
= sb
->scrollbar
.scroll_mode
;
7830 if (scroll_mode
== 2)
7831 sb
->scrollbar
.scroll_mode
= 0;
7834 /* Try to make the scrolling a tad smoother. */
7835 if (!xaw3d_pick_top
)
7836 shown
= min (shown
, old_shown
);
7838 XawScrollbarSetThumb (widget
, top
, shown
);
7841 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
7842 sb
->scrollbar
.scroll_mode
= scroll_mode
;
7847 #endif /* !USE_MOTIF */
7852 #endif /* USE_TOOLKIT_SCROLL_BARS */
7856 /************************************************************************
7857 Scroll bars, general
7858 ************************************************************************/
7860 /* Create a scroll bar and return the scroll bar vector for it. W is
7861 the Emacs window on which to create the scroll bar. TOP, LEFT,
7862 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7865 static struct scroll_bar
*
7866 x_scroll_bar_create (w
, top
, left
, width
, height
)
7868 int top
, left
, width
, height
;
7870 struct frame
*f
= XFRAME (w
->frame
);
7871 struct scroll_bar
*bar
7872 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
7876 #if USE_TOOLKIT_SCROLL_BARS
7877 x_create_toolkit_scroll_bar (f
, bar
);
7878 #else /* not USE_TOOLKIT_SCROLL_BARS */
7880 XSetWindowAttributes a
;
7884 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7885 if (a
.background_pixel
== -1)
7886 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
7888 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
7889 | ButtonMotionMask
| PointerMotionHintMask
7891 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
7893 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
7895 /* Clear the area of W that will serve as a scroll bar. This is
7896 for the case that a window has been split horizontally. In
7897 this case, no clear_frame is generated to reduce flickering. */
7898 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7900 window_box_height (w
), False
);
7902 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7903 /* Position and size of scroll bar. */
7904 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7906 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7908 /* Border width, depth, class, and visual. */
7915 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
7917 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7919 XSETWINDOW (bar
->window
, w
);
7920 XSETINT (bar
->top
, top
);
7921 XSETINT (bar
->left
, left
);
7922 XSETINT (bar
->width
, width
);
7923 XSETINT (bar
->height
, height
);
7924 XSETINT (bar
->start
, 0);
7925 XSETINT (bar
->end
, 0);
7926 bar
->dragging
= Qnil
;
7928 /* Add bar to its frame's list of scroll bars. */
7929 bar
->next
= FRAME_SCROLL_BARS (f
);
7931 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
7932 if (!NILP (bar
->next
))
7933 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
7935 /* Map the window/widget. */
7936 #if USE_TOOLKIT_SCROLL_BARS
7937 XtMapWidget (SCROLL_BAR_X_WIDGET (bar
));
7938 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
7939 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7941 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7943 #else /* not USE_TOOLKIT_SCROLL_BARS */
7944 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
7945 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7952 /* Draw BAR's handle in the proper position.
7954 If the handle is already drawn from START to END, don't bother
7955 redrawing it, unless REBUILD is non-zero; in that case, always
7956 redraw it. (REBUILD is handy for drawing the handle after expose
7959 Normally, we want to constrain the start and end of the handle to
7960 fit inside its rectangle, but if the user is dragging the scroll
7961 bar handle, we want to let them drag it down all the way, so that
7962 the bar's top is as far down as it goes; otherwise, there's no way
7963 to move to the very end of the buffer. */
7965 #ifndef USE_TOOLKIT_SCROLL_BARS
7968 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
7969 struct scroll_bar
*bar
;
7973 int dragging
= ! NILP (bar
->dragging
);
7974 Window w
= SCROLL_BAR_X_WINDOW (bar
);
7975 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7976 GC gc
= f
->output_data
.x
->normal_gc
;
7978 /* If the display is already accurate, do nothing. */
7980 && start
== XINT (bar
->start
)
7981 && end
== XINT (bar
->end
))
7987 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
7988 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
7989 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
7991 /* Make sure the values are reasonable, and try to preserve
7992 the distance between start and end. */
7994 int length
= end
- start
;
7998 else if (start
> top_range
)
8000 end
= start
+ length
;
8004 else if (end
> top_range
&& ! dragging
)
8008 /* Store the adjusted setting in the scroll bar. */
8009 XSETINT (bar
->start
, start
);
8010 XSETINT (bar
->end
, end
);
8012 /* Clip the end position, just for display. */
8013 if (end
> top_range
)
8016 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8017 below top positions, to make sure the handle is always at least
8018 that many pixels tall. */
8019 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
8021 /* Draw the empty space above the handle. Note that we can't clear
8022 zero-height areas; that means "clear to end of window." */
8024 XClearArea (FRAME_X_DISPLAY (f
), w
,
8026 /* x, y, width, height, and exposures. */
8027 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8028 VERTICAL_SCROLL_BAR_TOP_BORDER
,
8029 inside_width
, start
,
8032 /* Change to proper foreground color if one is specified. */
8033 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8034 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8035 f
->output_data
.x
->scroll_bar_foreground_pixel
);
8037 /* Draw the handle itself. */
8038 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8040 /* x, y, width, height */
8041 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8042 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
8043 inside_width
, end
- start
);
8045 /* Restore the foreground color of the GC if we changed it above. */
8046 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8047 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8048 f
->output_data
.x
->foreground_pixel
);
8050 /* Draw the empty space below the handle. Note that we can't
8051 clear zero-height areas; that means "clear to end of window." */
8052 if (end
< inside_height
)
8053 XClearArea (FRAME_X_DISPLAY (f
), w
,
8055 /* x, y, width, height, and exposures. */
8056 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8057 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
8058 inside_width
, inside_height
- end
,
8066 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8068 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8072 x_scroll_bar_remove (bar
)
8073 struct scroll_bar
*bar
;
8077 #if USE_TOOLKIT_SCROLL_BARS
8078 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar
));
8079 #else /* not USE_TOOLKIT_SCROLL_BARS */
8081 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8082 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
8084 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8086 /* Disassociate this scroll bar from its window. */
8087 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
8093 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8094 that we are displaying PORTION characters out of a total of WHOLE
8095 characters, starting at POSITION. If WINDOW has no scroll bar,
8099 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
8101 int portion
, whole
, position
;
8103 struct frame
*f
= XFRAME (w
->frame
);
8104 struct scroll_bar
*bar
;
8105 int top
, height
, left
, sb_left
, width
, sb_width
;
8106 int window_x
, window_y
, window_width
, window_height
;
8108 /* Get window dimensions. */
8109 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8111 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8112 height
= window_height
;
8114 /* Compute the left edge of the scroll bar area. */
8115 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8116 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
8118 left
= XFASTINT (w
->left
);
8119 left
*= CANON_X_UNIT (f
);
8120 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
8122 /* Compute the width of the scroll bar which might be less than
8123 the width of the area reserved for the scroll bar. */
8124 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
8125 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
8129 /* Compute the left edge of the scroll bar. */
8130 #ifdef USE_TOOLKIT_SCROLL_BARS
8131 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8132 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
8134 sb_left
= left
+ (width
- sb_width
) / 2;
8136 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8137 sb_left
= left
+ width
- sb_width
;
8142 /* Does the scroll bar exist yet? */
8143 if (NILP (w
->vertical_scroll_bar
))
8146 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8147 left
, top
, width
, height
, False
);
8149 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
8153 /* It may just need to be moved and resized. */
8154 unsigned int mask
= 0;
8156 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
8160 if (sb_left
!= XINT (bar
->left
))
8162 if (top
!= XINT (bar
->top
))
8164 if (sb_width
!= XINT (bar
->width
))
8166 if (height
!= XINT (bar
->height
))
8169 #ifdef USE_TOOLKIT_SCROLL_BARS
8171 /* Since toolkit scroll bars are smaller than the space reserved
8172 for them on the frame, we have to clear "under" them. */
8173 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8174 left
, top
, width
, height
, False
);
8176 /* Move/size the scroll bar widget. */
8178 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
8179 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8181 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8184 #else /* not USE_TOOLKIT_SCROLL_BARS */
8186 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
8188 /* Clear areas not covered by the scroll bar. This makes sure a
8189 previous mode line display is cleared after C-x 2 C-x 1, for
8190 example. Non-toolkit scroll bars are as wide as the area
8191 reserved for scroll bars - trim at both sides. */
8192 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8193 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8195 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8196 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8197 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8201 /* Move/size the scroll bar window. */
8206 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8208 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
8210 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
8214 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8216 /* Remember new settings. */
8217 XSETINT (bar
->left
, sb_left
);
8218 XSETINT (bar
->top
, top
);
8219 XSETINT (bar
->width
, sb_width
);
8220 XSETINT (bar
->height
, height
);
8225 #if USE_TOOLKIT_SCROLL_BARS
8226 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
8227 #else /* not USE_TOOLKIT_SCROLL_BARS */
8228 /* Set the scroll bar's current state, unless we're currently being
8230 if (NILP (bar
->dragging
))
8232 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8235 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8238 int start
= ((double) position
* top_range
) / whole
;
8239 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8240 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8243 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8245 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8249 /* The following three hooks are used when we're doing a thorough
8250 redisplay of the frame. We don't explicitly know which scroll bars
8251 are going to be deleted, because keeping track of when windows go
8252 away is a real pain - "Can you say set-window-configuration, boys
8253 and girls?" Instead, we just assert at the beginning of redisplay
8254 that *all* scroll bars are to be removed, and then save a scroll bar
8255 from the fiery pit when we actually redisplay its window. */
8257 /* Arrange for all scroll bars on FRAME to be removed at the next call
8258 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8259 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8262 XTcondemn_scroll_bars (frame
)
8265 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8266 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8269 bar
= FRAME_SCROLL_BARS (frame
);
8270 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8271 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8272 XSCROLL_BAR (bar
)->prev
= Qnil
;
8273 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8274 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8275 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8279 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8280 Note that WINDOW isn't necessarily condemned at all. */
8282 XTredeem_scroll_bar (window
)
8283 struct window
*window
;
8285 struct scroll_bar
*bar
;
8287 /* We can't redeem this window's scroll bar if it doesn't have one. */
8288 if (NILP (window
->vertical_scroll_bar
))
8291 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8293 /* Unlink it from the condemned list. */
8295 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
8297 if (NILP (bar
->prev
))
8299 /* If the prev pointer is nil, it must be the first in one of
8301 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8302 /* It's not condemned. Everything's fine. */
8304 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8305 window
->vertical_scroll_bar
))
8306 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8308 /* If its prev pointer is nil, it must be at the front of
8309 one or the other! */
8313 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8315 if (! NILP (bar
->next
))
8316 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8318 bar
->next
= FRAME_SCROLL_BARS (f
);
8320 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8321 if (! NILP (bar
->next
))
8322 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8326 /* Remove all scroll bars on FRAME that haven't been saved since the
8327 last call to `*condemn_scroll_bars_hook'. */
8330 XTjudge_scroll_bars (f
)
8333 Lisp_Object bar
, next
;
8335 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8337 /* Clear out the condemned list now so we won't try to process any
8338 more events on the hapless scroll bars. */
8339 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8341 for (; ! NILP (bar
); bar
= next
)
8343 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8345 x_scroll_bar_remove (b
);
8348 b
->next
= b
->prev
= Qnil
;
8351 /* Now there should be no references to the condemned scroll bars,
8352 and they should get garbage-collected. */
8356 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8357 is a no-op when using toolkit scroll bars.
8359 This may be called from a signal handler, so we have to ignore GC
8363 x_scroll_bar_expose (bar
, event
)
8364 struct scroll_bar
*bar
;
8367 #ifndef USE_TOOLKIT_SCROLL_BARS
8369 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8370 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8371 GC gc
= f
->output_data
.x
->normal_gc
;
8372 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8376 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
8378 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8379 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8381 /* x, y, width, height */
8383 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
8384 XINT (bar
->height
) - 1);
8388 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8391 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8392 is set to something other than no_event, it is enqueued.
8394 This may be called from a signal handler, so we have to ignore GC
8397 #ifndef USE_TOOLKIT_SCROLL_BARS
8400 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
8401 struct scroll_bar
*bar
;
8403 struct input_event
*emacs_event
;
8405 if (! GC_WINDOWP (bar
->window
))
8408 emacs_event
->kind
= scroll_bar_click
;
8409 emacs_event
->code
= event
->xbutton
.button
- Button1
;
8410 emacs_event
->modifiers
8411 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8412 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
8413 event
->xbutton
.state
)
8414 | (event
->type
== ButtonRelease
8417 emacs_event
->frame_or_window
= bar
->window
;
8418 emacs_event
->timestamp
= event
->xbutton
.time
;
8421 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8423 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8426 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8427 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
8430 if (y
> top_range
) y
= top_range
;
8432 if (y
< XINT (bar
->start
))
8433 emacs_event
->part
= scroll_bar_above_handle
;
8434 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8435 emacs_event
->part
= scroll_bar_handle
;
8437 emacs_event
->part
= scroll_bar_below_handle
;
8439 /* Just because the user has clicked on the handle doesn't mean
8440 they want to drag it. Lisp code needs to be able to decide
8441 whether or not we're dragging. */
8443 /* If the user has just clicked on the handle, record where they're
8445 if (event
->type
== ButtonPress
8446 && emacs_event
->part
== scroll_bar_handle
)
8447 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
8450 /* If the user has released the handle, set it to its final position. */
8451 if (event
->type
== ButtonRelease
8452 && ! NILP (bar
->dragging
))
8454 int new_start
= y
- XINT (bar
->dragging
);
8455 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8457 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8458 bar
->dragging
= Qnil
;
8461 /* Same deal here as the other #if 0. */
8463 /* Clicks on the handle are always reported as occurring at the top of
8465 if (emacs_event
->part
== scroll_bar_handle
)
8466 emacs_event
->x
= bar
->start
;
8468 XSETINT (emacs_event
->x
, y
);
8470 XSETINT (emacs_event
->x
, y
);
8473 XSETINT (emacs_event
->y
, top_range
);
8477 /* Handle some mouse motion while someone is dragging the scroll bar.
8479 This may be called from a signal handler, so we have to ignore GC
8483 x_scroll_bar_note_movement (bar
, event
)
8484 struct scroll_bar
*bar
;
8487 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8489 last_mouse_movement_time
= event
->xmotion
.time
;
8492 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8494 /* If we're dragging the bar, display it. */
8495 if (! GC_NILP (bar
->dragging
))
8497 /* Where should the handle be now? */
8498 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
8500 if (new_start
!= XINT (bar
->start
))
8502 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8504 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8509 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8511 /* Return information to the user about the current position of the mouse
8512 on the scroll bar. */
8515 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8517 Lisp_Object
*bar_window
;
8518 enum scroll_bar_part
*part
;
8520 unsigned long *time
;
8522 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8523 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8524 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8526 Window dummy_window
;
8528 unsigned int dummy_mask
;
8532 /* Get the mouse's position relative to the scroll bar window, and
8534 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
8536 /* Root, child, root x and root y. */
8537 &dummy_window
, &dummy_window
,
8538 &dummy_coord
, &dummy_coord
,
8540 /* Position relative to scroll bar. */
8543 /* Mouse buttons and modifier keys. */
8550 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8553 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8555 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8557 if (! NILP (bar
->dragging
))
8558 win_y
-= XINT (bar
->dragging
);
8562 if (win_y
> top_range
)
8566 *bar_window
= bar
->window
;
8568 if (! NILP (bar
->dragging
))
8569 *part
= scroll_bar_handle
;
8570 else if (win_y
< XINT (bar
->start
))
8571 *part
= scroll_bar_above_handle
;
8572 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8573 *part
= scroll_bar_handle
;
8575 *part
= scroll_bar_below_handle
;
8577 XSETINT (*x
, win_y
);
8578 XSETINT (*y
, top_range
);
8581 last_mouse_scroll_bar
= Qnil
;
8584 *time
= last_mouse_movement_time
;
8590 /* The screen has been cleared so we may have changed foreground or
8591 background colors, and the scroll bars may need to be redrawn.
8592 Clear out the scroll bars, and ask for expose events, so we can
8596 x_scroll_bar_clear (f
)
8599 #ifndef USE_TOOLKIT_SCROLL_BARS
8602 /* We can have scroll bars even if this is 0,
8603 if we just turned off scroll bar mode.
8604 But in that case we should not clear them. */
8605 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8606 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
8607 bar
= XSCROLL_BAR (bar
)->next
)
8608 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
8610 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8613 /* This processes Expose events from the menu-bar specific X event
8614 loop in xmenu.c. This allows to redisplay the frame if necessary
8615 when handling menu-bar or pop-up items. */
8618 process_expose_from_menu (event
)
8622 struct x_display_info
*dpyinfo
;
8623 int frame_exposed_p
= 0;
8627 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
8628 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8631 if (f
->async_visible
== 0)
8633 f
->async_visible
= 1;
8634 f
->async_iconified
= 0;
8635 f
->output_data
.x
->has_been_visible
= 1;
8636 SET_FRAME_GARBAGED (f
);
8640 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
8641 event
.xexpose
.x
, event
.xexpose
.y
,
8642 event
.xexpose
.width
, event
.xexpose
.height
);
8643 frame_exposed_p
= 1;
8648 struct scroll_bar
*bar
8649 = x_window_to_scroll_bar (event
.xexpose
.window
);
8652 x_scroll_bar_expose (bar
, &event
);
8656 return frame_exposed_p
;
8659 /* Define a queue to save up SelectionRequest events for later handling. */
8661 struct selection_event_queue
8664 struct selection_event_queue
*next
;
8667 static struct selection_event_queue
*queue
;
8669 /* Nonzero means queue up certain events--don't process them yet. */
8671 static int x_queue_selection_requests
;
8673 /* Queue up an X event *EVENT, to be processed later. */
8676 x_queue_event (f
, event
)
8680 struct selection_event_queue
*queue_tmp
8681 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
8683 if (queue_tmp
!= NULL
)
8685 queue_tmp
->event
= *event
;
8686 queue_tmp
->next
= queue
;
8691 /* Take all the queued events and put them back
8692 so that they get processed afresh. */
8695 x_unqueue_events (display
)
8698 while (queue
!= NULL
)
8700 struct selection_event_queue
*queue_tmp
= queue
;
8701 XPutBackEvent (display
, &queue_tmp
->event
);
8702 queue
= queue_tmp
->next
;
8703 xfree ((char *)queue_tmp
);
8707 /* Start queuing SelectionRequest events. */
8710 x_start_queuing_selection_requests (display
)
8713 x_queue_selection_requests
++;
8716 /* Stop queuing SelectionRequest events. */
8719 x_stop_queuing_selection_requests (display
)
8722 x_queue_selection_requests
--;
8723 x_unqueue_events (display
);
8726 /* The main X event-reading loop - XTread_socket. */
8728 /* Time stamp of enter window event. This is only used by XTread_socket,
8729 but we have to put it out here, since static variables within functions
8730 sometimes don't work. */
8732 static Time enter_timestamp
;
8734 /* This holds the state XLookupString needs to implement dead keys
8735 and other tricks known as "compose processing". _X Window System_
8736 says that a portable program can't use this, but Stephen Gildea assures
8737 me that letting the compiler initialize it to zeros will work okay.
8739 This must be defined outside of XTread_socket, for the same reasons
8740 given for enter_time stamp, above. */
8742 static XComposeStatus compose_status
;
8744 /* Record the last 100 characters stored
8745 to help debug the loss-of-chars-during-GC problem. */
8747 static int temp_index
;
8748 static short temp_buffer
[100];
8750 /* Set this to nonzero to fake an "X I/O error"
8751 on a particular display. */
8753 struct x_display_info
*XTread_socket_fake_io_error
;
8755 /* When we find no input here, we occasionally do a no-op command
8756 to verify that the X server is still running and we can still talk with it.
8757 We try all the open displays, one by one.
8758 This variable is used for cycling thru the displays. */
8760 static struct x_display_info
*next_noop_dpyinfo
;
8762 #define SET_SAVED_MENU_EVENT(size) \
8765 if (f->output_data.x->saved_menu_event == 0) \
8766 f->output_data.x->saved_menu_event \
8767 = (XEvent *) xmalloc (sizeof (XEvent)); \
8768 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8769 if (numchars >= 1) \
8771 bufp->kind = menu_bar_activate_event; \
8772 XSETFRAME (bufp->frame_or_window, f); \
8780 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8781 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8783 /* Read events coming from the X server.
8784 This routine is called by the SIGIO handler.
8785 We return as soon as there are no more events to be read.
8787 Events representing keys are stored in buffer BUFP,
8788 which can hold up to NUMCHARS characters.
8789 We return the number of characters stored into the buffer,
8790 thus pretending to be `read'.
8792 EXPECTED is nonzero if the caller knows input is available. */
8795 XTread_socket (sd
, bufp
, numchars
, expected
)
8797 /* register */ struct input_event
*bufp
;
8798 /* register */ int numchars
;
8805 int event_found
= 0;
8806 struct x_display_info
*dpyinfo
;
8808 Status status_return
;
8811 if (interrupt_input_blocked
)
8813 interrupt_input_pending
= 1;
8817 interrupt_input_pending
= 0;
8820 /* So people can tell when we have read the available input. */
8821 input_signal_count
++;
8824 abort (); /* Don't think this happens. */
8826 /* Find the display we are supposed to read input for.
8827 It's the one communicating on descriptor SD. */
8828 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
8830 #if 0 /* This ought to be unnecessary; let's verify it. */
8832 /* If available, Xlib uses FIOSNBIO to make the socket
8833 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8834 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8835 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8836 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
8837 #endif /* ! defined (FIOSNBIO) */
8840 #if 0 /* This code can't be made to work, with multiple displays,
8841 and appears not to be used on any system any more.
8842 Also keyboard.c doesn't turn O_NDELAY on and off
8843 for X connections. */
8846 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
8848 extern int read_alarm_should_throw
;
8849 read_alarm_should_throw
= 1;
8850 XPeekEvent (dpyinfo
->display
, &event
);
8851 read_alarm_should_throw
= 0;
8853 #endif /* HAVE_SELECT */
8857 /* For debugging, this gives a way to fake an I/O error. */
8858 if (dpyinfo
== XTread_socket_fake_io_error
)
8860 XTread_socket_fake_io_error
= 0;
8861 x_io_error_quitter (dpyinfo
->display
);
8864 while (XPending (dpyinfo
->display
))
8866 XNextEvent (dpyinfo
->display
, &event
);
8868 if (display_busy_cursor_p
)
8870 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8871 display until the next X event is read and we come
8872 here again. Setting it to 1 inhibits busy-cursor
8873 display for direct commands. */
8874 if (event
.type
== MotionNotify
8875 || event
.type
== EnterNotify
8876 || (dpyinfo
->grabbed
8877 && event
.type
!= ButtonRelease
))
8878 inhibit_busy_cursor
= 2;
8880 inhibit_busy_cursor
= 1;
8885 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
8886 event
.xclient
.window
);
8887 /* The necessity of the following line took me
8888 a full work-day to decipher from the docs!! */
8889 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
8899 if (event
.xclient
.message_type
8900 == dpyinfo
->Xatom_wm_protocols
8901 && event
.xclient
.format
== 32)
8903 if (event
.xclient
.data
.l
[0]
8904 == dpyinfo
->Xatom_wm_take_focus
)
8906 /* Use x_any_window_to_frame because this
8907 could be the shell widget window
8908 if the frame has no title bar. */
8909 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8911 /* Not quite sure this is needed -pd */
8912 if (f
&& FRAME_XIC (f
))
8913 XSetICFocus (FRAME_XIC (f
));
8915 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8916 instructs the WM to set the input focus automatically for
8917 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8918 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8919 it has set the focus. So, XSetInputFocus below is not
8922 The call to XSetInputFocus below has also caused trouble. In
8923 cases where the XSetInputFocus done by the WM and the one
8924 below are temporally close (on a fast machine), the call
8925 below can generate additional FocusIn events which confuse
8928 /* Since we set WM_TAKE_FOCUS, we must call
8929 XSetInputFocus explicitly. But not if f is null,
8930 since that might be an event for a deleted frame. */
8933 Display
*d
= event
.xclient
.display
;
8934 /* Catch and ignore errors, in case window has been
8935 iconified by a window manager such as GWM. */
8936 int count
= x_catch_errors (d
);
8937 XSetInputFocus (d
, event
.xclient
.window
,
8938 /* The ICCCM says this is
8939 the only valid choice. */
8941 event
.xclient
.data
.l
[1]);
8942 /* This is needed to detect the error
8943 if there is an error. */
8945 x_uncatch_errors (d
, count
);
8947 /* Not certain about handling scroll bars here */
8950 else if (event
.xclient
.data
.l
[0]
8951 == dpyinfo
->Xatom_wm_save_yourself
)
8953 /* Save state modify the WM_COMMAND property to
8954 something which can reinstate us. This notifies
8955 the session manager, who's looking for such a
8956 PropertyNotify. Can restart processing when
8957 a keyboard or mouse event arrives. */
8960 f
= x_top_window_to_frame (dpyinfo
,
8961 event
.xclient
.window
);
8963 /* This is just so we only give real data once
8964 for a single Emacs process. */
8965 if (f
== SELECTED_FRAME ())
8966 XSetCommand (FRAME_X_DISPLAY (f
),
8967 event
.xclient
.window
,
8968 initial_argv
, initial_argc
);
8970 XSetCommand (FRAME_X_DISPLAY (f
),
8971 event
.xclient
.window
,
8975 else if (event
.xclient
.data
.l
[0]
8976 == dpyinfo
->Xatom_wm_delete_window
)
8979 = x_any_window_to_frame (dpyinfo
,
8980 event
.xclient
.window
);
8987 bufp
->kind
= delete_window_event
;
8988 XSETFRAME (bufp
->frame_or_window
, f
);
8996 else if (event
.xclient
.message_type
8997 == dpyinfo
->Xatom_wm_configure_denied
)
9000 else if (event
.xclient
.message_type
9001 == dpyinfo
->Xatom_wm_window_moved
)
9005 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9007 new_x
= event
.xclient
.data
.s
[0];
9008 new_y
= event
.xclient
.data
.s
[1];
9012 f
->output_data
.x
->left_pos
= new_x
;
9013 f
->output_data
.x
->top_pos
= new_y
;
9017 else if (event
.xclient
.message_type
9018 == dpyinfo
->Xatom_editres
)
9021 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
9022 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
9025 #endif /* HACK_EDITRES */
9026 else if ((event
.xclient
.message_type
9027 == dpyinfo
->Xatom_DONE
)
9028 || (event
.xclient
.message_type
9029 == dpyinfo
->Xatom_PAGE
))
9031 /* Ghostview job completed. Kill it. We could
9032 reply with "Next" if we received "Page", but we
9033 currently never do because we are interested in
9034 images, only, which should have 1 page. */
9035 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
9037 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9038 x_kill_gs_process (pixmap
, f
);
9039 expose_frame (f
, 0, 0, 0, 0);
9041 #ifdef USE_TOOLKIT_SCROLL_BARS
9042 /* Scroll bar callbacks send a ClientMessage from which
9043 we construct an input_event. */
9044 else if (event
.xclient
.message_type
9045 == dpyinfo
->Xatom_Scrollbar
)
9047 if (display_busy_cursor_p
)
9048 inhibit_busy_cursor
= 2;
9049 x_scroll_bar_to_input_event (&event
, bufp
);
9050 ++bufp
, ++count
, --numchars
;
9053 #endif /* USE_TOOLKIT_SCROLL_BARS */
9059 case SelectionNotify
:
9060 #ifdef USE_X_TOOLKIT
9061 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
9063 #endif /* not USE_X_TOOLKIT */
9064 x_handle_selection_notify (&event
.xselection
);
9067 case SelectionClear
: /* Someone has grabbed ownership. */
9068 #ifdef USE_X_TOOLKIT
9069 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
9071 #endif /* USE_X_TOOLKIT */
9073 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
9078 bufp
->kind
= selection_clear_event
;
9079 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9080 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9081 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9082 bufp
->frame_or_window
= Qnil
;
9090 case SelectionRequest
: /* Someone wants our selection. */
9091 #ifdef USE_X_TOOLKIT
9092 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
9094 #endif /* USE_X_TOOLKIT */
9095 if (x_queue_selection_requests
)
9096 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
9100 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
9105 bufp
->kind
= selection_request_event
;
9106 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9107 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
9108 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9109 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
9110 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
9111 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9112 bufp
->frame_or_window
= Qnil
;
9120 case PropertyNotify
:
9121 #ifdef USE_X_TOOLKIT
9122 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
9124 #endif /* not USE_X_TOOLKIT */
9125 x_handle_property_notify (&event
.xproperty
);
9128 case ReparentNotify
:
9129 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
9133 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
9134 x_real_positions (f
, &x
, &y
);
9135 f
->output_data
.x
->left_pos
= x
;
9136 f
->output_data
.x
->top_pos
= y
;
9141 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9144 if (f
->async_visible
== 0)
9146 f
->async_visible
= 1;
9147 f
->async_iconified
= 0;
9148 f
->output_data
.x
->has_been_visible
= 1;
9149 SET_FRAME_GARBAGED (f
);
9152 expose_frame (x_window_to_frame (dpyinfo
,
9153 event
.xexpose
.window
),
9154 event
.xexpose
.x
, event
.xexpose
.y
,
9155 event
.xexpose
.width
, event
.xexpose
.height
);
9159 #ifdef USE_TOOLKIT_SCROLL_BARS
9160 /* Dispatch event to the widget. */
9162 #else /* not USE_TOOLKIT_SCROLL_BARS */
9163 struct scroll_bar
*bar
9164 = x_window_to_scroll_bar (event
.xexpose
.window
);
9167 x_scroll_bar_expose (bar
, &event
);
9168 #ifdef USE_X_TOOLKIT
9171 #endif /* USE_X_TOOLKIT */
9172 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9176 case GraphicsExpose
: /* This occurs when an XCopyArea's
9177 source area was obscured or not
9179 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
9183 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
9184 event
.xgraphicsexpose
.width
,
9185 event
.xgraphicsexpose
.height
);
9187 #ifdef USE_X_TOOLKIT
9190 #endif /* USE_X_TOOLKIT */
9193 case NoExpose
: /* This occurs when an XCopyArea's
9194 source area was completely
9199 /* Redo the mouse-highlight after the tooltip has gone. */
9200 if (event
.xmap
.window
== tip_window
)
9203 redo_mouse_highlight ();
9206 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
9207 if (f
) /* F may no longer exist if
9208 the frame was deleted. */
9210 /* While a frame is unmapped, display generation is
9211 disabled; you don't want to spend time updating a
9212 display that won't ever be seen. */
9213 f
->async_visible
= 0;
9214 /* We can't distinguish, from the event, whether the window
9215 has become iconified or invisible. So assume, if it
9216 was previously visible, than now it is iconified.
9217 But x_make_frame_invisible clears both
9218 the visible flag and the iconified flag;
9219 and that way, we know the window is not iconified now. */
9220 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
9222 f
->async_iconified
= 1;
9224 bufp
->kind
= iconify_event
;
9225 XSETFRAME (bufp
->frame_or_window
, f
);
9234 if (event
.xmap
.window
== tip_window
)
9235 /* The tooltip has been drawn already. Avoid
9236 the SET_FRAME_GARBAGED below. */
9239 /* We use x_top_window_to_frame because map events can
9240 come for sub-windows and they don't mean that the
9241 frame is visible. */
9242 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
9245 f
->async_visible
= 1;
9246 f
->async_iconified
= 0;
9247 f
->output_data
.x
->has_been_visible
= 1;
9249 /* wait_reading_process_input will notice this and update
9250 the frame's display structures. */
9251 SET_FRAME_GARBAGED (f
);
9255 bufp
->kind
= deiconify_event
;
9256 XSETFRAME (bufp
->frame_or_window
, f
);
9261 else if (! NILP (Vframe_list
)
9262 && ! NILP (XCDR (Vframe_list
)))
9263 /* Force a redisplay sooner or later
9264 to update the frame titles
9265 in case this is the second frame. */
9266 record_asynch_buffer_change ();
9271 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
9274 /* I couldn't find a way to prevent LessTif scroll bars
9275 from consuming key events. */
9278 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
9280 if (widget
&& XmIsScrollBar (widget
))
9282 widget
= XtParent (widget
);
9283 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
9286 #endif /* USE_MOTIF */
9290 KeySym keysym
, orig_keysym
;
9291 /* al%imercury@uunet.uu.net says that making this 81 instead of
9292 80 fixed a bug whereby meta chars made his Emacs hang. */
9293 unsigned char copy_buffer
[81];
9297 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
9298 extra_keyboard_modifiers
);
9299 modifiers
= event
.xkey
.state
;
9301 /* This will have to go some day... */
9303 /* make_lispy_event turns chars into control chars.
9304 Don't do it here because XLookupString is too eager. */
9305 event
.xkey
.state
&= ~ControlMask
;
9306 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
9307 | dpyinfo
->super_mod_mask
9308 | dpyinfo
->hyper_mod_mask
9309 | dpyinfo
->alt_mod_mask
);
9311 /* In case Meta is ComposeCharacter,
9312 clear its status. According to Markus Ehrnsperger
9313 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9314 this enables ComposeCharacter to work whether or
9315 not it is combined with Meta. */
9316 if (modifiers
& dpyinfo
->meta_mod_mask
)
9317 bzero (&compose_status
, sizeof (compose_status
));
9322 /* The necessity of the following line took me
9323 a full work-day to decipher from the docs!! */
9324 if (XFilterEvent (&event
, None
))
9326 nbytes
= XmbLookupString (FRAME_XIC (f
),
9327 &event
.xkey
, copy_buffer
,
9330 if (status_return
== XLookupNone
)
9332 else if (status_return
== XLookupChars
)
9334 else if (status_return
!= XLookupKeySym
9335 && status_return
!= XLookupBoth
)
9339 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9340 80, &keysym
, &compose_status
);
9342 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9343 80, &keysym
, &compose_status
);
9346 orig_keysym
= keysym
;
9350 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
9351 || keysym
== XK_Delete
9352 #ifdef XK_ISO_Left_Tab
9353 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
9355 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
9356 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
9357 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
9359 /* This recognizes the "extended function keys".
9360 It seems there's no cleaner way.
9361 Test IsModifierKey to avoid handling mode_switch
9363 || ((unsigned) (keysym
) >= XK_Select
9364 && (unsigned)(keysym
) < XK_KP_Space
)
9366 #ifdef XK_dead_circumflex
9367 || orig_keysym
== XK_dead_circumflex
9369 #ifdef XK_dead_grave
9370 || orig_keysym
== XK_dead_grave
9372 #ifdef XK_dead_tilde
9373 || orig_keysym
== XK_dead_tilde
9375 #ifdef XK_dead_diaeresis
9376 || orig_keysym
== XK_dead_diaeresis
9378 #ifdef XK_dead_macron
9379 || orig_keysym
== XK_dead_macron
9381 #ifdef XK_dead_degree
9382 || orig_keysym
== XK_dead_degree
9384 #ifdef XK_dead_acute
9385 || orig_keysym
== XK_dead_acute
9387 #ifdef XK_dead_cedilla
9388 || orig_keysym
== XK_dead_cedilla
9390 #ifdef XK_dead_breve
9391 || orig_keysym
== XK_dead_breve
9393 #ifdef XK_dead_ogonek
9394 || orig_keysym
== XK_dead_ogonek
9396 #ifdef XK_dead_caron
9397 || orig_keysym
== XK_dead_caron
9399 #ifdef XK_dead_doubleacute
9400 || orig_keysym
== XK_dead_doubleacute
9402 #ifdef XK_dead_abovedot
9403 || orig_keysym
== XK_dead_abovedot
9405 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
9406 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
9407 /* Any "vendor-specific" key is ok. */
9408 || (orig_keysym
& (1 << 28)))
9409 && ! (IsModifierKey (orig_keysym
)
9411 #ifdef XK_Mode_switch
9412 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
9415 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
9417 #endif /* not HAVE_X11R5 */
9420 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9422 temp_buffer
[temp_index
++] = keysym
;
9423 bufp
->kind
= non_ascii_keystroke
;
9424 bufp
->code
= keysym
;
9425 XSETFRAME (bufp
->frame_or_window
, f
);
9427 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9429 bufp
->timestamp
= event
.xkey
.time
;
9434 if (display_busy_cursor_p
)
9435 if (keysym
!= XK_Return
|| minibuf_level
== 0)
9436 inhibit_busy_cursor
= 2;
9438 else if (numchars
> nbytes
)
9442 for (i
= 0; i
< nbytes
; i
++)
9444 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9446 temp_buffer
[temp_index
++] = copy_buffer
[i
];
9447 bufp
->kind
= ascii_keystroke
;
9448 bufp
->code
= copy_buffer
[i
];
9449 XSETFRAME (bufp
->frame_or_window
, f
);
9451 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9453 bufp
->timestamp
= event
.xkey
.time
;
9460 if (keysym
== NoSymbol
)
9471 /* Here's a possible interpretation of the whole
9472 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9473 you get a FocusIn event, you have to get a FocusOut
9474 event before you relinquish the focus. If you
9475 haven't received a FocusIn event, then a mere
9476 LeaveNotify is enough to free you. */
9480 int from_menu_bar_p
= 0;
9482 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9484 #ifdef LESSTIF_VERSION
9485 /* When clicking outside of a menu bar popup to close
9486 it, we get a FocusIn/ EnterNotify sequence of
9487 events. The flag event.xcrossing.focus is not set
9488 in the EnterNotify event of that sequence because
9489 the focus is in the menu bar,
9490 event.xcrossing.window is the frame's X window.
9491 Unconditionally setting the focus frame to null in
9492 this case is not the right thing, because no event
9493 follows that could set the focus frame to the right
9496 This could be a LessTif bug, but I wasn't able to
9497 reproduce the behavior in a simple test program.
9499 (gerd, LessTif 0.88.1). */
9501 if (!event
.xcrossing
.focus
9503 && f
->output_data
.x
->menubar_widget
)
9508 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9509 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9510 from_menu_bar_p
= 1;
9512 #endif /* LESSTIF_VERSION */
9514 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9516 /* Avoid nasty pop/raise loops. */
9517 if (f
&& (!(f
->auto_raise
)
9519 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
9521 x_new_focus_frame (dpyinfo
, f
);
9522 enter_timestamp
= event
.xcrossing
.time
;
9525 else if (f
== dpyinfo
->x_focus_frame
)
9526 x_new_focus_frame (dpyinfo
, 0);
9528 /* EnterNotify counts as mouse movement,
9529 so update things that depend on mouse position. */
9530 if (f
&& !f
->output_data
.x
->busy_p
)
9531 note_mouse_movement (f
, &event
.xmotion
);
9536 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9537 if (event
.xfocus
.detail
!= NotifyPointer
)
9538 dpyinfo
->x_focus_event_frame
= f
;
9540 x_new_focus_frame (dpyinfo
, f
);
9543 if (f
&& FRAME_XIC (f
))
9544 XSetICFocus (FRAME_XIC (f
));
9550 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9554 int from_menu_bar_p
= 0;
9556 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9558 /* If we move outside the frame, then we're
9559 certainly no longer on any text in the frame. */
9560 clear_mouse_face (dpyinfo
);
9561 dpyinfo
->mouse_face_mouse_frame
= 0;
9564 /* Generate a nil HELP_EVENT to cancel a help-echo.
9565 Do it only if there's something to cancel.
9566 Otherwise, the startup message is cleared when
9567 the mouse leaves the frame. */
9568 if (any_help_event_p
)
9570 XSETFRAME (frame
, f
);
9571 bufp
->kind
= HELP_EVENT
;
9572 bufp
->frame_or_window
= Fcons (frame
, Qnil
);
9573 ++bufp
, ++count
, --numchars
;
9576 #ifdef LESSTIF_VERSION
9577 /* Please see the comment at the start of the
9578 EnterNotify case. */
9579 if (!event
.xcrossing
.focus
9580 && f
->output_data
.x
->menubar_widget
)
9584 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9585 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9586 from_menu_bar_p
= 1;
9588 #endif /* LESSTIF_VERSION */
9590 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9591 x_mouse_leave (dpyinfo
);
9594 if (f
== dpyinfo
->x_focus_event_frame
)
9595 dpyinfo
->x_focus_event_frame
= 0;
9596 if (f
== dpyinfo
->x_focus_frame
)
9597 x_new_focus_frame (dpyinfo
, 0);
9603 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9604 if (event
.xfocus
.detail
!= NotifyPointer
9605 && f
== dpyinfo
->x_focus_event_frame
)
9606 dpyinfo
->x_focus_event_frame
= 0;
9607 if (f
&& f
== dpyinfo
->x_focus_frame
)
9608 x_new_focus_frame (dpyinfo
, 0);
9611 if (f
&& FRAME_XIC (f
))
9612 XUnsetICFocus (FRAME_XIC (f
));
9619 previous_help_echo
= help_echo
;
9622 if (dpyinfo
->grabbed
&& last_mouse_frame
9623 && FRAME_LIVE_P (last_mouse_frame
))
9624 f
= last_mouse_frame
;
9626 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
9629 note_mouse_movement (f
, &event
.xmotion
);
9632 #ifndef USE_TOOLKIT_SCROLL_BARS
9633 struct scroll_bar
*bar
9634 = x_window_to_scroll_bar (event
.xmotion
.window
);
9637 x_scroll_bar_note_movement (bar
, &event
);
9638 #endif /* USE_TOOLKIT_SCROLL_BARS */
9640 /* If we move outside the frame, then we're
9641 certainly no longer on any text in the frame. */
9642 clear_mouse_face (dpyinfo
);
9645 /* If the contents of the global variable help_echo
9646 has changed, generate a HELP_EVENT. */
9647 if (STRINGP (help_echo
)
9648 || STRINGP (previous_help_echo
))
9653 XSETFRAME (frame
, f
);
9657 any_help_event_p
= 1;
9658 bufp
->kind
= HELP_EVENT
;
9659 bufp
->frame_or_window
= Fcons (frame
, help_echo
);
9660 ++bufp
, ++count
, --numchars
;
9666 case ConfigureNotify
:
9667 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
9670 #ifndef USE_X_TOOLKIT
9671 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
9672 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
9674 /* In the toolkit version, change_frame_size
9675 is called by the code that handles resizing
9676 of the EmacsFrame widget. */
9678 /* Even if the number of character rows and columns has
9679 not changed, the font size may have changed, so we need
9680 to check the pixel dimensions as well. */
9681 if (columns
!= f
->width
9682 || rows
!= f
->height
9683 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
9684 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
9686 change_frame_size (f
, rows
, columns
, 0, 1, 0);
9687 SET_FRAME_GARBAGED (f
);
9688 cancel_mouse_face (f
);
9692 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
9693 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
9695 /* What we have now is the position of Emacs's own window.
9696 Convert that to the position of the window manager window. */
9697 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
9698 &f
->output_data
.x
->top_pos
);
9700 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
9702 /* Since the WM decorations come below top_pos now,
9703 we must put them below top_pos in the future. */
9704 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9705 x_wm_set_size_hint (f
, (long) 0, 0);
9708 /* Some window managers pass (0,0) as the location of
9709 the window, and the Motif event handler stores it
9710 in the emacs widget, which messes up Motif menus. */
9711 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
9713 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
9714 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
9716 #endif /* USE_MOTIF */
9723 /* If we decide we want to generate an event to be seen
9724 by the rest of Emacs, we put it here. */
9725 struct input_event emacs_event
;
9728 emacs_event
.kind
= no_event
;
9729 bzero (&compose_status
, sizeof (compose_status
));
9731 if (dpyinfo
->grabbed
9733 && FRAME_LIVE_P (last_mouse_frame
))
9734 f
= last_mouse_frame
;
9736 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9740 /* Is this in the tool-bar? */
9741 if (WINDOWP (f
->tool_bar_window
)
9742 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
9747 x
= event
.xbutton
.x
;
9748 y
= event
.xbutton
.y
;
9751 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
9752 if (EQ (window
, f
->tool_bar_window
))
9754 x_handle_tool_bar_click (f
, &event
.xbutton
);
9760 if (!dpyinfo
->x_focus_frame
9761 || f
== dpyinfo
->x_focus_frame
)
9762 construct_mouse_click (&emacs_event
, &event
, f
);
9766 #ifndef USE_TOOLKIT_SCROLL_BARS
9767 struct scroll_bar
*bar
9768 = x_window_to_scroll_bar (event
.xbutton
.window
);
9771 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
9772 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9775 if (event
.type
== ButtonPress
)
9777 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
9778 last_mouse_frame
= f
;
9779 /* Ignore any mouse motion that happened
9780 before this event; any subsequent mouse-movement
9781 Emacs events should reflect only motion after
9787 last_tool_bar_item
= -1;
9788 if (display_busy_cursor_p
)
9789 inhibit_busy_cursor
= 2;
9793 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
9796 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
9798 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
9804 #ifdef USE_X_TOOLKIT
9805 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9806 /* For a down-event in the menu bar,
9807 don't pass it to Xt right now.
9808 Instead, save it away
9809 and we will pass it to Xt from kbd_buffer_get_event.
9810 That way, we can run some Lisp code first. */
9811 if (f
&& event
.type
== ButtonPress
9812 /* Verify the event is really within the menu bar
9813 and not just sent to it due to grabbing. */
9814 && event
.xbutton
.x
>= 0
9815 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
9816 && event
.xbutton
.y
>= 0
9817 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
9818 && event
.xbutton
.same_screen
)
9820 SET_SAVED_BUTTON_EVENT
;
9821 XSETFRAME (last_mouse_press_frame
, f
);
9823 else if (event
.type
== ButtonPress
)
9825 last_mouse_press_frame
= Qnil
;
9829 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9830 but I am trying to be cautious. */
9831 else if (event
.type
== ButtonRelease
)
9833 if (!NILP (last_mouse_press_frame
))
9835 f
= XFRAME (last_mouse_press_frame
);
9836 if (f
->output_data
.x
)
9837 SET_SAVED_BUTTON_EVENT
;
9842 #endif /* USE_MOTIF */
9845 #endif /* USE_X_TOOLKIT */
9849 case CirculateNotify
:
9852 case CirculateRequest
:
9855 case VisibilityNotify
:
9859 /* Someone has changed the keyboard mapping - update the
9861 switch (event
.xmapping
.request
)
9863 case MappingModifier
:
9864 x_find_modifier_meanings (dpyinfo
);
9865 /* This is meant to fall through. */
9866 case MappingKeyboard
:
9867 XRefreshKeyboardMapping (&event
.xmapping
);
9873 #ifdef USE_X_TOOLKIT
9875 XtDispatchEvent (&event
);
9877 #endif /* USE_X_TOOLKIT */
9885 /* On some systems, an X bug causes Emacs to get no more events
9886 when the window is destroyed. Detect that. (1994.) */
9889 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9890 One XNOOP in 100 loops will make Emacs terminate.
9891 B. Bretthauer, 1994 */
9893 if (x_noop_count
>= 100)
9897 if (next_noop_dpyinfo
== 0)
9898 next_noop_dpyinfo
= x_display_list
;
9900 XNoOp (next_noop_dpyinfo
->display
);
9902 /* Each time we get here, cycle through the displays now open. */
9903 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
9907 /* If the focus was just given to an auto-raising frame,
9909 /* ??? This ought to be able to handle more than one such frame. */
9910 if (pending_autoraise_frame
)
9912 x_raise_frame (pending_autoraise_frame
);
9913 pending_autoraise_frame
= 0;
9923 /***********************************************************************
9925 ***********************************************************************/
9927 /* Note if the text cursor of window W has been overwritten by a
9928 drawing operation that outputs N glyphs starting at HPOS in the
9929 line given by output_cursor.vpos. N < 0 means all the rest of the
9930 line after HPOS has been written. */
9933 note_overwritten_text_cursor (w
, hpos
, n
)
9937 if (updated_area
== TEXT_AREA
9938 && output_cursor
.vpos
== w
->phys_cursor
.vpos
9939 && hpos
<= w
->phys_cursor
.hpos
9941 || hpos
+ n
> w
->phys_cursor
.hpos
))
9942 w
->phys_cursor_on_p
= 0;
9946 /* Set clipping for output in glyph row ROW. W is the window in which
9947 we operate. GC is the graphics context to set clipping in.
9948 WHOLE_LINE_P non-zero means include the areas used for truncation
9949 mark display and alike in the clipping rectangle.
9951 ROW may be a text row or, e.g., a mode line. Text rows must be
9952 clipped to the interior of the window dedicated to text display,
9953 mode lines must be clipped to the whole window. */
9956 x_clip_to_row (w
, row
, gc
, whole_line_p
)
9958 struct glyph_row
*row
;
9962 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9963 XRectangle clip_rect
;
9964 int window_x
, window_y
, window_width
, window_height
;
9966 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
9968 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
9969 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
9970 clip_rect
.y
= max (clip_rect
.y
, window_y
);
9971 clip_rect
.width
= window_width
;
9972 clip_rect
.height
= row
->visible_height
;
9974 /* If clipping to the whole line, including trunc marks, extend
9975 the rectangle to the left and increase its width. */
9978 clip_rect
.x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
9979 clip_rect
.width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
9982 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
9986 /* Draw a hollow box cursor on window W in glyph row ROW. */
9989 x_draw_hollow_cursor (w
, row
)
9991 struct glyph_row
*row
;
9993 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9994 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9995 Display
*dpy
= FRAME_X_DISPLAY (f
);
9998 struct glyph
*cursor_glyph
;
10001 /* Compute frame-relative coordinates from window-relative
10003 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10004 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
10005 + row
->ascent
- w
->phys_cursor_ascent
);
10006 h
= row
->height
- 1;
10008 /* Get the glyph the cursor is on. If we can't tell because
10009 the current matrix is invalid or such, give up. */
10010 cursor_glyph
= get_phys_cursor_glyph (w
);
10011 if (cursor_glyph
== NULL
)
10014 /* Compute the width of the rectangle to draw. If on a stretch
10015 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10016 rectangle as wide as the glyph, but use a canonical character
10018 wd
= cursor_glyph
->pixel_width
- 1;
10019 if (cursor_glyph
->type
== STRETCH_GLYPH
10020 && !x_stretch_cursor_p
)
10021 wd
= min (CANON_X_UNIT (f
), wd
);
10023 /* The foreground of cursor_gc is typically the same as the normal
10024 background color, which can cause the cursor box to be invisible. */
10025 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10026 if (dpyinfo
->scratch_cursor_gc
)
10027 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
10029 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
10030 GCForeground
, &xgcv
);
10031 gc
= dpyinfo
->scratch_cursor_gc
;
10033 /* Set clipping, draw the rectangle, and reset clipping again. */
10034 x_clip_to_row (w
, row
, gc
, 0);
10035 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
10036 XSetClipMask (dpy
, gc
, None
);
10040 /* Draw a bar cursor on window W in glyph row ROW.
10042 Implementation note: One would like to draw a bar cursor with an
10043 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10044 Unfortunately, I didn't find a font yet that has this property set.
10048 x_draw_bar_cursor (w
, row
)
10050 struct glyph_row
*row
;
10052 /* If cursor hpos is out of bounds, don't draw garbage. This can
10053 happen in mini-buffer windows when switching between echo area
10054 glyphs and mini-buffer. */
10055 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10057 struct frame
*f
= XFRAME (w
->frame
);
10058 struct glyph
*cursor_glyph
;
10061 unsigned long mask
;
10066 cursor_glyph
= get_phys_cursor_glyph (w
);
10067 if (cursor_glyph
== NULL
)
10070 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
10071 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10072 xgcv
.graphics_exposures
= 0;
10073 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
10074 dpy
= FRAME_X_DISPLAY (f
);
10075 window
= FRAME_X_WINDOW (f
);
10076 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
10079 XChangeGC (dpy
, gc
, mask
, &xgcv
);
10082 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
10083 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
10086 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10087 x_clip_to_row (w
, row
, gc
, 0);
10088 XFillRectangle (dpy
, window
, gc
,
10090 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
10091 min (cursor_glyph
->pixel_width
,
10092 f
->output_data
.x
->cursor_width
),
10094 XSetClipMask (dpy
, gc
, None
);
10099 /* Clear the cursor of window W to background color, and mark the
10100 cursor as not shown. This is used when the text where the cursor
10101 is is about to be rewritten. */
10107 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
10108 x_update_window_cursor (w
, 0);
10112 /* Draw the cursor glyph of window W in glyph row ROW. See the
10113 comment of x_draw_glyphs for the meaning of HL. */
10116 x_draw_phys_cursor_glyph (w
, row
, hl
)
10118 struct glyph_row
*row
;
10119 enum draw_glyphs_face hl
;
10121 /* If cursor hpos is out of bounds, don't draw garbage. This can
10122 happen in mini-buffer windows when switching between echo area
10123 glyphs and mini-buffer. */
10124 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10126 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
10127 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
10130 /* When we erase the cursor, and ROW is overlapped by other
10131 rows, make sure that these overlapping parts of other rows
10133 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
10135 if (row
> w
->current_matrix
->rows
10136 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
10137 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
10139 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
10140 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
10141 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
10147 /* Erase the image of a cursor of window W from the screen. */
10150 x_erase_phys_cursor (w
)
10153 struct frame
*f
= XFRAME (w
->frame
);
10154 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10155 int hpos
= w
->phys_cursor
.hpos
;
10156 int vpos
= w
->phys_cursor
.vpos
;
10157 int mouse_face_here_p
= 0;
10158 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
10159 struct glyph_row
*cursor_row
;
10160 struct glyph
*cursor_glyph
;
10161 enum draw_glyphs_face hl
;
10163 /* No cursor displayed or row invalidated => nothing to do on the
10165 if (w
->phys_cursor_type
== NO_CURSOR
)
10166 goto mark_cursor_off
;
10168 /* VPOS >= active_glyphs->nrows means that window has been resized.
10169 Don't bother to erase the cursor. */
10170 if (vpos
>= active_glyphs
->nrows
)
10171 goto mark_cursor_off
;
10173 /* If row containing cursor is marked invalid, there is nothing we
10175 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
10176 if (!cursor_row
->enabled_p
)
10177 goto mark_cursor_off
;
10179 /* This can happen when the new row is shorter than the old one.
10180 In this case, either x_draw_glyphs or clear_end_of_line
10181 should have cleared the cursor. Note that we wouldn't be
10182 able to erase the cursor in this case because we don't have a
10183 cursor glyph at hand. */
10184 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
10185 goto mark_cursor_off
;
10187 /* If the cursor is in the mouse face area, redisplay that when
10188 we clear the cursor. */
10189 if (w
== XWINDOW (dpyinfo
->mouse_face_window
)
10190 && (vpos
> dpyinfo
->mouse_face_beg_row
10191 || (vpos
== dpyinfo
->mouse_face_beg_row
10192 && hpos
>= dpyinfo
->mouse_face_beg_col
))
10193 && (vpos
< dpyinfo
->mouse_face_end_row
10194 || (vpos
== dpyinfo
->mouse_face_end_row
10195 && hpos
< dpyinfo
->mouse_face_end_col
))
10196 /* Don't redraw the cursor's spot in mouse face if it is at the
10197 end of a line (on a newline). The cursor appears there, but
10198 mouse highlighting does not. */
10199 && cursor_row
->used
[TEXT_AREA
] > hpos
)
10200 mouse_face_here_p
= 1;
10202 /* Maybe clear the display under the cursor. */
10203 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
10206 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
10208 cursor_glyph
= get_phys_cursor_glyph (w
);
10209 if (cursor_glyph
== NULL
)
10210 goto mark_cursor_off
;
10212 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
10214 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10216 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
10218 cursor_glyph
->pixel_width
,
10219 cursor_row
->visible_height
,
10223 /* Erase the cursor by redrawing the character underneath it. */
10224 if (mouse_face_here_p
)
10225 hl
= DRAW_MOUSE_FACE
;
10226 else if (cursor_row
->inverse_p
)
10227 hl
= DRAW_INVERSE_VIDEO
;
10229 hl
= DRAW_NORMAL_TEXT
;
10230 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
10233 w
->phys_cursor_on_p
= 0;
10234 w
->phys_cursor_type
= NO_CURSOR
;
10238 /* Display or clear cursor of window W. If ON is zero, clear the
10239 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10240 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10243 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
10245 int on
, hpos
, vpos
, x
, y
;
10247 struct frame
*f
= XFRAME (w
->frame
);
10248 int new_cursor_type
;
10249 struct glyph_matrix
*current_glyphs
;
10250 struct glyph_row
*glyph_row
;
10251 struct glyph
*glyph
;
10253 /* This is pointless on invisible frames, and dangerous on garbaged
10254 windows and frames; in the latter case, the frame or window may
10255 be in the midst of changing its size, and x and y may be off the
10257 if (! FRAME_VISIBLE_P (f
)
10258 || FRAME_GARBAGED_P (f
)
10259 || vpos
>= w
->current_matrix
->nrows
10260 || hpos
>= w
->current_matrix
->matrix_w
)
10263 /* If cursor is off and we want it off, return quickly. */
10264 if (!on
&& !w
->phys_cursor_on_p
)
10267 current_glyphs
= w
->current_matrix
;
10268 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
10269 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
10271 /* If cursor row is not enabled, we don't really know where to
10272 display the cursor. */
10273 if (!glyph_row
->enabled_p
)
10275 w
->phys_cursor_on_p
= 0;
10279 xassert (interrupt_input_blocked
);
10281 /* Set new_cursor_type to the cursor we want to be displayed. In a
10282 mini-buffer window, we want the cursor only to appear if we are
10283 reading input from this window. For the selected window, we want
10284 the cursor type given by the frame parameter. If explicitly
10285 marked off, draw no cursor. In all other cases, we want a hollow
10287 if (cursor_in_echo_area
10288 && FRAME_HAS_MINIBUF_P (f
)
10289 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
10291 if (w
== XWINDOW (echo_area_window
))
10292 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10294 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10298 if (w
!= XWINDOW (selected_window
)
10299 || f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
10301 if (MINI_WINDOW_P (w
))
10302 new_cursor_type
= NO_CURSOR
;
10304 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10306 else if (w
->cursor_off_p
)
10307 new_cursor_type
= NO_CURSOR
;
10309 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10312 /* If cursor is currently being shown and we don't want it to be or
10313 it is in the wrong place, or the cursor type is not what we want,
10315 if (w
->phys_cursor_on_p
10317 || w
->phys_cursor
.x
!= x
10318 || w
->phys_cursor
.y
!= y
10319 || new_cursor_type
!= w
->phys_cursor_type
))
10320 x_erase_phys_cursor (w
);
10322 /* If the cursor is now invisible and we want it to be visible,
10324 if (on
&& !w
->phys_cursor_on_p
)
10326 w
->phys_cursor_ascent
= glyph_row
->ascent
;
10327 w
->phys_cursor_height
= glyph_row
->height
;
10329 /* Set phys_cursor_.* before x_draw_.* is called because some
10330 of them may need the information. */
10331 w
->phys_cursor
.x
= x
;
10332 w
->phys_cursor
.y
= glyph_row
->y
;
10333 w
->phys_cursor
.hpos
= hpos
;
10334 w
->phys_cursor
.vpos
= vpos
;
10335 w
->phys_cursor_type
= new_cursor_type
;
10336 w
->phys_cursor_on_p
= 1;
10338 switch (new_cursor_type
)
10340 case HOLLOW_BOX_CURSOR
:
10341 x_draw_hollow_cursor (w
, glyph_row
);
10344 case FILLED_BOX_CURSOR
:
10345 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
10349 x_draw_bar_cursor (w
, glyph_row
);
10361 if (updating_frame
!= f
)
10362 XFlush (FRAME_X_DISPLAY (f
));
10367 /* Display the cursor on window W, or clear it. X and Y are window
10368 relative pixel coordinates. HPOS and VPOS are glyph matrix
10369 positions. If W is not the selected window, display a hollow
10370 cursor. ON non-zero means display the cursor at X, Y which
10371 correspond to HPOS, VPOS, otherwise it is cleared. */
10374 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
10376 int on
, hpos
, vpos
, x
, y
;
10379 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
10384 /* Display the cursor on window W, or clear it, according to ON_P.
10385 Don't change the cursor's position. */
10388 x_update_cursor (f
, on_p
)
10391 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
10395 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10396 in the window tree rooted at W. */
10399 x_update_cursor_in_window_tree (w
, on_p
)
10405 if (!NILP (w
->hchild
))
10406 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
10407 else if (!NILP (w
->vchild
))
10408 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
10410 x_update_window_cursor (w
, on_p
);
10412 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
10417 /* Switch the display of W's cursor on or off, according to the value
10421 x_update_window_cursor (w
, on
)
10426 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
10427 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
10436 /* Refresh bitmap kitchen sink icon for frame F
10437 when we get an expose event for it. */
10443 /* Normally, the window manager handles this function. */
10446 /* Make the x-window of frame F use the gnu icon bitmap. */
10449 x_bitmap_icon (f
, file
)
10455 if (FRAME_X_WINDOW (f
) == 0)
10458 /* Free up our existing icon bitmap if any. */
10459 if (f
->output_data
.x
->icon_bitmap
> 0)
10460 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10461 f
->output_data
.x
->icon_bitmap
= 0;
10463 if (STRINGP (file
))
10464 bitmap_id
= x_create_bitmap_from_file (f
, file
);
10467 /* Create the GNU bitmap if necessary. */
10468 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
10469 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
10470 = x_create_bitmap_from_data (f
, gnu_bits
,
10471 gnu_width
, gnu_height
);
10473 /* The first time we create the GNU bitmap,
10474 this increments the ref-count one extra time.
10475 As a result, the GNU bitmap is never freed.
10476 That way, we don't have to worry about allocating it again. */
10477 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
10479 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
10482 x_wm_set_icon_pixmap (f
, bitmap_id
);
10483 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
10489 /* Make the x-window of frame F use a rectangle with text.
10490 Use ICON_NAME as the text. */
10493 x_text_icon (f
, icon_name
)
10497 if (FRAME_X_WINDOW (f
) == 0)
10502 XTextProperty text
;
10503 text
.value
= (unsigned char *) icon_name
;
10504 text
.encoding
= XA_STRING
;
10506 text
.nitems
= strlen (icon_name
);
10507 #ifdef USE_X_TOOLKIT
10508 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10510 #else /* not USE_X_TOOLKIT */
10511 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
10512 #endif /* not USE_X_TOOLKIT */
10514 #else /* not HAVE_X11R4 */
10515 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
10516 #endif /* not HAVE_X11R4 */
10518 if (f
->output_data
.x
->icon_bitmap
> 0)
10519 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10520 f
->output_data
.x
->icon_bitmap
= 0;
10521 x_wm_set_icon_pixmap (f
, 0);
10526 #define X_ERROR_MESSAGE_SIZE 200
10528 /* If non-nil, this should be a string.
10529 It means catch X errors and store the error message in this string. */
10531 static Lisp_Object x_error_message_string
;
10533 /* An X error handler which stores the error message in
10534 x_error_message_string. This is called from x_error_handler if
10535 x_catch_errors is in effect. */
10538 x_error_catcher (display
, error
)
10540 XErrorEvent
*error
;
10542 XGetErrorText (display
, error
->error_code
,
10543 XSTRING (x_error_message_string
)->data
,
10544 X_ERROR_MESSAGE_SIZE
);
10547 /* Begin trapping X errors for display DPY. Actually we trap X errors
10548 for all displays, but DPY should be the display you are actually
10551 After calling this function, X protocol errors no longer cause
10552 Emacs to exit; instead, they are recorded in the string
10553 stored in x_error_message_string.
10555 Calling x_check_errors signals an Emacs error if an X error has
10556 occurred since the last call to x_catch_errors or x_check_errors.
10558 Calling x_uncatch_errors resumes the normal error handling. */
10560 void x_check_errors ();
10561 static Lisp_Object
x_catch_errors_unwind ();
10564 x_catch_errors (dpy
)
10567 int count
= specpdl_ptr
- specpdl
;
10569 /* Make sure any errors from previous requests have been dealt with. */
10570 XSync (dpy
, False
);
10572 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
10574 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
10575 XSTRING (x_error_message_string
)->data
[0] = 0;
10580 /* Unbind the binding that we made to check for X errors. */
10583 x_catch_errors_unwind (old_val
)
10584 Lisp_Object old_val
;
10586 x_error_message_string
= old_val
;
10590 /* If any X protocol errors have arrived since the last call to
10591 x_catch_errors or x_check_errors, signal an Emacs error using
10592 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10595 x_check_errors (dpy
, format
)
10599 /* Make sure to catch any errors incurred so far. */
10600 XSync (dpy
, False
);
10602 if (XSTRING (x_error_message_string
)->data
[0])
10603 error (format
, XSTRING (x_error_message_string
)->data
);
10606 /* Nonzero if we had any X protocol errors
10607 since we did x_catch_errors on DPY. */
10610 x_had_errors_p (dpy
)
10613 /* Make sure to catch any errors incurred so far. */
10614 XSync (dpy
, False
);
10616 return XSTRING (x_error_message_string
)->data
[0] != 0;
10619 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10622 x_clear_errors (dpy
)
10625 XSTRING (x_error_message_string
)->data
[0] = 0;
10628 /* Stop catching X protocol errors and let them make Emacs die.
10629 DPY should be the display that was passed to x_catch_errors.
10630 COUNT should be the value that was returned by
10631 the corresponding call to x_catch_errors. */
10634 x_uncatch_errors (dpy
, count
)
10638 unbind_to (count
, Qnil
);
10642 static unsigned int x_wire_count
;
10645 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
10650 /* Handle SIGPIPE, which can happen when the connection to a server
10651 simply goes away. SIGPIPE is handled by x_connection_signal.
10652 Don't need to do anything, because the write which caused the
10653 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10654 which will do the appropriate cleanup for us. */
10657 x_connection_signal (signalnum
) /* If we don't have an argument, */
10658 int signalnum
; /* some compilers complain in signal calls. */
10661 /* USG systems forget handlers when they are used;
10662 must reestablish each time */
10663 signal (signalnum
, x_connection_signal
);
10667 /* Handling X errors. */
10669 /* Handle the loss of connection to display DISPLAY. */
10672 x_connection_closed (display
, error_message
)
10674 char *error_message
;
10676 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
10677 Lisp_Object frame
, tail
;
10679 /* Indicate that this display is dead. */
10681 #ifdef USE_X_TOOLKIT
10682 XtCloseDisplay (display
);
10685 dpyinfo
->display
= 0;
10687 /* First delete frames whose mini-buffers are on frames
10688 that are on the dead display. */
10689 FOR_EACH_FRAME (tail
, frame
)
10691 Lisp_Object minibuf_frame
;
10693 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
10694 if (FRAME_X_P (XFRAME (frame
))
10695 && FRAME_X_P (XFRAME (minibuf_frame
))
10696 && ! EQ (frame
, minibuf_frame
)
10697 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
10698 Fdelete_frame (frame
, Qt
);
10701 /* Now delete all remaining frames on the dead display.
10702 We are now sure none of these is used as the mini-buffer
10703 for another frame that we need to delete. */
10704 FOR_EACH_FRAME (tail
, frame
)
10705 if (FRAME_X_P (XFRAME (frame
))
10706 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
10708 /* Set this to t so that Fdelete_frame won't get confused
10709 trying to find a replacement. */
10710 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
10711 Fdelete_frame (frame
, Qt
);
10715 x_delete_display (dpyinfo
);
10717 if (x_display_list
== 0)
10719 fprintf (stderr
, "%s\n", error_message
);
10720 shut_down_emacs (0, 0, Qnil
);
10724 /* Ordinary stack unwind doesn't deal with these. */
10726 sigunblock (sigmask (SIGIO
));
10728 sigunblock (sigmask (SIGALRM
));
10729 TOTALLY_UNBLOCK_INPUT
;
10731 clear_waiting_for_input ();
10732 error ("%s", error_message
);
10735 /* This is the usual handler for X protocol errors.
10736 It kills all frames on the display that we got the error for.
10737 If that was the only one, it prints an error message and kills Emacs. */
10740 x_error_quitter (display
, error
)
10742 XErrorEvent
*error
;
10744 char buf
[256], buf1
[356];
10746 /* Note that there is no real way portable across R3/R4 to get the
10747 original error handler. */
10749 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
10750 sprintf (buf1
, "X protocol error: %s on protocol request %d",
10751 buf
, error
->request_code
);
10752 x_connection_closed (display
, buf1
);
10755 /* This is the first-level handler for X protocol errors.
10756 It calls x_error_quitter or x_error_catcher. */
10759 x_error_handler (display
, error
)
10761 XErrorEvent
*error
;
10763 if (! NILP (x_error_message_string
))
10764 x_error_catcher (display
, error
);
10766 x_error_quitter (display
, error
);
10770 /* This is the handler for X IO errors, always.
10771 It kills all frames on the display that we lost touch with.
10772 If that was the only one, it prints an error message and kills Emacs. */
10775 x_io_error_quitter (display
)
10780 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
10781 x_connection_closed (display
, buf
);
10785 /* Changing the font of the frame. */
10787 /* Give frame F the font named FONTNAME as its default font, and
10788 return the full name of that font. FONTNAME may be a wildcard
10789 pattern; in that case, we choose some font that fits the pattern.
10790 The return value shows which font we chose. */
10793 x_new_font (f
, fontname
)
10795 register char *fontname
;
10797 struct font_info
*fontp
10798 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
10803 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
10804 f
->output_data
.x
->baseline_offset
= fontp
->baseline_offset
;
10805 f
->output_data
.x
->fontset
= -1;
10807 /* Compute the scroll bar width in character columns. */
10808 if (f
->scroll_bar_pixel_width
> 0)
10810 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10811 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
10815 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10816 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
10819 /* Now make the frame display the given font. */
10820 if (FRAME_X_WINDOW (f
) != 0)
10822 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
10823 f
->output_data
.x
->font
->fid
);
10824 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
10825 f
->output_data
.x
->font
->fid
);
10826 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
10827 f
->output_data
.x
->font
->fid
);
10829 frame_update_line_height (f
);
10830 x_set_window_size (f
, 0, f
->width
, f
->height
);
10833 /* If we are setting a new frame's font for the first time,
10834 there are no faces yet, so this font's height is the line height. */
10835 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
10837 return build_string (fontp
->full_name
);
10840 /* Give frame F the fontset named FONTSETNAME as its default font, and
10841 return the full name of that fontset. FONTSETNAME may be a wildcard
10842 pattern; in that case, we choose some fontset that fits the pattern.
10843 The return value shows which fontset we chose. */
10846 x_new_fontset (f
, fontsetname
)
10850 int fontset
= fs_query_fontset (f
, fontsetname
);
10851 struct fontset_info
*fontsetp
;
10852 Lisp_Object result
;
10857 if (f
->output_data
.x
->fontset
== fontset
)
10858 /* This fontset is already set in frame F. There's nothing more
10860 return build_string (fontsetname
);
10862 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
10864 if (!fontsetp
->fontname
[CHARSET_ASCII
])
10865 /* This fontset doesn't contain ASCII font. */
10868 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
10870 if (!STRINGP (result
))
10871 /* Can't load ASCII font. */
10874 /* Since x_new_font doesn't update any fontset information, do it now. */
10875 f
->output_data
.x
->fontset
= fontset
;
10876 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
10877 CHARSET_ASCII
, fontsetp
->fontname
[CHARSET_ASCII
], fontset
);
10879 return build_string (fontsetname
);
10882 /* Calculate the absolute position in frame F
10883 from its current recorded position values and gravity. */
10886 x_calc_absolute_position (f
)
10890 int win_x
= 0, win_y
= 0;
10891 int flags
= f
->output_data
.x
->size_hint_flags
;
10894 /* We have nothing to do if the current position
10895 is already for the top-left corner. */
10896 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
10899 #ifdef USE_X_TOOLKIT
10900 this_window
= XtWindow (f
->output_data
.x
->widget
);
10902 this_window
= FRAME_X_WINDOW (f
);
10905 /* Find the position of the outside upper-left corner of
10906 the inner window, with respect to the outer window.
10907 But do this only if we will need the results. */
10908 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
10913 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
10916 x_clear_errors (FRAME_X_DISPLAY (f
));
10917 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
10919 /* From-window, to-window. */
10921 f
->output_data
.x
->parent_desc
,
10923 /* From-position, to-position. */
10924 0, 0, &win_x
, &win_y
,
10926 /* Child of win. */
10928 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
10930 Window newroot
, newparent
= 0xdeadbeef;
10931 Window
*newchildren
;
10934 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
10935 &newparent
, &newchildren
, &nchildren
))
10938 XFree ((char *) newchildren
);
10940 f
->output_data
.x
->parent_desc
= newparent
;
10946 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
10950 /* Treat negative positions as relative to the leftmost bottommost
10951 position that fits on the screen. */
10952 if (flags
& XNegative
)
10953 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
10954 - 2 * f
->output_data
.x
->border_width
- win_x
10956 + f
->output_data
.x
->left_pos
);
10958 if (flags
& YNegative
)
10960 int menubar_height
= 0;
10962 #ifdef USE_X_TOOLKIT
10963 if (f
->output_data
.x
->menubar_widget
)
10965 = (f
->output_data
.x
->menubar_widget
->core
.height
10966 + f
->output_data
.x
->menubar_widget
->core
.border_width
);
10969 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
10970 - 2 * f
->output_data
.x
->border_width
10974 + f
->output_data
.x
->top_pos
);
10977 /* The left_pos and top_pos
10978 are now relative to the top and left screen edges,
10979 so the flags should correspond. */
10980 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10983 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10984 to really change the position, and 0 when calling from
10985 x_make_frame_visible (in that case, XOFF and YOFF are the current
10986 position values). It is -1 when calling from x_set_frame_parameters,
10987 which means, do adjust for borders but don't change the gravity. */
10990 x_set_offset (f
, xoff
, yoff
, change_gravity
)
10992 register int xoff
, yoff
;
10993 int change_gravity
;
10995 int modified_top
, modified_left
;
10997 if (change_gravity
> 0)
10999 f
->output_data
.x
->top_pos
= yoff
;
11000 f
->output_data
.x
->left_pos
= xoff
;
11001 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
11003 f
->output_data
.x
->size_hint_flags
|= XNegative
;
11005 f
->output_data
.x
->size_hint_flags
|= YNegative
;
11006 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11008 x_calc_absolute_position (f
);
11011 x_wm_set_size_hint (f
, (long) 0, 0);
11013 modified_left
= f
->output_data
.x
->left_pos
;
11014 modified_top
= f
->output_data
.x
->top_pos
;
11015 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11016 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11017 /* It is a mystery why we need to add the border_width here
11018 when the frame is already visible, but experiment says we do. */
11019 if (change_gravity
!= 0)
11021 modified_left
+= f
->output_data
.x
->border_width
;
11022 modified_top
+= f
->output_data
.x
->border_width
;
11026 #ifdef USE_X_TOOLKIT
11027 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
11028 modified_left
, modified_top
);
11029 #else /* not USE_X_TOOLKIT */
11030 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11031 modified_left
, modified_top
);
11032 #endif /* not USE_X_TOOLKIT */
11036 /* Call this to change the size of frame F's x-window.
11037 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11038 for this size change and subsequent size changes.
11039 Otherwise we leave the window gravity unchanged. */
11042 x_set_window_size (f
, change_gravity
, cols
, rows
)
11044 int change_gravity
;
11047 #ifndef USE_X_TOOLKIT
11048 int pixelwidth
, pixelheight
;
11053 #ifdef USE_X_TOOLKIT
11055 /* The x and y position of the widget is clobbered by the
11056 call to XtSetValues within EmacsFrameSetCharSize.
11057 This is a real kludge, but I don't understand Xt so I can't
11058 figure out a correct fix. Can anyone else tell me? -- rms. */
11059 int xpos
= f
->output_data
.x
->widget
->core
.x
;
11060 int ypos
= f
->output_data
.x
->widget
->core
.y
;
11061 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
11062 f
->output_data
.x
->widget
->core
.x
= xpos
;
11063 f
->output_data
.x
->widget
->core
.y
= ypos
;
11066 #else /* not USE_X_TOOLKIT */
11068 check_frame_size (f
, &rows
, &cols
);
11069 f
->output_data
.x
->vertical_scroll_bar_extra
11070 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
11072 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
11073 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
11074 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
11075 f
->output_data
.x
->flags_areas_extra
11076 = FRAME_FLAGS_AREA_WIDTH (f
);
11077 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
11078 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
11080 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11081 x_wm_set_size_hint (f
, (long) 0, 0);
11083 XSync (FRAME_X_DISPLAY (f
), False
);
11084 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11085 pixelwidth
, pixelheight
);
11087 /* Now, strictly speaking, we can't be sure that this is accurate,
11088 but the window manager will get around to dealing with the size
11089 change request eventually, and we'll hear how it went when the
11090 ConfigureNotify event gets here.
11092 We could just not bother storing any of this information here,
11093 and let the ConfigureNotify event set everything up, but that
11094 might be kind of confusing to the Lisp code, since size changes
11095 wouldn't be reported in the frame parameters until some random
11096 point in the future when the ConfigureNotify event arrives.
11098 We pass 1 for DELAY since we can't run Lisp code inside of
11100 change_frame_size (f
, rows
, cols
, 0, 1, 0);
11101 PIXEL_WIDTH (f
) = pixelwidth
;
11102 PIXEL_HEIGHT (f
) = pixelheight
;
11104 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11105 receive in the ConfigureNotify event; if we get what we asked
11106 for, then the event won't cause the screen to become garbaged, so
11107 we have to make sure to do it here. */
11108 SET_FRAME_GARBAGED (f
);
11110 XFlush (FRAME_X_DISPLAY (f
));
11112 #endif /* not USE_X_TOOLKIT */
11114 /* If cursor was outside the new size, mark it as off. */
11115 mark_window_cursors_off (XWINDOW (f
->root_window
));
11117 /* Clear out any recollection of where the mouse highlighting was,
11118 since it might be in a place that's outside the new frame size.
11119 Actually checking whether it is outside is a pain in the neck,
11120 so don't try--just let the highlighting be done afresh with new size. */
11121 cancel_mouse_face (f
);
11126 /* Mouse warping. */
11129 x_set_mouse_position (f
, x
, y
)
11135 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
11136 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
11138 if (pix_x
< 0) pix_x
= 0;
11139 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
11141 if (pix_y
< 0) pix_y
= 0;
11142 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
11146 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11147 0, 0, 0, 0, pix_x
, pix_y
);
11151 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11154 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
11160 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11161 0, 0, 0, 0, pix_x
, pix_y
);
11165 /* focus shifting, raising and lowering. */
11168 x_focus_on_frame (f
)
11171 #if 0 /* This proves to be unpleasant. */
11175 /* I don't think that the ICCCM allows programs to do things like this
11176 without the interaction of the window manager. Whatever you end up
11177 doing with this code, do it to x_unfocus_frame too. */
11178 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11179 RevertToPointerRoot
, CurrentTime
);
11184 x_unfocus_frame (f
)
11188 /* Look at the remarks in x_focus_on_frame. */
11189 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
11190 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
11191 RevertToPointerRoot
, CurrentTime
);
11195 /* Raise frame F. */
11201 if (f
->async_visible
)
11204 #ifdef USE_X_TOOLKIT
11205 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11206 #else /* not USE_X_TOOLKIT */
11207 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11208 #endif /* not USE_X_TOOLKIT */
11209 XFlush (FRAME_X_DISPLAY (f
));
11214 /* Lower frame F. */
11220 if (f
->async_visible
)
11223 #ifdef USE_X_TOOLKIT
11224 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11225 #else /* not USE_X_TOOLKIT */
11226 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11227 #endif /* not USE_X_TOOLKIT */
11228 XFlush (FRAME_X_DISPLAY (f
));
11234 XTframe_raise_lower (f
, raise_flag
)
11244 /* Change of visibility. */
11246 /* This tries to wait until the frame is really visible.
11247 However, if the window manager asks the user where to position
11248 the frame, this will return before the user finishes doing that.
11249 The frame will not actually be visible at that time,
11250 but it will become visible later when the window manager
11251 finishes with it. */
11254 x_make_frame_visible (f
)
11258 int original_top
, original_left
;
11262 type
= x_icon_type (f
);
11264 x_bitmap_icon (f
, type
);
11266 if (! FRAME_VISIBLE_P (f
))
11268 /* We test FRAME_GARBAGED_P here to make sure we don't
11269 call x_set_offset a second time
11270 if we get to x_make_frame_visible a second time
11271 before the window gets really visible. */
11272 if (! FRAME_ICONIFIED_P (f
)
11273 && ! f
->output_data
.x
->asked_for_visible
)
11274 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11276 f
->output_data
.x
->asked_for_visible
= 1;
11278 if (! EQ (Vx_no_window_manager
, Qt
))
11279 x_wm_set_window_state (f
, NormalState
);
11280 #ifdef USE_X_TOOLKIT
11281 /* This was XtPopup, but that did nothing for an iconified frame. */
11282 XtMapWidget (f
->output_data
.x
->widget
);
11283 #else /* not USE_X_TOOLKIT */
11284 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11285 #endif /* not USE_X_TOOLKIT */
11286 #if 0 /* This seems to bring back scroll bars in the wrong places
11287 if the window configuration has changed. They seem
11288 to come back ok without this. */
11289 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
11290 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11294 XFlush (FRAME_X_DISPLAY (f
));
11296 /* Synchronize to ensure Emacs knows the frame is visible
11297 before we do anything else. We do this loop with input not blocked
11298 so that incoming events are handled. */
11301 int count
= input_signal_count
;
11302 /* This must be before UNBLOCK_INPUT
11303 since events that arrive in response to the actions above
11304 will set it when they are handled. */
11305 int previously_visible
= f
->output_data
.x
->has_been_visible
;
11307 original_left
= f
->output_data
.x
->left_pos
;
11308 original_top
= f
->output_data
.x
->top_pos
;
11310 /* This must come after we set COUNT. */
11313 /* We unblock here so that arriving X events are processed. */
11315 /* Now move the window back to where it was "supposed to be".
11316 But don't do it if the gravity is negative.
11317 When the gravity is negative, this uses a position
11318 that is 3 pixels too low. Perhaps that's really the border width.
11320 Don't do this if the window has never been visible before,
11321 because the window manager may choose the position
11322 and we don't want to override it. */
11324 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
11325 && f
->output_data
.x
->win_gravity
== NorthWestGravity
11326 && previously_visible
)
11330 unsigned int width
, height
, border
, depth
;
11334 /* On some window managers (such as FVWM) moving an existing
11335 window, even to the same place, causes the window manager
11336 to introduce an offset. This can cause the window to move
11337 to an unexpected location. Check the geometry (a little
11338 slow here) and then verify that the window is in the right
11339 place. If the window is not in the right place, move it
11340 there, and take the potential window manager hit. */
11341 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11342 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
11344 if (original_left
!= x
|| original_top
!= y
)
11345 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11346 original_left
, original_top
);
11351 XSETFRAME (frame
, f
);
11356 /* Once we have handled input events,
11357 we should have received the MapNotify if one is coming.
11358 So if we have not got it yet, stop looping.
11359 Some window managers make their own decisions
11360 about visibility. */
11361 if (input_signal_count
!= count
)
11363 /* Machines that do polling rather than SIGIO have been observed
11364 to go into a busy-wait here. So we'll fake an alarm signal
11365 to let the handler know that there's something to be read.
11366 We used to raise a real alarm, but it seems that the handler
11367 isn't always enabled here. This is probably a bug. */
11368 if (input_polling_used ())
11370 /* It could be confusing if a real alarm arrives while processing
11371 the fake one. Turn it off and let the handler reset it. */
11373 input_poll_signal (0);
11375 /* Once we have handled input events,
11376 we should have received the MapNotify if one is coming.
11377 So if we have not got it yet, stop looping.
11378 Some window managers make their own decisions
11379 about visibility. */
11380 if (input_signal_count
!= count
)
11383 FRAME_SAMPLE_VISIBILITY (f
);
11387 /* Change from mapped state to withdrawn state. */
11389 /* Make the frame visible (mapped and not iconified). */
11392 x_make_frame_invisible (f
)
11397 #ifdef USE_X_TOOLKIT
11398 /* Use the frame's outermost window, not the one we normally draw on. */
11399 window
= XtWindow (f
->output_data
.x
->widget
);
11400 #else /* not USE_X_TOOLKIT */
11401 window
= FRAME_X_WINDOW (f
);
11402 #endif /* not USE_X_TOOLKIT */
11404 /* Don't keep the highlight on an invisible frame. */
11405 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11406 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11408 #if 0/* This might add unreliability; I don't trust it -- rms. */
11409 if (! f
->async_visible
&& ! f
->async_iconified
)
11415 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11416 that the current position of the window is user-specified, rather than
11417 program-specified, so that when the window is mapped again, it will be
11418 placed at the same location, without forcing the user to position it
11419 by hand again (they have already done that once for this window.) */
11420 x_wm_set_size_hint (f
, (long) 0, 1);
11424 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11425 DefaultScreen (FRAME_X_DISPLAY (f
))))
11427 UNBLOCK_INPUT_RESIGNAL
;
11428 error ("Can't notify window manager of window withdrawal");
11430 #else /* ! defined (HAVE_X11R4) */
11432 /* Tell the window manager what we're going to do. */
11433 if (! EQ (Vx_no_window_manager
, Qt
))
11437 unmap
.xunmap
.type
= UnmapNotify
;
11438 unmap
.xunmap
.window
= window
;
11439 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
11440 unmap
.xunmap
.from_configure
= False
;
11441 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11442 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11444 SubstructureRedirectMaskSubstructureNotifyMask
,
11447 UNBLOCK_INPUT_RESIGNAL
;
11448 error ("Can't notify window manager of withdrawal");
11452 /* Unmap the window ourselves. Cheeky! */
11453 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
11454 #endif /* ! defined (HAVE_X11R4) */
11456 /* We can't distinguish this from iconification
11457 just by the event that we get from the server.
11458 So we can't win using the usual strategy of letting
11459 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11460 and synchronize with the server to make sure we agree. */
11462 FRAME_ICONIFIED_P (f
) = 0;
11463 f
->async_visible
= 0;
11464 f
->async_iconified
= 0;
11471 /* Change window state from mapped to iconified. */
11474 x_iconify_frame (f
)
11480 /* Don't keep the highlight on an invisible frame. */
11481 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11482 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11484 if (f
->async_iconified
)
11489 FRAME_SAMPLE_VISIBILITY (f
);
11491 type
= x_icon_type (f
);
11493 x_bitmap_icon (f
, type
);
11495 #ifdef USE_X_TOOLKIT
11497 if (! FRAME_VISIBLE_P (f
))
11499 if (! EQ (Vx_no_window_manager
, Qt
))
11500 x_wm_set_window_state (f
, IconicState
);
11501 /* This was XtPopup, but that did nothing for an iconified frame. */
11502 XtMapWidget (f
->output_data
.x
->widget
);
11503 /* The server won't give us any event to indicate
11504 that an invisible frame was changed to an icon,
11505 so we have to record it here. */
11508 f
->async_iconified
= 1;
11509 f
->async_visible
= 0;
11514 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11515 XtWindow (f
->output_data
.x
->widget
),
11516 DefaultScreen (FRAME_X_DISPLAY (f
)));
11520 error ("Can't notify window manager of iconification");
11522 f
->async_iconified
= 1;
11523 f
->async_visible
= 0;
11527 XFlush (FRAME_X_DISPLAY (f
));
11529 #else /* not USE_X_TOOLKIT */
11531 /* Make sure the X server knows where the window should be positioned,
11532 in case the user deiconifies with the window manager. */
11533 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
11534 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11536 /* Since we don't know which revision of X we're running, we'll use both
11537 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11539 /* X11R4: send a ClientMessage to the window manager using the
11540 WM_CHANGE_STATE type. */
11544 message
.xclient
.window
= FRAME_X_WINDOW (f
);
11545 message
.xclient
.type
= ClientMessage
;
11546 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
11547 message
.xclient
.format
= 32;
11548 message
.xclient
.data
.l
[0] = IconicState
;
11550 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11551 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11553 SubstructureRedirectMask
| SubstructureNotifyMask
,
11556 UNBLOCK_INPUT_RESIGNAL
;
11557 error ("Can't notify window manager of iconification");
11561 /* X11R3: set the initial_state field of the window manager hints to
11563 x_wm_set_window_state (f
, IconicState
);
11565 if (!FRAME_VISIBLE_P (f
))
11567 /* If the frame was withdrawn, before, we must map it. */
11568 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11571 f
->async_iconified
= 1;
11572 f
->async_visible
= 0;
11574 XFlush (FRAME_X_DISPLAY (f
));
11576 #endif /* not USE_X_TOOLKIT */
11579 /* Destroy the X window of frame F. */
11582 x_destroy_window (f
)
11585 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11589 /* If a display connection is dead, don't try sending more
11590 commands to the X server. */
11591 if (dpyinfo
->display
!= 0)
11593 if (f
->output_data
.x
->icon_desc
!= 0)
11594 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
11598 XDestroyIC (FRAME_XIC (f
));
11599 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11600 /* This line causes crashes on Solaris with Openwin,
11601 due to an apparent bug in XCloseIM.
11602 X11R6 seems not to have the bug. */
11603 XCloseIM (FRAME_XIM (f
));
11607 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
11608 #ifdef USE_X_TOOLKIT
11609 if (f
->output_data
.x
->widget
)
11610 XtDestroyWidget (f
->output_data
.x
->widget
);
11611 free_frame_menubar (f
);
11612 #endif /* USE_X_TOOLKIT */
11614 free_frame_faces (f
);
11615 XFlush (FRAME_X_DISPLAY (f
));
11618 if (f
->output_data
.x
->saved_menu_event
)
11619 xfree (f
->output_data
.x
->saved_menu_event
);
11621 xfree (f
->output_data
.x
);
11622 f
->output_data
.x
= 0;
11623 if (f
== dpyinfo
->x_focus_frame
)
11624 dpyinfo
->x_focus_frame
= 0;
11625 if (f
== dpyinfo
->x_focus_event_frame
)
11626 dpyinfo
->x_focus_event_frame
= 0;
11627 if (f
== dpyinfo
->x_highlight_frame
)
11628 dpyinfo
->x_highlight_frame
= 0;
11630 dpyinfo
->reference_count
--;
11632 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11634 dpyinfo
->mouse_face_beg_row
11635 = dpyinfo
->mouse_face_beg_col
= -1;
11636 dpyinfo
->mouse_face_end_row
11637 = dpyinfo
->mouse_face_end_col
= -1;
11638 dpyinfo
->mouse_face_window
= Qnil
;
11639 dpyinfo
->mouse_face_deferred_gc
= 0;
11640 dpyinfo
->mouse_face_mouse_frame
= 0;
11646 /* Setting window manager hints. */
11648 /* Set the normal size hints for the window manager, for frame F.
11649 FLAGS is the flags word to use--or 0 meaning preserve the flags
11650 that the window now has.
11651 If USER_POSITION is nonzero, we set the USPosition
11652 flag (this is useful when FLAGS is 0). */
11655 x_wm_set_size_hint (f
, flags
, user_position
)
11660 XSizeHints size_hints
;
11662 #ifdef USE_X_TOOLKIT
11665 Dimension widget_width
, widget_height
;
11666 Window window
= XtWindow (f
->output_data
.x
->widget
);
11667 #else /* not USE_X_TOOLKIT */
11668 Window window
= FRAME_X_WINDOW (f
);
11669 #endif /* not USE_X_TOOLKIT */
11671 /* Setting PMaxSize caused various problems. */
11672 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
11674 size_hints
.x
= f
->output_data
.x
->left_pos
;
11675 size_hints
.y
= f
->output_data
.x
->top_pos
;
11677 #ifdef USE_X_TOOLKIT
11678 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
11679 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
11680 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
11681 size_hints
.height
= widget_height
;
11682 size_hints
.width
= widget_width
;
11683 #else /* not USE_X_TOOLKIT */
11684 size_hints
.height
= PIXEL_HEIGHT (f
);
11685 size_hints
.width
= PIXEL_WIDTH (f
);
11686 #endif /* not USE_X_TOOLKIT */
11688 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
11689 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
11690 size_hints
.max_width
11691 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
11692 size_hints
.max_height
11693 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
11695 /* Calculate the base and minimum sizes.
11697 (When we use the X toolkit, we don't do it here.
11698 Instead we copy the values that the widgets are using, below.) */
11699 #ifndef USE_X_TOOLKIT
11701 int base_width
, base_height
;
11702 int min_rows
= 0, min_cols
= 0;
11704 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
11705 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
11707 check_frame_size (f
, &min_rows
, &min_cols
);
11709 /* The window manager uses the base width hints to calculate the
11710 current number of rows and columns in the frame while
11711 resizing; min_width and min_height aren't useful for this
11712 purpose, since they might not give the dimensions for a
11713 zero-row, zero-column frame.
11715 We use the base_width and base_height members if we have
11716 them; otherwise, we set the min_width and min_height members
11717 to the size for a zero x zero frame. */
11720 size_hints
.flags
|= PBaseSize
;
11721 size_hints
.base_width
= base_width
;
11722 size_hints
.base_height
= base_height
;
11723 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
11724 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
11726 size_hints
.min_width
= base_width
;
11727 size_hints
.min_height
= base_height
;
11731 /* If we don't need the old flags, we don't need the old hint at all. */
11734 size_hints
.flags
|= flags
;
11737 #endif /* not USE_X_TOOLKIT */
11740 XSizeHints hints
; /* Sometimes I hate X Windows... */
11741 long supplied_return
;
11745 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
11748 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
11751 #ifdef USE_X_TOOLKIT
11752 size_hints
.base_height
= hints
.base_height
;
11753 size_hints
.base_width
= hints
.base_width
;
11754 size_hints
.min_height
= hints
.min_height
;
11755 size_hints
.min_width
= hints
.min_width
;
11759 size_hints
.flags
|= flags
;
11764 if (hints
.flags
& PSize
)
11765 size_hints
.flags
|= PSize
;
11766 if (hints
.flags
& PPosition
)
11767 size_hints
.flags
|= PPosition
;
11768 if (hints
.flags
& USPosition
)
11769 size_hints
.flags
|= USPosition
;
11770 if (hints
.flags
& USSize
)
11771 size_hints
.flags
|= USSize
;
11775 #ifndef USE_X_TOOLKIT
11780 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
11781 size_hints
.flags
|= PWinGravity
;
11785 size_hints
.flags
&= ~ PPosition
;
11786 size_hints
.flags
|= USPosition
;
11788 #endif /* PWinGravity */
11791 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11793 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11797 /* Used for IconicState or NormalState */
11800 x_wm_set_window_state (f
, state
)
11804 #ifdef USE_X_TOOLKIT
11807 XtSetArg (al
[0], XtNinitialState
, state
);
11808 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11809 #else /* not USE_X_TOOLKIT */
11810 Window window
= FRAME_X_WINDOW (f
);
11812 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
11813 f
->output_data
.x
->wm_hints
.initial_state
= state
;
11815 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11816 #endif /* not USE_X_TOOLKIT */
11820 x_wm_set_icon_pixmap (f
, pixmap_id
)
11824 Pixmap icon_pixmap
;
11826 #ifndef USE_X_TOOLKIT
11827 Window window
= FRAME_X_WINDOW (f
);
11832 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
11833 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
11837 /* It seems there is no way to turn off use of an icon pixmap.
11838 The following line does it, only if no icon has yet been created,
11839 for some window managers. But with mwm it crashes.
11840 Some people say it should clear the IconPixmapHint bit in this case,
11841 but that doesn't work, and the X consortium said it isn't the
11842 right thing at all. Since there is no way to win,
11843 best to explicitly give up. */
11845 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
11851 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11855 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
11856 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11859 #else /* not USE_X_TOOLKIT */
11861 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
11862 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11864 #endif /* not USE_X_TOOLKIT */
11868 x_wm_set_icon_position (f
, icon_x
, icon_y
)
11870 int icon_x
, icon_y
;
11872 #ifdef USE_X_TOOLKIT
11873 Window window
= XtWindow (f
->output_data
.x
->widget
);
11875 Window window
= FRAME_X_WINDOW (f
);
11878 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
11879 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
11880 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
11882 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11886 /***********************************************************************
11888 ***********************************************************************/
11890 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
11893 x_get_font_info (f
, font_idx
)
11897 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
11901 /* Return a list of names of available fonts matching PATTERN on frame
11902 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11903 to be listed. Frame F NULL means we have not yet created any
11904 frame on X, and consult the first display in x_display_list.
11905 MAXNAMES sets a limit on how many fonts to match. */
11908 x_list_fonts (f
, pattern
, size
, maxnames
)
11910 Lisp_Object pattern
;
11914 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
11915 Lisp_Object tem
, second_best
;
11916 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
11917 int try_XLoadQueryFont
= 0;
11920 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
11921 if (NILP (patterns
))
11922 patterns
= Fcons (pattern
, Qnil
);
11924 if (maxnames
== 1 && !size
)
11925 /* We can return any single font matching PATTERN. */
11926 try_XLoadQueryFont
= 1;
11928 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
11933 pattern
= XCAR (patterns
);
11934 /* See if we cached the result for this particular query.
11935 The cache is an alist of the form:
11936 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11938 if (f
&& (tem
= XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
),
11939 key
= Fcons (pattern
, make_number (maxnames
)),
11940 !NILP (list
= Fassoc (key
, tem
))))
11942 list
= Fcdr_safe (list
);
11943 /* We have a cashed list. Don't have to get the list again. */
11947 /* At first, put PATTERN in the cache. */
11950 count
= x_catch_errors (dpy
);
11952 if (try_XLoadQueryFont
)
11955 unsigned long value
;
11957 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
11958 if (x_had_errors_p (dpy
))
11960 /* This error is perhaps due to insufficient memory on X
11961 server. Let's just ignore it. */
11963 x_clear_errors (dpy
);
11967 && XGetFontProperty (font
, XA_FONT
, &value
))
11969 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
11970 int len
= strlen (name
);
11973 /* If DXPC (a Differential X Protocol Compressor)
11974 Ver.3.7 is running, XGetAtomName will return null
11975 string. We must avoid such a name. */
11977 try_XLoadQueryFont
= 0;
11981 names
= (char **) alloca (sizeof (char *));
11982 /* Some systems only allow alloca assigned to a
11984 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
11985 bcopy (name
, names
[0], len
+ 1);
11990 try_XLoadQueryFont
= 0;
11993 XFreeFont (dpy
, font
);
11996 if (!try_XLoadQueryFont
)
11998 /* We try at least 10 fonts because XListFonts will return
11999 auto-scaled fonts at the head. */
12000 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
12002 if (x_had_errors_p (dpy
))
12004 /* This error is perhaps due to insufficient memory on X
12005 server. Let's just ignore it. */
12007 x_clear_errors (dpy
);
12011 x_uncatch_errors (dpy
, count
);
12018 /* Make a list of all the fonts we got back.
12019 Store that in the font cache for the display. */
12020 for (i
= 0; i
< num_fonts
; i
++)
12023 char *p
= names
[i
];
12024 int average_width
= -1, dashes
= 0;
12026 /* Count the number of dashes in NAMES[I]. If there are
12027 14 dashes, and the field value following 12th dash
12028 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12029 is usually too ugly to be used for editing. Let's
12035 if (dashes
== 7) /* PIXEL_SIZE field */
12037 else if (dashes
== 12) /* AVERAGE_WIDTH field */
12038 average_width
= atoi (p
);
12040 if (dashes
< 14 || average_width
!= 0)
12042 tem
= build_string (names
[i
]);
12043 if (NILP (Fassoc (tem
, list
)))
12045 if (STRINGP (Vx_pixel_size_width_font_regexp
)
12046 && ((fast_c_string_match_ignore_case
12047 (Vx_pixel_size_width_font_regexp
, names
[i
]))
12049 /* We can set the value of PIXEL_SIZE to the
12050 width of this font. */
12051 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
12053 /* For the moment, width is not known. */
12054 list
= Fcons (Fcons (tem
, Qnil
), list
);
12058 if (!try_XLoadQueryFont
)
12059 XFreeFontNames (names
);
12062 /* Now store the result in the cache. */
12064 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)
12065 = Fcons (Fcons (key
, list
),
12066 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
12069 if (NILP (list
)) continue; /* Try the remaining alternatives. */
12071 newlist
= second_best
= Qnil
;
12072 /* Make a list of the fonts that have the right width. */
12073 for (; CONSP (list
); list
= XCDR (list
))
12079 if (!CONSP (tem
) || NILP (XCAR (tem
)))
12083 newlist
= Fcons (XCAR (tem
), newlist
);
12087 if (!INTEGERP (XCDR (tem
)))
12089 /* Since we have not yet known the size of this font, we
12090 must try slow function call XLoadQueryFont. */
12091 XFontStruct
*thisinfo
;
12094 count
= x_catch_errors (dpy
);
12095 thisinfo
= XLoadQueryFont (dpy
,
12096 XSTRING (XCAR (tem
))->data
);
12097 if (x_had_errors_p (dpy
))
12099 /* This error is perhaps due to insufficient memory on X
12100 server. Let's just ignore it. */
12102 x_clear_errors (dpy
);
12104 x_uncatch_errors (dpy
, count
);
12110 = (thisinfo
->min_bounds
.width
== 0
12112 : make_number (thisinfo
->max_bounds
.width
));
12113 XFreeFont (dpy
, thisinfo
);
12116 /* For unknown reason, the previous call of XListFont had
12117 returned a font which can't be opened. Record the size
12118 as 0 not to try to open it again. */
12119 XCDR (tem
) = make_number (0);
12122 found_size
= XINT (XCDR (tem
));
12123 if (found_size
== size
)
12124 newlist
= Fcons (XCAR (tem
), newlist
);
12125 else if (found_size
> 0)
12127 if (NILP (second_best
))
12129 else if (found_size
< size
)
12131 if (XINT (XCDR (second_best
)) > size
12132 || XINT (XCDR (second_best
)) < found_size
)
12137 if (XINT (XCDR (second_best
)) > size
12138 && XINT (XCDR (second_best
)) > found_size
)
12143 if (!NILP (newlist
))
12145 else if (!NILP (second_best
))
12147 newlist
= Fcons (XCAR (second_best
), Qnil
);
12158 /* Check that FONT is valid on frame F. It is if it can be found in F's
12162 x_check_font (f
, font
)
12167 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12169 xassert (font
!= NULL
);
12171 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12172 if (dpyinfo
->font_table
[i
].name
12173 && font
== dpyinfo
->font_table
[i
].font
)
12176 xassert (i
< dpyinfo
->n_fonts
);
12179 #endif /* GLYPH_DEBUG != 0 */
12181 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12182 Note: There are (broken) X fonts out there with invalid XFontStruct
12183 min_bounds contents. For example, handa@etl.go.jp reports that
12184 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12185 have font->min_bounds.width == 0. */
12188 x_font_min_bounds (font
, w
, h
)
12192 *h
= FONT_HEIGHT (font
);
12193 *w
= font
->min_bounds
.width
;
12195 /* Try to handle the case where FONT->min_bounds has invalid
12196 contents. Since the only font known to have invalid min_bounds
12197 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12199 *w
= font
->max_bounds
.width
;
12203 /* Compute the smallest character width and smallest font height over
12204 all fonts available on frame F. Set the members smallest_char_width
12205 and smallest_font_height in F's x_display_info structure to
12206 the values computed. Value is non-zero if smallest_font_height or
12207 smallest_char_width become smaller than they were before. */
12210 x_compute_min_glyph_bounds (f
)
12214 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12216 int old_width
= dpyinfo
->smallest_char_width
;
12217 int old_height
= dpyinfo
->smallest_font_height
;
12219 dpyinfo
->smallest_font_height
= 100000;
12220 dpyinfo
->smallest_char_width
= 100000;
12222 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12223 if (dpyinfo
->font_table
[i
].name
)
12225 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
12228 font
= (XFontStruct
*) fontp
->font
;
12229 xassert (font
!= (XFontStruct
*) ~0);
12230 x_font_min_bounds (font
, &w
, &h
);
12232 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
12233 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
12236 xassert (dpyinfo
->smallest_char_width
> 0
12237 && dpyinfo
->smallest_font_height
> 0);
12239 return (dpyinfo
->n_fonts
== 1
12240 || dpyinfo
->smallest_char_width
< old_width
12241 || dpyinfo
->smallest_font_height
< old_height
);
12245 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12246 pointer to the structure font_info while allocating it dynamically.
12247 If SIZE is 0, load any size of font.
12248 If loading is failed, return NULL. */
12251 x_load_font (f
, fontname
, size
)
12253 register char *fontname
;
12256 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12257 Lisp_Object font_names
;
12260 /* Get a list of all the fonts that match this name. Once we
12261 have a list of matching fonts, we compare them against the fonts
12262 we already have by comparing names. */
12263 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
12265 if (!NILP (font_names
))
12270 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12271 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
12272 if (dpyinfo
->font_table
[i
].name
12273 && (!strcmp (dpyinfo
->font_table
[i
].name
,
12274 XSTRING (XCAR (tail
))->data
)
12275 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
12276 XSTRING (XCAR (tail
))->data
)))
12277 return (dpyinfo
->font_table
+ i
);
12280 /* Load the font and add it to the table. */
12284 struct font_info
*fontp
;
12285 unsigned long value
;
12288 /* If we have found fonts by x_list_font, load one of them. If
12289 not, we still try to load a font by the name given as FONTNAME
12290 because XListFonts (called in x_list_font) of some X server has
12291 a bug of not finding a font even if the font surely exists and
12292 is loadable by XLoadQueryFont. */
12293 if (size
> 0 && !NILP (font_names
))
12294 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
12297 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
12298 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
12299 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
12301 /* This error is perhaps due to insufficient memory on X
12302 server. Let's just ignore it. */
12304 x_clear_errors (FRAME_X_DISPLAY (f
));
12306 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
12311 /* Find a free slot in the font table. */
12312 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12313 if (dpyinfo
->font_table
[i
].name
== NULL
)
12316 /* If no free slot found, maybe enlarge the font table. */
12317 if (i
== dpyinfo
->n_fonts
12318 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
12321 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
12322 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
12323 dpyinfo
->font_table
12324 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
12327 fontp
= dpyinfo
->font_table
+ i
;
12328 if (i
== dpyinfo
->n_fonts
)
12329 ++dpyinfo
->n_fonts
;
12331 /* Now fill in the slots of *FONTP. */
12333 fontp
->font
= font
;
12334 fontp
->font_idx
= i
;
12335 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
12336 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
12338 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12340 if (XGetFontProperty (font
, XA_FONT
, &value
))
12342 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
12346 /* Count the number of dashes in the "full name".
12347 If it is too few, this isn't really the font's full name,
12349 In X11R4, the fonts did not come with their canonical names
12360 full_name
= (char *) xmalloc (p
- name
+ 1);
12361 bcopy (name
, full_name
, p
- name
+ 1);
12367 if (full_name
!= 0)
12368 fontp
->full_name
= full_name
;
12370 fontp
->full_name
= fontp
->name
;
12372 fontp
->size
= font
->max_bounds
.width
;
12373 fontp
->height
= FONT_HEIGHT (font
);
12375 /* For some font, ascent and descent in max_bounds field is
12376 larger than the above value. */
12377 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
12378 if (max_height
> fontp
->height
)
12379 fontp
->height
= max_height
;
12382 if (NILP (font_names
))
12384 /* We come here because of a bug of XListFonts mentioned at
12385 the head of this block. Let's store this information in
12386 the cache for x_list_fonts. */
12387 Lisp_Object lispy_name
= build_string (fontname
);
12388 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
12390 XCDR (dpyinfo
->name_list_element
)
12391 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
12392 Fcons (Fcons (lispy_full_name
,
12393 make_number (fontp
->size
)),
12395 XCDR (dpyinfo
->name_list_element
));
12397 XCDR (dpyinfo
->name_list_element
)
12398 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
12399 Fcons (Fcons (lispy_full_name
,
12400 make_number (fontp
->size
)),
12402 XCDR (dpyinfo
->name_list_element
));
12405 /* The slot `encoding' specifies how to map a character
12406 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12407 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12408 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12409 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12410 2:0xA020..0xFF7F). For the moment, we don't know which charset
12411 uses this font. So, we set information in fontp->encoding[1]
12412 which is never used by any charset. If mapping can't be
12413 decided, set FONT_ENCODING_NOT_DECIDED. */
12415 = (font
->max_byte1
== 0
12417 ? (font
->min_char_or_byte2
< 0x80
12418 ? (font
->max_char_or_byte2
< 0x80
12419 ? 0 /* 0x20..0x7F */
12420 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
12421 : 1) /* 0xA0..0xFF */
12423 : (font
->min_byte1
< 0x80
12424 ? (font
->max_byte1
< 0x80
12425 ? (font
->min_char_or_byte2
< 0x80
12426 ? (font
->max_char_or_byte2
< 0x80
12427 ? 0 /* 0x2020..0x7F7F */
12428 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
12429 : 3) /* 0x20A0..0x7FFF */
12430 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
12431 : (font
->min_char_or_byte2
< 0x80
12432 ? (font
->max_char_or_byte2
< 0x80
12433 ? 2 /* 0xA020..0xFF7F */
12434 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
12435 : 1))); /* 0xA0A0..0xFFFF */
12437 fontp
->baseline_offset
12438 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
12439 ? (long) value
: 0);
12440 fontp
->relative_compose
12441 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
12442 ? (long) value
: 0);
12443 fontp
->default_ascent
12444 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
12445 ? (long) value
: 0);
12447 /* Set global flag fonts_changed_p to non-zero if the font loaded
12448 has a character with a smaller width than any other character
12449 before, or if the font loaded has a smalle>r height than any
12450 other font loaded before. If this happens, it will make a
12451 glyph matrix reallocation necessary. */
12452 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
12459 /* Return a pointer to struct font_info of a font named FONTNAME for
12460 frame F. If no such font is loaded, return NULL. */
12463 x_query_font (f
, fontname
)
12465 register char *fontname
;
12467 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12470 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12471 if (dpyinfo
->font_table
[i
].name
12472 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
12473 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
12474 return (dpyinfo
->font_table
+ i
);
12479 /* Find a CCL program for a font specified by FONTP, and set the member
12480 `encoder' of the structure. */
12483 x_find_ccl_program (fontp
)
12484 struct font_info
*fontp
;
12486 Lisp_Object list
, elt
;
12488 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
12492 && STRINGP (XCAR (elt
))
12493 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
12499 struct ccl_program
*ccl
12500 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
12502 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
12505 fontp
->font_encoder
= ccl
;
12511 /***********************************************************************
12513 ***********************************************************************/
12515 #ifdef USE_X_TOOLKIT
12516 static XrmOptionDescRec emacs_options
[] = {
12517 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
12518 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
12520 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12521 XrmoptionSepArg
, NULL
},
12522 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
12524 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12525 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12526 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12527 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12528 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12529 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
12530 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
12532 #endif /* USE_X_TOOLKIT */
12534 static int x_initialized
;
12536 #ifdef MULTI_KBOARD
12537 /* Test whether two display-name strings agree up to the dot that separates
12538 the screen number from the server number. */
12540 same_x_server (name1
, name2
)
12541 char *name1
, *name2
;
12543 int seen_colon
= 0;
12544 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
12545 int system_name_length
= strlen (system_name
);
12546 int length_until_period
= 0;
12548 while (system_name
[length_until_period
] != 0
12549 && system_name
[length_until_period
] != '.')
12550 length_until_period
++;
12552 /* Treat `unix' like an empty host name. */
12553 if (! strncmp (name1
, "unix:", 5))
12555 if (! strncmp (name2
, "unix:", 5))
12557 /* Treat this host's name like an empty host name. */
12558 if (! strncmp (name1
, system_name
, system_name_length
)
12559 && name1
[system_name_length
] == ':')
12560 name1
+= system_name_length
;
12561 if (! strncmp (name2
, system_name
, system_name_length
)
12562 && name2
[system_name_length
] == ':')
12563 name2
+= system_name_length
;
12564 /* Treat this host's domainless name like an empty host name. */
12565 if (! strncmp (name1
, system_name
, length_until_period
)
12566 && name1
[length_until_period
] == ':')
12567 name1
+= length_until_period
;
12568 if (! strncmp (name2
, system_name
, length_until_period
)
12569 && name2
[length_until_period
] == ':')
12570 name2
+= length_until_period
;
12572 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
12576 if (seen_colon
&& *name1
== '.')
12580 && (*name1
== '.' || *name1
== '\0')
12581 && (*name2
== '.' || *name2
== '\0'));
12585 struct x_display_info
*
12586 x_term_init (display_name
, xrm_option
, resource_name
)
12587 Lisp_Object display_name
;
12589 char *resource_name
;
12593 struct x_display_info
*dpyinfo
;
12598 if (!x_initialized
)
12604 #ifdef USE_X_TOOLKIT
12605 /* weiner@footloose.sps.mot.com reports that this causes
12607 X protocol error: BadAtom (invalid Atom parameter)
12608 on protocol request 18skiloaf.
12609 So let's not use it until R6. */
12610 #ifdef HAVE_X11XTR6
12611 XtSetLanguageProc (NULL
, NULL
, NULL
);
12622 argv
[argc
++] = "-xrm";
12623 argv
[argc
++] = xrm_option
;
12625 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
12626 resource_name
, EMACS_CLASS
,
12627 emacs_options
, XtNumber (emacs_options
),
12630 #ifdef HAVE_X11XTR6
12631 /* I think this is to compensate for XtSetLanguageProc. */
12636 #else /* not USE_X_TOOLKIT */
12638 XSetLocaleModifiers ("");
12640 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
12641 #endif /* not USE_X_TOOLKIT */
12643 /* Detect failure. */
12650 /* We have definitely succeeded. Record the new connection. */
12652 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
12654 #ifdef MULTI_KBOARD
12656 struct x_display_info
*share
;
12659 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
12660 share
= share
->next
, tail
= XCDR (tail
))
12661 if (same_x_server (XSTRING (XCAR (XCAR (tail
)))->data
,
12662 XSTRING (display_name
)->data
))
12665 dpyinfo
->kboard
= share
->kboard
;
12668 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
12669 init_kboard (dpyinfo
->kboard
);
12670 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
12672 char *vendor
= ServerVendor (dpy
);
12673 dpyinfo
->kboard
->Vsystem_key_alist
12674 = call1 (Qvendor_specific_keysyms
,
12675 build_string (vendor
? vendor
: ""));
12678 dpyinfo
->kboard
->next_kboard
= all_kboards
;
12679 all_kboards
= dpyinfo
->kboard
;
12680 /* Don't let the initial kboard remain current longer than necessary.
12681 That would cause problems if a file loaded on startup tries to
12682 prompt in the mini-buffer. */
12683 if (current_kboard
== initial_kboard
)
12684 current_kboard
= dpyinfo
->kboard
;
12686 dpyinfo
->kboard
->reference_count
++;
12690 /* Put this display on the chain. */
12691 dpyinfo
->next
= x_display_list
;
12692 x_display_list
= dpyinfo
;
12694 /* Put it on x_display_name_list as well, to keep them parallel. */
12695 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
12696 x_display_name_list
);
12697 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12699 dpyinfo
->display
= dpy
;
12702 XSetAfterFunction (x_current_display
, x_trace_wire
);
12706 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
12707 + STRING_BYTES (XSTRING (Vsystem_name
))
12709 sprintf (dpyinfo
->x_id_name
, "%s@%s",
12710 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
12712 /* Figure out which modifier bits mean what. */
12713 x_find_modifier_meanings (dpyinfo
);
12715 /* Get the scroll bar cursor. */
12716 dpyinfo
->vertical_scroll_bar_cursor
12717 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
12719 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
12720 resource_name
, EMACS_CLASS
);
12721 #ifdef HAVE_XRMSETDATABASE
12722 XrmSetDatabase (dpyinfo
->display
, xrdb
);
12724 dpyinfo
->display
->db
= xrdb
;
12726 /* Put the rdb where we can find it in a way that works on
12728 dpyinfo
->xrdb
= xrdb
;
12730 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
12731 DefaultScreen (dpyinfo
->display
));
12732 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
12733 &dpyinfo
->n_planes
);
12734 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
12735 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
12736 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
12737 dpyinfo
->grabbed
= 0;
12738 dpyinfo
->reference_count
= 0;
12739 dpyinfo
->icon_bitmap_id
= -1;
12740 dpyinfo
->font_table
= NULL
;
12741 dpyinfo
->n_fonts
= 0;
12742 dpyinfo
->font_table_size
= 0;
12743 dpyinfo
->bitmaps
= 0;
12744 dpyinfo
->bitmaps_size
= 0;
12745 dpyinfo
->bitmaps_last
= 0;
12746 dpyinfo
->scratch_cursor_gc
= 0;
12747 dpyinfo
->mouse_face_mouse_frame
= 0;
12748 dpyinfo
->mouse_face_deferred_gc
= 0;
12749 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12750 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12751 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12752 dpyinfo
->mouse_face_window
= Qnil
;
12753 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
12754 dpyinfo
->mouse_face_defer
= 0;
12755 dpyinfo
->x_focus_frame
= 0;
12756 dpyinfo
->x_focus_event_frame
= 0;
12757 dpyinfo
->x_highlight_frame
= 0;
12758 dpyinfo
->image_cache
= make_image_cache ();
12761 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
12762 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
12763 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
12764 dpyinfo
->resy
= pixels
* 25.4 / mm
;
12765 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
12766 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
12767 dpyinfo
->resx
= pixels
* 25.4 / mm
;
12770 dpyinfo
->Xatom_wm_protocols
12771 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
12772 dpyinfo
->Xatom_wm_take_focus
12773 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
12774 dpyinfo
->Xatom_wm_save_yourself
12775 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
12776 dpyinfo
->Xatom_wm_delete_window
12777 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
12778 dpyinfo
->Xatom_wm_change_state
12779 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
12780 dpyinfo
->Xatom_wm_configure_denied
12781 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
12782 dpyinfo
->Xatom_wm_window_moved
12783 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
12784 dpyinfo
->Xatom_editres
12785 = XInternAtom (dpyinfo
->display
, "Editres", False
);
12786 dpyinfo
->Xatom_CLIPBOARD
12787 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
12788 dpyinfo
->Xatom_TIMESTAMP
12789 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
12790 dpyinfo
->Xatom_TEXT
12791 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
12792 dpyinfo
->Xatom_COMPOUND_TEXT
12793 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
12794 dpyinfo
->Xatom_DELETE
12795 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
12796 dpyinfo
->Xatom_MULTIPLE
12797 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
12798 dpyinfo
->Xatom_INCR
12799 = XInternAtom (dpyinfo
->display
, "INCR", False
);
12800 dpyinfo
->Xatom_EMACS_TMP
12801 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
12802 dpyinfo
->Xatom_TARGETS
12803 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
12804 dpyinfo
->Xatom_NULL
12805 = XInternAtom (dpyinfo
->display
, "NULL", False
);
12806 dpyinfo
->Xatom_ATOM_PAIR
12807 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
12808 /* For properties of font. */
12809 dpyinfo
->Xatom_PIXEL_SIZE
12810 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
12811 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
12812 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
12813 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
12814 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
12815 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
12816 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
12818 /* Ghostscript support. */
12819 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
12820 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
12822 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
12825 dpyinfo
->cut_buffers_initialized
= 0;
12827 connection
= ConnectionNumber (dpyinfo
->display
);
12828 dpyinfo
->connection
= connection
;
12833 null_bits
[0] = 0x00;
12835 dpyinfo
->null_pixel
12836 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12837 null_bits
, 1, 1, (long) 0, (long) 0,
12842 extern int gray_bitmap_width
, gray_bitmap_height
;
12843 extern unsigned char *gray_bitmap_bits
;
12845 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12847 gray_bitmap_width
, gray_bitmap_height
,
12848 (unsigned long) 1, (unsigned long) 0, 1);
12851 #ifdef subprocesses
12852 /* This is only needed for distinguishing keyboard and process input. */
12853 if (connection
!= 0)
12854 add_keyboard_wait_descriptor (connection
);
12857 #ifndef F_SETOWN_BUG
12859 #ifdef F_SETOWN_SOCK_NEG
12860 /* stdin is a socket here */
12861 fcntl (connection
, F_SETOWN
, -getpid ());
12862 #else /* ! defined (F_SETOWN_SOCK_NEG) */
12863 fcntl (connection
, F_SETOWN
, getpid ());
12864 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
12865 #endif /* ! defined (F_SETOWN) */
12866 #endif /* F_SETOWN_BUG */
12869 if (interrupt_input
)
12870 init_sigio (connection
);
12871 #endif /* ! defined (SIGIO) */
12874 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
12875 /* Make sure that we have a valid font for dialog boxes
12876 so that Xt does not crash. */
12878 Display
*dpy
= dpyinfo
->display
;
12879 XrmValue d
, fr
, to
;
12883 d
.addr
= (XPointer
)&dpy
;
12884 d
.size
= sizeof (Display
*);
12885 fr
.addr
= XtDefaultFont
;
12886 fr
.size
= sizeof (XtDefaultFont
);
12887 to
.size
= sizeof (Font
*);
12888 to
.addr
= (XPointer
)&font
;
12889 count
= x_catch_errors (dpy
);
12890 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
12892 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
12893 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
12894 x_uncatch_errors (dpy
, count
);
12904 /* Get rid of display DPYINFO, assuming all frames are already gone,
12905 and without sending any more commands to the X server. */
12908 x_delete_display (dpyinfo
)
12909 struct x_display_info
*dpyinfo
;
12911 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
12913 /* Discard this display from x_display_name_list and x_display_list.
12914 We can't use Fdelq because that can quit. */
12915 if (! NILP (x_display_name_list
)
12916 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12917 x_display_name_list
= XCDR (x_display_name_list
);
12922 tail
= x_display_name_list
;
12923 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12925 if (EQ (XCAR (XCDR (tail
)),
12926 dpyinfo
->name_list_element
))
12928 XCDR (tail
) = XCDR (XCDR (tail
));
12931 tail
= XCDR (tail
);
12935 if (x_display_list
== dpyinfo
)
12936 x_display_list
= dpyinfo
->next
;
12939 struct x_display_info
*tail
;
12941 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12942 if (tail
->next
== dpyinfo
)
12943 tail
->next
= tail
->next
->next
;
12946 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12947 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
12948 XrmDestroyDatabase (dpyinfo
->xrdb
);
12951 #ifdef MULTI_KBOARD
12952 if (--dpyinfo
->kboard
->reference_count
== 0)
12953 delete_kboard (dpyinfo
->kboard
);
12955 xfree (dpyinfo
->font_table
);
12956 xfree (dpyinfo
->x_id_name
);
12960 /* Set up use of X before we make the first connection. */
12962 static struct redisplay_interface x_redisplay_interface
=
12967 x_clear_end_of_line
,
12969 x_after_update_window_line
,
12970 x_update_window_begin
,
12971 x_update_window_end
,
12974 x_get_glyph_overhangs
,
12975 x_fix_overlapping_area
12981 rif
= &x_redisplay_interface
;
12983 clear_frame_hook
= x_clear_frame
;
12984 ins_del_lines_hook
= x_ins_del_lines
;
12985 change_line_highlight_hook
= x_change_line_highlight
;
12986 delete_glyphs_hook
= x_delete_glyphs
;
12987 ring_bell_hook
= XTring_bell
;
12988 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12989 set_terminal_modes_hook
= XTset_terminal_modes
;
12990 update_begin_hook
= x_update_begin
;
12991 update_end_hook
= x_update_end
;
12992 set_terminal_window_hook
= XTset_terminal_window
;
12993 read_socket_hook
= XTread_socket
;
12994 frame_up_to_date_hook
= XTframe_up_to_date
;
12995 reassert_line_highlight_hook
= XTreassert_line_highlight
;
12996 mouse_position_hook
= XTmouse_position
;
12997 frame_rehighlight_hook
= XTframe_rehighlight
;
12998 frame_raise_lower_hook
= XTframe_raise_lower
;
12999 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13000 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13001 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13002 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13003 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
13005 scroll_region_ok
= 1; /* we'll scroll partial frames */
13006 char_ins_del_ok
= 0; /* just as fast to write the line */
13007 line_ins_del_ok
= 1; /* we'll just blt 'em */
13008 fast_clear_end_of_line
= 1; /* X does this well */
13009 memory_below_frame
= 0; /* we don't remember what scrolls
13014 last_tool_bar_item
= -1;
13015 any_help_event_p
= 0;
13017 /* Try to use interrupt input; if we can't, then start polling. */
13018 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
13020 #ifdef USE_X_TOOLKIT
13021 XtToolkitInitialize ();
13022 Xt_app_con
= XtCreateApplicationContext ();
13023 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
13025 #if USE_TOOLKIT_SCROLL_BARS
13026 xaw3d_arrow_scroll
= False
;
13027 xaw3d_pick_top
= True
;
13030 /* Note that there is no real way portable across R3/R4 to get the
13031 original error handler. */
13032 XSetErrorHandler (x_error_handler
);
13033 XSetIOErrorHandler (x_io_error_quitter
);
13035 /* Disable Window Change signals; they are handled by X events. */
13037 signal (SIGWINCH
, SIG_DFL
);
13038 #endif /* ! defined (SIGWINCH) */
13040 signal (SIGPIPE
, x_connection_signal
);
13047 staticpro (&x_error_message_string
);
13048 x_error_message_string
= Qnil
;
13050 staticpro (&x_display_name_list
);
13051 x_display_name_list
= Qnil
;
13053 staticpro (&last_mouse_scroll_bar
);
13054 last_mouse_scroll_bar
= Qnil
;
13056 staticpro (&Qvendor_specific_keysyms
);
13057 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
13059 staticpro (&last_mouse_press_frame
);
13060 last_mouse_press_frame
= Qnil
;
13062 staticpro (&help_echo
);
13064 staticpro (&previous_help_echo
);
13065 previous_help_echo
= Qnil
;
13067 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
13068 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13069 For example, if a block cursor is over a tab, it will be drawn as\n\
13070 wide as that tab on the display.");
13071 x_stretch_cursor_p
= 0;
13073 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p
,
13074 "If not nil, Emacs uses toolkit scroll bars.");
13075 #if USE_TOOLKIT_SCROLL_BARS
13076 x_toolkit_scroll_bars_p
= 1;
13078 x_toolkit_scroll_bars_p
= 0;
13081 defsubr (&Sxt_process_timeouts
);
13082 staticpro (&last_mouse_motion_frame
);
13083 last_mouse_motion_frame
= Qnil
;
13086 #endif /* not HAVE_X_WINDOWS */