1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
45 #include <X11/cursorfont.h>
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> */
75 #include "dispextern.h"
77 #include "termhooks.h"
89 #include "intervals.h"
94 #include <X11/Shell.h>
97 #include <sys/types.h>
98 #ifdef HAVE_SYS_TIME_H
107 extern void free_frame_menubar ();
108 extern FRAME_PTR
x_menubar_window_to_frame ();
110 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112 extern void _XEditResCheckMessages ();
113 #endif /* not NO_EDITRES */
115 /* Include toolkit specific headers for the scroll bar widget. */
117 #ifdef USE_TOOLKIT_SCROLL_BARS
118 #if defined USE_MOTIF
119 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
120 #include <Xm/ScrollBar.h>
121 #include <Xm/ScrollBarP.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
139 #endif /* USE_X_TOOLKIT */
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
154 /* memmove will be defined as a macro in Xfuncs.h unless
155 <string.h> is included beforehand. The declaration for memmove in
156 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
161 #define min(a,b) ((a) < (b) ? (a) : (b))
164 #define max(a,b) ((a) > (b) ? (a) : (b))
167 #define abs(x) ((x) < 0 ? -(x) : (x))
169 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
172 /* Bitmaps for truncated lines. */
177 LEFT_TRUNCATION_BITMAP
,
178 RIGHT_TRUNCATION_BITMAP
,
179 OVERLAY_ARROW_BITMAP
,
180 CONTINUED_LINE_BITMAP
,
181 CONTINUATION_LINE_BITMAP
,
185 /* Bitmap drawn to indicate lines not displaying text if
186 `indicate-empty-lines' is non-nil. */
190 static unsigned char zv_bits
[] = {
191 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
193 /* An arrow like this: `<-'. */
196 #define left_height 8
197 static unsigned char left_bits
[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
200 /* Right truncation arrow bitmap `->'. */
202 #define right_width 8
203 #define right_height 8
204 static unsigned char right_bits
[] = {
205 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
207 /* Marker for continued lines. */
209 #define continued_width 8
210 #define continued_height 8
211 static unsigned char continued_bits
[] = {
212 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
214 /* Marker for continuation lines. */
216 #define continuation_width 8
217 #define continuation_height 8
218 static unsigned char continuation_bits
[] = {
219 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
221 /* Overlay arrow bitmap. */
227 static unsigned char ov_bits
[] = {
228 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
230 /* A triangular arrow. */
233 static unsigned char ov_bits
[] = {
234 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
238 extern Lisp_Object Qhelp_echo
;
241 /* Non-zero means Emacs uses toolkit scroll bars. */
243 int x_toolkit_scroll_bars_p
;
245 /* If a string, XTread_socket generates an event to display that string.
246 (The display is done in read_char.) */
248 static Lisp_Object help_echo
;
250 /* Temporary variable for XTread_socket. */
252 static Lisp_Object previous_help_echo
;
254 /* Non-zero means that a HELP_EVENT has been generated since Emacs
257 static int any_help_event_p
;
259 /* Non-zero means draw block and hollow cursor as wide as the glyph
260 under it. For example, if a block cursor is over a tab, it will be
261 drawn as wide as that tab on the display. */
263 int x_stretch_cursor_p
;
265 /* This is a chain of structures for all the X displays currently in
268 struct x_display_info
*x_display_list
;
270 /* This is a list of cons cells, each of the form (NAME
271 . FONT-LIST-CACHE), one for each element of x_display_list and in
272 the same order. NAME is the name of the frame. FONT-LIST-CACHE
273 records previous values returned by x-list-fonts. */
275 Lisp_Object x_display_name_list
;
277 /* Frame being updated by update_frame. This is declared in term.c.
278 This is set by update_begin and looked at by all the XT functions.
279 It is zero while not inside an update. In that case, the XT
280 functions assume that `selected_frame' is the frame to apply to. */
282 extern struct frame
*updating_frame
;
284 extern int waiting_for_input
;
286 /* This is a frame waiting to be auto-raised, within XTread_socket. */
288 struct frame
*pending_autoraise_frame
;
291 /* The application context for Xt use. */
292 XtAppContext Xt_app_con
;
293 static String Xt_default_resources
[] = {0};
294 #endif /* USE_X_TOOLKIT */
296 /* Nominal cursor position -- where to draw output.
297 HPOS and VPOS are window relative glyph matrix coordinates.
298 X and Y are window relative pixel coordinates. */
300 struct cursor_pos output_cursor
;
302 /* Non-zero means user is interacting with a toolkit scroll bar. */
304 static int toolkit_scroll_bar_interaction
;
308 Formerly, we used PointerMotionHintMask (in standard_event_mask)
309 so that we would have to call XQueryPointer after each MotionNotify
310 event to ask for another such event. However, this made mouse tracking
311 slow, and there was a bug that made it eventually stop.
313 Simply asking for MotionNotify all the time seems to work better.
315 In order to avoid asking for motion events and then throwing most
316 of them away or busy-polling the server for mouse positions, we ask
317 the server for pointer motion hints. This means that we get only
318 one event per group of mouse movements. "Groups" are delimited by
319 other kinds of events (focus changes and button clicks, for
320 example), or by XQueryPointer calls; when one of these happens, we
321 get another MotionNotify event the next time the mouse moves. This
322 is at least as efficient as getting motion events when mouse
323 tracking is on, and I suspect only negligibly worse when tracking
326 /* Where the mouse was last time we reported a mouse event. */
328 FRAME_PTR last_mouse_frame
;
329 static XRectangle last_mouse_glyph
;
330 static Lisp_Object last_mouse_press_frame
;
332 /* The scroll bar in which the last X motion event occurred.
334 If the last X motion event occurred in a scroll bar, we set this so
335 XTmouse_position can know whether to report a scroll bar motion or
338 If the last X motion event didn't occur in a scroll bar, we set
339 this to Qnil, to tell XTmouse_position to return an ordinary motion
342 static Lisp_Object last_mouse_scroll_bar
;
344 /* This is a hack. We would really prefer that XTmouse_position would
345 return the time associated with the position it returns, but there
346 doesn't seem to be any way to wrest the time-stamp from the server
347 along with the position query. So, we just keep track of the time
348 of the last movement we received, and return that in hopes that
349 it's somewhat accurate. */
351 static Time last_mouse_movement_time
;
353 /* Incremented by XTread_socket whenever it really tries to read
357 static int volatile input_signal_count
;
359 static int input_signal_count
;
362 /* Used locally within XTread_socket. */
364 static int x_noop_count
;
366 /* Initial values of argv and argc. */
368 extern char **initial_argv
;
369 extern int initial_argc
;
371 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
373 /* Tells if a window manager is present or not. */
375 extern Lisp_Object Vx_no_window_manager
;
377 extern Lisp_Object Qface
, Qmouse_face
;
381 /* A mask of extra modifier bits to put into every keyboard char. */
383 extern int extra_keyboard_modifiers
;
385 static Lisp_Object Qvendor_specific_keysyms
;
387 extern XrmDatabase
x_load_resources ();
388 extern Lisp_Object
x_icon_type ();
391 /* Enumeration for overriding/changing the face to use for drawing
392 glyphs in x_draw_glyphs. */
394 enum draw_glyphs_face
404 static void x_update_window_end
P_ ((struct window
*, int));
405 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
406 void x_delete_display
P_ ((struct x_display_info
*));
407 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
409 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
411 static void set_output_cursor
P_ ((struct cursor_pos
*));
412 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
413 int *, int *, int *));
414 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
415 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
416 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
417 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
418 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
419 static void show_mouse_face
P_ ((struct x_display_info
*,
420 enum draw_glyphs_face
));
421 static int x_io_error_quitter
P_ ((Display
*));
422 int x_catch_errors
P_ ((Display
*));
423 void x_uncatch_errors
P_ ((Display
*, int));
424 void x_lower_frame
P_ ((struct frame
*));
425 void x_scroll_bar_clear
P_ ((struct frame
*));
426 int x_had_errors_p
P_ ((Display
*));
427 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
428 void x_raise_frame
P_ ((struct frame
*));
429 void x_set_window_size
P_ ((struct frame
*, int, int, int));
430 void x_wm_set_window_state
P_ ((struct frame
*, int));
431 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
432 void x_initialize
P_ ((void));
433 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
434 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
435 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
437 enum draw_glyphs_face
));
438 static void x_update_end
P_ ((struct frame
*));
439 static void XTframe_up_to_date
P_ ((struct frame
*));
440 static void XTreassert_line_highlight
P_ ((int, int));
441 static void x_change_line_highlight
P_ ((int, int, int, int));
442 static void XTset_terminal_modes
P_ ((void));
443 static void XTreset_terminal_modes
P_ ((void));
444 static void XTcursor_to
P_ ((int, int, int, int));
445 static void x_write_glyphs
P_ ((struct glyph
*, int));
446 static void x_clear_end_of_line
P_ ((int));
447 static void x_clear_frame
P_ ((void));
448 static void x_clear_cursor
P_ ((struct window
*));
449 static void frame_highlight
P_ ((struct frame
*));
450 static void frame_unhighlight
P_ ((struct frame
*));
451 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
452 static void XTframe_rehighlight
P_ ((struct frame
*));
453 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
454 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
455 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int));
456 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
458 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
459 static void expose_window_tree
P_ ((struct window
*, XRectangle
*));
460 static void expose_window
P_ ((struct window
*, XRectangle
*));
461 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
462 XRectangle
*, enum glyph_row_area
));
463 static void expose_line
P_ ((struct window
*, struct glyph_row
*,
465 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
466 static void x_update_window_cursor
P_ ((struct window
*, int));
467 static void x_erase_phys_cursor
P_ ((struct window
*));
468 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
469 static void x_draw_bitmap
P_ ((struct window
*, struct glyph_row
*,
472 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
474 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
475 static void x_draw_row_bitmaps
P_ ((struct window
*, struct glyph_row
*));
476 static void note_overwritten_text_cursor
P_ ((struct window
*, int, int));
477 static void x_flush
P_ ((struct frame
*f
));
480 /* Flush display of frame F, or of all frames if F is null. */
489 Lisp_Object rest
, frame
;
490 FOR_EACH_FRAME (rest
, frame
)
491 x_flush (XFRAME (frame
));
493 else if (FRAME_X_P (f
))
494 XFlush (FRAME_X_DISPLAY (f
));
499 /* Remove calls to XFlush by defining XFlush to an empty replacement.
500 Calls to XFlush should be unnecessary because the X output buffer
501 is flushed automatically as needed by calls to XPending,
502 XNextEvent, or XWindowEvent according to the XFlush man page.
503 XTread_socket calls XPending. Removing XFlush improves
506 #define XFlush(DISPLAY) (void) 0
509 /***********************************************************************
511 ***********************************************************************/
515 /* This is a function useful for recording debugging information about
516 the sequence of occurrences in this file. */
524 struct record event_record
[100];
526 int event_record_index
;
528 record_event (locus
, type
)
532 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
533 event_record_index
= 0;
535 event_record
[event_record_index
].locus
= locus
;
536 event_record
[event_record_index
].type
= type
;
537 event_record_index
++;
544 /* Return the struct x_display_info corresponding to DPY. */
546 struct x_display_info
*
547 x_display_info_for_display (dpy
)
550 struct x_display_info
*dpyinfo
;
552 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
553 if (dpyinfo
->display
== dpy
)
561 /***********************************************************************
562 Starting and ending an update
563 ***********************************************************************/
565 /* Start an update of frame F. This function is installed as a hook
566 for update_begin, i.e. it is called when update_begin is called.
567 This function is called prior to calls to x_update_window_begin for
568 each window being updated. Currently, there is nothing to do here
569 because all interesting stuff is done on a window basis. */
579 /* Start update of window W. Set the global variable updated_window
580 to the window being updated and set output_cursor to the cursor
584 x_update_window_begin (w
)
587 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
588 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
591 set_output_cursor (&w
->cursor
);
595 if (f
== display_info
->mouse_face_mouse_frame
)
597 /* Don't do highlighting for mouse motion during the update. */
598 display_info
->mouse_face_defer
= 1;
600 /* If F needs to be redrawn, simply forget about any prior mouse
602 if (FRAME_GARBAGED_P (f
))
603 display_info
->mouse_face_window
= Qnil
;
605 /* Can we tell that this update does not affect the window
606 where the mouse highlight is? If so, no need to turn off.
607 Likewise, don't do anything if the frame is garbaged;
608 in that case, the frame's current matrix that we would use
609 is all wrong, and we will redisplay that line anyway. */
610 if (!NILP (display_info
->mouse_face_window
)
611 && w
== XWINDOW (display_info
->mouse_face_window
))
615 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
616 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
619 if (i
< w
->desired_matrix
->nrows
)
620 clear_mouse_face (display_info
);
628 /* Draw a vertical window border to the right of window W if W doesn't
629 have vertical scroll bars. */
632 x_draw_vertical_border (w
)
635 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
637 /* Redraw borders between horizontally adjacent windows. Don't
638 do it for frames with vertical scroll bars because either the
639 right scroll bar of a window, or the left scroll bar of its
640 neighbor will suffice as a border. */
641 if (!WINDOW_RIGHTMOST_P (w
)
642 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
646 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
647 x1
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
);
650 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
651 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
656 /* End update of window W (which is equal to updated_window). Draw
657 vertical borders between horizontally adjacent windows, and display
658 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
659 pseudo-window in case we don't have X toolkit support. Such
660 windows don't have a cursor, so don't display it here. */
663 x_update_window_end (w
, cursor_on_p
)
667 if (!w
->pseudo_window_p
)
671 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
673 output_cursor
.x
, output_cursor
.y
);
674 x_draw_vertical_border (w
);
678 updated_window
= NULL
;
682 /* End update of frame F. This function is installed as a hook in
689 /* Mouse highlight may be displayed again. */
690 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
693 XFlush (FRAME_X_DISPLAY (f
));
698 /* This function is called from various places in xdisp.c whenever a
699 complete update has been performed. The global variable
700 updated_window is not available here. */
703 XTframe_up_to_date (f
)
708 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
709 if (dpyinfo
->mouse_face_deferred_gc
710 || f
== dpyinfo
->mouse_face_mouse_frame
)
713 if (dpyinfo
->mouse_face_mouse_frame
)
714 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
715 dpyinfo
->mouse_face_mouse_x
,
716 dpyinfo
->mouse_face_mouse_y
);
717 dpyinfo
->mouse_face_deferred_gc
= 0;
724 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
725 arrow bitmaps, or clear the areas where they would be displayed
726 before DESIRED_ROW is made current. The window being updated is
727 found in updated_window. This function It is called from
728 update_window_line only if it is known that there are differences
729 between bitmaps to be drawn between current row and DESIRED_ROW. */
732 x_after_update_window_line (desired_row
)
733 struct glyph_row
*desired_row
;
735 struct window
*w
= updated_window
;
739 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
742 x_draw_row_bitmaps (w
, desired_row
);
744 /* When a window has disappeared, make sure that no rest of
745 full-width rows stays visible in the internal border. */
746 if (windows_or_buffers_changed
)
748 struct frame
*f
= XFRAME (w
->frame
);
749 int width
= FRAME_INTERNAL_BORDER_WIDTH (f
);
750 int height
= desired_row
->visible_height
;
751 int x
= (window_box_right (w
, -1)
752 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
));
753 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
755 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
756 x
, y
, width
, height
, False
);
764 /* Draw the bitmap WHICH in one of the areas to the left or right of
765 window W. ROW is the glyph row for which to display the bitmap; it
766 determines the vertical position at which the bitmap has to be
770 x_draw_bitmap (w
, row
, which
)
772 struct glyph_row
*row
;
773 enum bitmap_type which
;
775 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
776 Display
*display
= FRAME_X_DISPLAY (f
);
777 Window window
= FRAME_X_WINDOW (f
);
781 GC gc
= f
->output_data
.x
->normal_gc
;
783 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
785 /* Must clip because of partially visible lines. */
786 x_clip_to_row (w
, row
, gc
, 1);
790 case LEFT_TRUNCATION_BITMAP
:
794 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
796 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
799 case OVERLAY_ARROW_BITMAP
:
803 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
805 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
808 case RIGHT_TRUNCATION_BITMAP
:
812 x
= window_box_right (w
, -1);
813 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
816 case CONTINUED_LINE_BITMAP
:
819 bits
= continued_bits
;
820 x
= window_box_right (w
, -1);
821 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
824 case CONTINUATION_LINE_BITMAP
:
825 wd
= continuation_width
;
826 h
= continuation_height
;
827 bits
= continuation_bits
;
828 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
830 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
837 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
839 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
846 /* Convert to frame coordinates. Set dy to the offset in the row to
847 start drawing the bitmap. */
848 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
849 dy
= (row
->height
- h
) / 2;
851 /* Draw the bitmap. I believe these small pixmaps can be cached
853 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
854 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
856 face
->background
, depth
);
857 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
858 XFreePixmap (display
, pixmap
);
859 XSetClipMask (display
, gc
, None
);
863 /* Draw flags bitmaps for glyph row ROW on window W. Call this
864 function with input blocked. */
867 x_draw_row_bitmaps (w
, row
)
869 struct glyph_row
*row
;
871 struct frame
*f
= XFRAME (w
->frame
);
872 enum bitmap_type bitmap
;
874 int header_line_height
= -1;
876 xassert (interrupt_input_blocked
);
878 /* If row is completely invisible, because of vscrolling, we
879 don't have to draw anything. */
880 if (row
->visible_height
<= 0)
883 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
884 PREPARE_FACE_FOR_DISPLAY (f
, face
);
886 /* Decide which bitmap to draw at the left side. */
887 if (row
->overlay_arrow_p
)
888 bitmap
= OVERLAY_ARROW_BITMAP
;
889 else if (row
->truncated_on_left_p
)
890 bitmap
= LEFT_TRUNCATION_BITMAP
;
891 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
892 bitmap
= CONTINUATION_LINE_BITMAP
;
893 else if (row
->indicate_empty_line_p
)
894 bitmap
= ZV_LINE_BITMAP
;
898 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
900 if (bitmap
== NO_BITMAP
901 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
902 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
904 /* If W has a vertical border to its left, don't draw over it. */
905 int border
= ((XFASTINT (w
->left
) > 0
906 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
908 int left
= window_box_left (w
, -1);
910 if (header_line_height
< 0)
911 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
913 /* In case the same realized face is used for bitmap areas and
914 for something displayed in the text (e.g. face `region' on
915 mono-displays, the fill style may have been changed to
916 FillSolid in x_draw_glyph_string_background. */
918 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
920 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
922 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
925 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
927 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
929 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - border
,
930 row
->visible_height
);
932 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
935 /* Draw the left bitmap. */
936 if (bitmap
!= NO_BITMAP
)
937 x_draw_bitmap (w
, row
, bitmap
);
939 /* Decide which bitmap to draw at the right side. */
940 if (row
->truncated_on_right_p
)
941 bitmap
= RIGHT_TRUNCATION_BITMAP
;
942 else if (row
->continued_p
)
943 bitmap
= CONTINUED_LINE_BITMAP
;
947 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
949 if (bitmap
== NO_BITMAP
950 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
)
951 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
953 int right
= window_box_right (w
, -1);
955 if (header_line_height
< 0)
956 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
958 /* In case the same realized face is used for bitmap areas and
959 for something displayed in the text (e.g. face `region' on
960 mono-displays, the fill style may have been changed to
961 FillSolid in x_draw_glyph_string_background. */
963 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
965 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
966 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
969 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
971 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
),
972 row
->visible_height
);
974 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
977 /* Draw the right bitmap. */
978 if (bitmap
!= NO_BITMAP
)
979 x_draw_bitmap (w
, row
, bitmap
);
983 /***********************************************************************
985 ***********************************************************************/
987 /* External interface to control of standout mode. Not used for X
988 frames. Aborts when called. */
991 XTreassert_line_highlight (new, vpos
)
998 /* Call this when about to modify line at position VPOS and change
999 whether it is highlighted. Not used for X frames. Aborts when
1003 x_change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
1004 int new_highlight
, vpos
, y
, first_unused_hpos
;
1010 /* This is called when starting Emacs and when restarting after
1011 suspend. When starting Emacs, no X window is mapped. And nothing
1012 must be done to Emacs's own window if it is suspended (though that
1016 XTset_terminal_modes ()
1020 /* This is called when exiting or suspending Emacs. Exiting will make
1021 the X-windows go away, and suspending requires no action. */
1024 XTreset_terminal_modes ()
1030 /***********************************************************************
1032 ***********************************************************************/
1034 /* Set the global variable output_cursor to CURSOR. All cursor
1035 positions are relative to updated_window. */
1038 set_output_cursor (cursor
)
1039 struct cursor_pos
*cursor
;
1041 output_cursor
.hpos
= cursor
->hpos
;
1042 output_cursor
.vpos
= cursor
->vpos
;
1043 output_cursor
.x
= cursor
->x
;
1044 output_cursor
.y
= cursor
->y
;
1048 /* Set a nominal cursor position.
1050 HPOS and VPOS are column/row positions in a window glyph matrix. X
1051 and Y are window text area relative pixel positions.
1053 If this is done during an update, updated_window will contain the
1054 window that is being updated and the position is the future output
1055 cursor position for that window. If updated_window is null, use
1056 selected_window and display the cursor at the given position. */
1059 XTcursor_to (vpos
, hpos
, y
, x
)
1060 int vpos
, hpos
, y
, x
;
1064 /* If updated_window is not set, work on selected_window. */
1068 w
= XWINDOW (selected_window
);
1070 /* Set the output cursor. */
1071 output_cursor
.hpos
= hpos
;
1072 output_cursor
.vpos
= vpos
;
1073 output_cursor
.x
= x
;
1074 output_cursor
.y
= y
;
1076 /* If not called as part of an update, really display the cursor.
1077 This will also set the cursor position of W. */
1078 if (updated_window
== NULL
)
1081 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1082 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1089 /***********************************************************************
1091 ***********************************************************************/
1093 /* Function prototypes of this page. */
1095 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1099 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1100 int, XChar2b
*, int));
1101 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1102 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1103 static void x_append_glyph
P_ ((struct it
*));
1104 static void x_append_composite_glyph
P_ ((struct it
*));
1105 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1107 static void x_produce_glyphs
P_ ((struct it
*));
1108 static void x_produce_image_glyph
P_ ((struct it
*it
));
1111 /* Return a pointer to per-char metric information in FONT of a
1112 character pointed by B which is a pointer to an XChar2b. */
1114 #define PER_CHAR_METRIC(font, b) \
1116 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1117 + (((font)->min_byte1 || (font)->max_byte1) \
1118 ? (((b)->byte1 - (font)->min_byte1) \
1119 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1121 : &((font)->max_bounds))
1124 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1125 is not contained in the font. */
1127 static INLINE XCharStruct
*
1128 x_per_char_metric (font
, char2b
)
1132 /* The result metric information. */
1133 XCharStruct
*pcm
= NULL
;
1135 xassert (font
&& char2b
);
1137 if (font
->per_char
!= NULL
)
1139 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1141 /* min_char_or_byte2 specifies the linear character index
1142 corresponding to the first element of the per_char array,
1143 max_char_or_byte2 is the index of the last character. A
1144 character with non-zero CHAR2B->byte1 is not in the font.
1145 A character with byte2 less than min_char_or_byte2 or
1146 greater max_char_or_byte2 is not in the font. */
1147 if (char2b
->byte1
== 0
1148 && char2b
->byte2
>= font
->min_char_or_byte2
1149 && char2b
->byte2
<= font
->max_char_or_byte2
)
1150 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1154 /* If either min_byte1 or max_byte1 are nonzero, both
1155 min_char_or_byte2 and max_char_or_byte2 are less than
1156 256, and the 2-byte character index values corresponding
1157 to the per_char array element N (counting from 0) are:
1159 byte1 = N/D + min_byte1
1160 byte2 = N\D + min_char_or_byte2
1164 D = max_char_or_byte2 - min_char_or_byte2 + 1
1165 / = integer division
1166 \ = integer modulus */
1167 if (char2b
->byte1
>= font
->min_byte1
1168 && char2b
->byte1
<= font
->max_byte1
1169 && char2b
->byte2
>= font
->min_char_or_byte2
1170 && char2b
->byte2
<= font
->max_char_or_byte2
)
1172 pcm
= (font
->per_char
1173 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1174 * (char2b
->byte1
- font
->min_byte1
))
1175 + (char2b
->byte2
- font
->min_char_or_byte2
));
1181 /* If the per_char pointer is null, all glyphs between the first
1182 and last character indexes inclusive have the same
1183 information, as given by both min_bounds and max_bounds. */
1184 if (char2b
->byte2
>= font
->min_char_or_byte2
1185 && char2b
->byte2
<= font
->max_char_or_byte2
)
1186 pcm
= &font
->max_bounds
;
1189 return ((pcm
== NULL
1190 || pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0)
1195 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1196 the two-byte form of C. Encoding is returned in *CHAR2B. */
1199 x_encode_char (c
, char2b
, font_info
)
1202 struct font_info
*font_info
;
1204 int charset
= CHAR_CHARSET (c
);
1205 XFontStruct
*font
= font_info
->font
;
1207 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1208 This may be either a program in a special encoder language or a
1210 if (font_info
->font_encoder
)
1212 /* It's a program. */
1213 struct ccl_program
*ccl
= font_info
->font_encoder
;
1215 if (CHARSET_DIMENSION (charset
) == 1)
1217 ccl
->reg
[0] = charset
;
1218 ccl
->reg
[1] = char2b
->byte2
;
1222 ccl
->reg
[0] = charset
;
1223 ccl
->reg
[1] = char2b
->byte1
;
1224 ccl
->reg
[2] = char2b
->byte2
;
1227 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1229 /* We assume that MSBs are appropriately set/reset by CCL
1231 if (font
->max_byte1
== 0) /* 1-byte font */
1232 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1234 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1236 else if (font_info
->encoding
[charset
])
1238 /* Fixed encoding scheme. See fontset.h for the meaning of the
1239 encoding numbers. */
1240 int enc
= font_info
->encoding
[charset
];
1242 if ((enc
== 1 || enc
== 2)
1243 && CHARSET_DIMENSION (charset
) == 2)
1244 char2b
->byte1
|= 0x80;
1246 if (enc
== 1 || enc
== 3)
1247 char2b
->byte2
|= 0x80;
1252 /* Get face and two-byte form of character C in face FACE_ID on frame
1253 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1254 means we want to display multibyte text. Value is a pointer to a
1255 realized face that is ready for display. */
1257 static INLINE
struct face
*
1258 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1264 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1268 /* Unibyte case. We don't have to encode, but we have to make
1269 sure to use a face suitable for unibyte. */
1272 face_id
= FACE_FOR_CHAR (f
, face
, c
);
1273 face
= FACE_FROM_ID (f
, face_id
);
1275 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1277 /* Case of ASCII in a face known to fit ASCII. */
1283 int c1
, c2
, charset
;
1285 /* Split characters into bytes. If c2 is -1 afterwards, C is
1286 really a one-byte character so that byte1 is zero. */
1287 SPLIT_CHAR (c
, charset
, c1
, c2
);
1289 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1291 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1293 /* Maybe encode the character in *CHAR2B. */
1294 if (face
->font
!= NULL
)
1296 struct font_info
*font_info
1297 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1299 x_encode_char (c
, char2b
, font_info
);
1303 /* Make sure X resources of the face are allocated. */
1304 xassert (face
!= NULL
);
1305 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1311 /* Get face and two-byte form of character glyph GLYPH on frame F.
1312 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1313 a pointer to a realized face that is ready for display. */
1315 static INLINE
struct face
*
1316 x_get_glyph_face_and_encoding (f
, glyph
, char2b
, two_byte_p
)
1318 struct glyph
*glyph
;
1324 xassert (glyph
->type
== CHAR_GLYPH
);
1325 face
= FACE_FROM_ID (f
, glyph
->face_id
);
1330 if (!glyph
->multibyte_p
)
1332 /* Unibyte case. We don't have to encode, but we have to make
1333 sure to use a face suitable for unibyte. */
1335 char2b
->byte2
= glyph
->u
.ch
;
1337 else if (glyph
->u
.ch
< 128
1338 && glyph
->face_id
< BASIC_FACE_ID_SENTINEL
)
1340 /* Case of ASCII in a face known to fit ASCII. */
1342 char2b
->byte2
= glyph
->u
.ch
;
1346 int c1
, c2
, charset
;
1348 /* Split characters into bytes. If c2 is -1 afterwards, C is
1349 really a one-byte character so that byte1 is zero. */
1350 SPLIT_CHAR (glyph
->u
.ch
, charset
, c1
, c2
);
1352 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1354 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1356 /* Maybe encode the character in *CHAR2B. */
1357 if (charset
!= CHARSET_ASCII
)
1359 struct font_info
*font_info
1360 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1363 x_encode_char (glyph
->u
.ch
, char2b
, font_info
);
1366 = ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1371 /* Make sure X resources of the face are allocated. */
1372 xassert (face
!= NULL
);
1373 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1378 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1379 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1385 struct glyph
*glyph
;
1386 enum glyph_row_area area
= it
->area
;
1388 xassert (it
->glyph_row
);
1389 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1391 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1392 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1394 /* Play it safe. If sub-structures of the glyph are not all the
1395 same size, it otherwise be that some bits stay set. This
1396 would prevent a comparison with GLYPH_EQUAL_P. */
1399 glyph
->type
= CHAR_GLYPH
;
1400 glyph
->pixel_width
= it
->pixel_width
;
1401 glyph
->u
.ch
= it
->char_to_display
;
1402 glyph
->face_id
= it
->face_id
;
1403 glyph
->charpos
= CHARPOS (it
->position
);
1404 glyph
->object
= it
->object
;
1405 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1406 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1407 glyph
->voffset
= it
->voffset
;
1408 glyph
->multibyte_p
= it
->multibyte_p
;
1409 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1410 || it
->phys_descent
> it
->descent
);
1411 glyph
->glyph_not_available_p
= it
->glyph_not_available_p
;
1412 ++it
->glyph_row
->used
[area
];
1416 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1417 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1420 x_append_composite_glyph (it
)
1423 struct glyph
*glyph
;
1424 enum glyph_row_area area
= it
->area
;
1426 xassert (it
->glyph_row
);
1428 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1429 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1431 /* Play it safe. If sub-structures of the glyph are not all the
1432 same size, it otherwise be that some bits stay set. This
1433 would prevent a comparison with GLYPH_EQUAL_P. */
1436 glyph
->type
= COMPOSITE_GLYPH
;
1437 glyph
->pixel_width
= it
->pixel_width
;
1438 glyph
->u
.cmp_id
= it
->cmp_id
;
1439 glyph
->face_id
= it
->face_id
;
1440 glyph
->charpos
= CHARPOS (it
->position
);
1441 glyph
->object
= it
->object
;
1442 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1443 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1444 glyph
->voffset
= it
->voffset
;
1445 glyph
->multibyte_p
= it
->multibyte_p
;
1446 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1447 || it
->phys_descent
> it
->descent
);
1448 ++it
->glyph_row
->used
[area
];
1453 /* Change IT->ascent and IT->height according to the setting of
1457 take_vertical_position_into_account (it
)
1462 if (it
->voffset
< 0)
1463 /* Increase the ascent so that we can display the text higher
1465 it
->ascent
+= abs (it
->voffset
);
1467 /* Increase the descent so that we can display the text lower
1469 it
->descent
+= it
->voffset
;
1474 /* Produce glyphs/get display metrics for the image IT is loaded with.
1475 See the description of struct display_iterator in dispextern.h for
1476 an overview of struct display_iterator. */
1479 x_produce_image_glyph (it
)
1485 xassert (it
->what
== IT_IMAGE
);
1487 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1488 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1491 /* Make sure X resources of the face and image are loaded. */
1492 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1493 prepare_image_for_display (it
->f
, img
);
1495 it
->ascent
= it
->phys_ascent
= image_ascent (img
, face
);
1496 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->margin
- it
->ascent
;
1497 it
->pixel_width
= img
->width
+ 2 * img
->margin
;
1501 if (face
->box
!= FACE_NO_BOX
)
1503 it
->ascent
+= face
->box_line_width
;
1504 it
->descent
+= face
->box_line_width
;
1506 if (it
->start_of_box_run_p
)
1507 it
->pixel_width
+= face
->box_line_width
;
1508 if (it
->end_of_box_run_p
)
1509 it
->pixel_width
+= face
->box_line_width
;
1512 take_vertical_position_into_account (it
);
1516 struct glyph
*glyph
;
1517 enum glyph_row_area area
= it
->area
;
1519 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1520 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1522 glyph
->type
= IMAGE_GLYPH
;
1523 glyph
->u
.img_id
= img
->id
;
1524 glyph
->face_id
= it
->face_id
;
1525 glyph
->pixel_width
= it
->pixel_width
;
1526 glyph
->charpos
= CHARPOS (it
->position
);
1527 glyph
->object
= it
->object
;
1528 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1529 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1530 glyph
->voffset
= it
->voffset
;
1531 glyph
->multibyte_p
= it
->multibyte_p
;
1532 ++it
->glyph_row
->used
[area
];
1538 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1539 of the glyph, WIDTH and HEIGHT are the width and height of the
1540 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1541 ascent of the glyph (0 <= ASCENT <= 1). */
1544 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1550 struct glyph
*glyph
;
1551 enum glyph_row_area area
= it
->area
;
1553 xassert (ascent
>= 0 && ascent
<= 1);
1555 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1556 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1558 glyph
->type
= STRETCH_GLYPH
;
1559 glyph
->u
.stretch
.ascent
= height
* ascent
;
1560 glyph
->u
.stretch
.height
= height
;
1561 glyph
->face_id
= it
->face_id
;
1562 glyph
->pixel_width
= width
;
1563 glyph
->charpos
= CHARPOS (it
->position
);
1564 glyph
->object
= object
;
1565 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1566 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1567 glyph
->voffset
= it
->voffset
;
1568 glyph
->multibyte_p
= it
->multibyte_p
;
1569 ++it
->glyph_row
->used
[area
];
1574 /* Produce a stretch glyph for iterator IT. IT->object is the value
1575 of the glyph property displayed. The value must be a list
1576 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1579 1. `:width WIDTH' specifies that the space should be WIDTH *
1580 canonical char width wide. WIDTH may be an integer or floating
1583 2. `:relative-width FACTOR' specifies that the width of the stretch
1584 should be computed from the width of the first character having the
1585 `glyph' property, and should be FACTOR times that width.
1587 3. `:align-to HPOS' specifies that the space should be wide enough
1588 to reach HPOS, a value in canonical character units.
1590 Exactly one of the above pairs must be present.
1592 4. `:height HEIGHT' specifies that the height of the stretch produced
1593 should be HEIGHT, measured in canonical character units.
1595 5. `:relative-height FACTOR' specifies that the height of the the
1596 stretch should be FACTOR times the height of the characters having
1599 Either none or exactly one of 4 or 5 must be present.
1601 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1602 of the stretch should be used for the ascent of the stretch.
1603 ASCENT must be in the range 0 <= ASCENT <= 100. */
1606 ((INTEGERP (X) || FLOATP (X)) \
1612 x_produce_stretch_glyph (it
)
1615 /* (space :width WIDTH :height HEIGHT. */
1616 extern Lisp_Object QCwidth
, QCheight
, QCascent
, Qspace
;
1617 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1618 extern Lisp_Object QCalign_to
;
1619 Lisp_Object prop
, plist
;
1620 double width
= 0, height
= 0, ascent
= 0;
1621 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1622 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1624 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1626 /* List should start with `space'. */
1627 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1628 plist
= XCDR (it
->object
);
1630 /* Compute the width of the stretch. */
1631 if (prop
= Fplist_get (plist
, QCwidth
),
1633 /* Absolute width `:width WIDTH' specified and valid. */
1634 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1635 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1638 /* Relative width `:relative-width FACTOR' specified and valid.
1639 Compute the width of the characters having the `glyph'
1642 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1645 if (it
->multibyte_p
)
1647 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1648 - IT_BYTEPOS (*it
));
1649 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1652 it2
.c
= *p
, it2
.len
= 1;
1654 it2
.glyph_row
= NULL
;
1655 it2
.what
= IT_CHARACTER
;
1656 x_produce_glyphs (&it2
);
1657 width
= NUMVAL (prop
) * it2
.pixel_width
;
1659 else if (prop
= Fplist_get (plist
, QCalign_to
),
1661 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1663 /* Nothing specified -> width defaults to canonical char width. */
1664 width
= CANON_X_UNIT (it
->f
);
1666 /* Compute height. */
1667 if (prop
= Fplist_get (plist
, QCheight
),
1669 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1670 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1672 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1674 height
= FONT_HEIGHT (font
);
1676 /* Compute percentage of height used for ascent. If
1677 `:ascent ASCENT' is present and valid, use that. Otherwise,
1678 derive the ascent from the font in use. */
1679 if (prop
= Fplist_get (plist
, QCascent
),
1680 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1681 ascent
= NUMVAL (prop
) / 100.0;
1683 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1692 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1693 if (!STRINGP (object
))
1694 object
= it
->w
->buffer
;
1695 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1698 it
->pixel_width
= width
;
1699 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1700 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1703 if (face
->box
!= FACE_NO_BOX
)
1705 it
->ascent
+= face
->box_line_width
;
1706 it
->descent
+= face
->box_line_width
;
1708 if (it
->start_of_box_run_p
)
1709 it
->pixel_width
+= face
->box_line_width
;
1710 if (it
->end_of_box_run_p
)
1711 it
->pixel_width
+= face
->box_line_width
;
1714 take_vertical_position_into_account (it
);
1717 /* Return proper value to be used as baseline offset of font that has
1718 ASCENT and DESCENT to draw characters by the font at the vertical
1719 center of the line of frame F.
1721 Here, out task is to find the value of BOFF in the following figure;
1723 -------------------------+-----------+-
1724 -+-+---------+-+ | |
1726 | | | | F_ASCENT F_HEIGHT
1729 | | |-|-+------+-----------|------- baseline
1731 | |---------|-+-+ | |
1733 -+-+---------+-+ F_DESCENT |
1734 -------------------------+-----------+-
1736 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1737 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1738 DESCENT = FONT->descent
1739 HEIGHT = FONT_HEIGHT (FONT)
1740 F_DESCENT = (F->output_data.x->font->descent
1741 - F->output_data.x->baseline_offset)
1742 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1745 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1747 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1748 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1750 /* Produce glyphs/get display metrics for the display element IT is
1751 loaded with. See the description of struct display_iterator in
1752 dispextern.h for an overview of struct display_iterator. */
1755 x_produce_glyphs (it
)
1758 it
->glyph_not_available_p
= 0;
1760 if (it
->what
== IT_CHARACTER
)
1764 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1766 int font_not_found_p
;
1767 struct font_info
*font_info
;
1768 int boff
; /* baseline offset */
1770 /* Maybe translate single-byte characters to multibyte, or the
1772 it
->char_to_display
= it
->c
;
1773 if (!ASCII_BYTE_P (it
->c
))
1775 if (unibyte_display_via_language_environment
1776 && SINGLE_BYTE_CHAR_P (it
->c
)
1778 || !NILP (Vnonascii_translation_table
)))
1780 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1781 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1782 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1784 else if (!SINGLE_BYTE_CHAR_P (it
->c
)
1785 && !it
->multibyte_p
)
1787 it
->char_to_display
= multibyte_char_to_unibyte (it
->c
, Qnil
);
1788 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
1789 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1793 /* Get font to use. Encode IT->char_to_display. */
1794 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1795 it
->face_id
, &char2b
,
1799 /* When no suitable font found, use the default font. */
1800 font_not_found_p
= font
== NULL
;
1801 if (font_not_found_p
)
1803 font
= FRAME_FONT (it
->f
);
1804 boff
= it
->f
->output_data
.x
->baseline_offset
;
1809 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
1810 boff
= font_info
->baseline_offset
;
1811 if (font_info
->vertical_centering
)
1812 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
1815 if (it
->char_to_display
>= ' '
1816 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1818 /* Either unibyte or ASCII. */
1823 pcm
= x_per_char_metric (font
, &char2b
);
1824 it
->ascent
= font
->ascent
+ boff
;
1825 it
->descent
= font
->descent
- boff
;
1829 it
->phys_ascent
= pcm
->ascent
+ boff
;
1830 it
->phys_descent
= pcm
->descent
- boff
;
1831 it
->pixel_width
= pcm
->width
;
1835 it
->glyph_not_available_p
= 1;
1836 it
->phys_ascent
= font
->ascent
+ boff
;
1837 it
->phys_descent
= font
->descent
- boff
;
1838 it
->pixel_width
= FONT_WIDTH (font
);
1841 /* If this is a space inside a region of text with
1842 `space-width' property, change its width. */
1843 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1845 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1847 /* If face has a box, add the box thickness to the character
1848 height. If character has a box line to the left and/or
1849 right, add the box line width to the character's width. */
1850 if (face
->box
!= FACE_NO_BOX
)
1852 int thick
= face
->box_line_width
;
1854 it
->ascent
+= thick
;
1855 it
->descent
+= thick
;
1857 if (it
->start_of_box_run_p
)
1858 it
->pixel_width
+= thick
;
1859 if (it
->end_of_box_run_p
)
1860 it
->pixel_width
+= thick
;
1863 /* If face has an overline, add the height of the overline
1864 (1 pixel) and a 1 pixel margin to the character height. */
1865 if (face
->overline_p
)
1868 take_vertical_position_into_account (it
);
1870 /* If we have to actually produce glyphs, do it. */
1875 /* Translate a space with a `space-width' property
1876 into a stretch glyph. */
1877 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1878 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1879 it
->ascent
+ it
->descent
, ascent
);
1882 x_append_glyph (it
);
1884 /* If characters with lbearing or rbearing are displayed
1885 in this line, record that fact in a flag of the
1886 glyph row. This is used to optimize X output code. */
1887 if (pcm
&& (pcm
->lbearing
< 0 || pcm
->rbearing
> pcm
->width
))
1888 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1891 else if (it
->char_to_display
== '\n')
1893 /* A newline has no width but we need the height of the line. */
1894 it
->pixel_width
= 0;
1896 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1897 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1899 if (face
->box
!= FACE_NO_BOX
)
1901 int thick
= face
->box_line_width
;
1902 it
->ascent
+= thick
;
1903 it
->descent
+= thick
;
1906 else if (it
->char_to_display
== '\t')
1908 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1909 int x
= it
->current_x
+ it
->continuation_lines_width
;
1910 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1912 it
->pixel_width
= next_tab_x
- x
;
1914 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1915 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1919 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1920 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1921 it
->ascent
+ it
->descent
, ascent
);
1926 /* A multi-byte character. Assume that the display width of the
1927 character is the width of the character multiplied by the
1928 width of the font. */
1930 /* If we found a font, this font should give us the right
1931 metrics. If we didn't find a font, use the frame's
1932 default font and calculate the width of the character
1933 from the charset width; this is what old redisplay code
1935 pcm
= x_per_char_metric (font
, &char2b
);
1936 if (font_not_found_p
|| !pcm
)
1938 int charset
= CHAR_CHARSET (it
->char_to_display
);
1940 it
->glyph_not_available_p
= 1;
1941 it
->pixel_width
= (FONT_WIDTH (FRAME_FONT (it
->f
))
1942 * CHARSET_WIDTH (charset
));
1943 it
->phys_ascent
= font
->ascent
+ boff
;
1944 it
->phys_descent
= font
->descent
- boff
;
1948 it
->pixel_width
= pcm
->width
;
1949 it
->phys_ascent
= pcm
->ascent
+ boff
;
1950 it
->phys_descent
= pcm
->descent
- boff
;
1952 && (pcm
->lbearing
< 0
1953 || pcm
->rbearing
> pcm
->width
))
1954 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1957 it
->ascent
= font
->ascent
+ boff
;
1958 it
->descent
= font
->descent
- boff
;
1959 if (face
->box
!= FACE_NO_BOX
)
1961 int thick
= face
->box_line_width
;
1962 it
->ascent
+= thick
;
1963 it
->descent
+= thick
;
1965 if (it
->start_of_box_run_p
)
1966 it
->pixel_width
+= thick
;
1967 if (it
->end_of_box_run_p
)
1968 it
->pixel_width
+= thick
;
1971 /* If face has an overline, add the height of the overline
1972 (1 pixel) and a 1 pixel margin to the character height. */
1973 if (face
->overline_p
)
1976 take_vertical_position_into_account (it
);
1979 x_append_glyph (it
);
1982 else if (it
->what
== IT_COMPOSITION
)
1984 /* Note: A composition is represented as one glyph in the
1985 glyph matrix. There are no padding glyphs. */
1988 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1990 int font_not_found_p
;
1991 struct font_info
*font_info
;
1992 int boff
; /* baseline offset */
1993 struct composition
*cmp
= composition_table
[it
->cmp_id
];
1995 /* Maybe translate single-byte characters to multibyte. */
1996 it
->char_to_display
= it
->c
;
1997 if (unibyte_display_via_language_environment
1998 && SINGLE_BYTE_CHAR_P (it
->c
)
2001 && !NILP (Vnonascii_translation_table
))))
2003 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2006 /* Get face and font to use. Encode IT->char_to_display. */
2007 it
->face_id
= FACE_FOR_CHAR (it
->f
, face
, it
->char_to_display
);
2008 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
2009 x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2010 it
->face_id
, &char2b
, it
->multibyte_p
);
2013 /* When no suitable font found, use the default font. */
2014 font_not_found_p
= font
== NULL
;
2015 if (font_not_found_p
)
2017 font
= FRAME_FONT (it
->f
);
2018 boff
= it
->f
->output_data
.x
->baseline_offset
;
2023 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2024 boff
= font_info
->baseline_offset
;
2025 if (font_info
->vertical_centering
)
2026 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2029 /* There are no padding glyphs, so there is only one glyph to
2030 produce for the composition. Important is that pixel_width,
2031 ascent and descent are the values of what is drawn by
2032 draw_glyphs (i.e. the values of the overall glyphs composed). */
2035 /* If we have not yet calculated pixel size data of glyphs of
2036 the composition for the current face font, calculate them
2037 now. Theoretically, we have to check all fonts for the
2038 glyphs, but that requires much time and memory space. So,
2039 here we check only the font of the first glyph. This leads
2040 to incorrect display very rarely, and C-l (recenter) can
2041 correct the display anyway. */
2042 if (cmp
->font
!= (void *) font
)
2044 /* Ascent and descent of the font of the first character of
2045 this composition (adjusted by baseline offset). Ascent
2046 and descent of overall glyphs should not be less than
2047 them respectively. */
2048 int font_ascent
= font
->ascent
+ boff
;
2049 int font_descent
= font
->descent
- boff
;
2050 /* Bounding box of the overall glyphs. */
2051 int leftmost
, rightmost
, lowest
, highest
;
2052 int i
, width
, ascent
, descent
;
2054 cmp
->font
= (void *) font
;
2056 /* Initialize the bounding box. */
2057 pcm
= x_per_char_metric (font
, &char2b
);
2061 ascent
= pcm
->ascent
;
2062 descent
= pcm
->descent
;
2066 width
= FONT_WIDTH (font
);
2067 ascent
= font
->ascent
;
2068 descent
= font
->descent
;
2072 lowest
= - descent
+ boff
;
2073 highest
= ascent
+ boff
;
2077 && font_info
->default_ascent
2078 && CHAR_TABLE_P (Vuse_default_ascent
)
2079 && !NILP (Faref (Vuse_default_ascent
,
2080 make_number (it
->char_to_display
))))
2081 highest
= font_info
->default_ascent
+ boff
;
2083 /* Draw the first glyph at the normal position. It may be
2084 shifted to right later if some other glyphs are drawn at
2086 cmp
->offsets
[0] = 0;
2087 cmp
->offsets
[1] = boff
;
2089 /* Set cmp->offsets for the remaining glyphs. */
2090 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2092 int left
, right
, btm
, top
;
2093 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2094 int face_id
= FACE_FOR_CHAR (it
->f
, face
, ch
);
2096 face
= FACE_FROM_ID (it
->f
, face_id
);
2097 x_get_char_face_and_encoding (it
->f
, ch
, face
->id
, &char2b
,
2102 font
= FRAME_FONT (it
->f
);
2103 boff
= it
->f
->output_data
.x
->baseline_offset
;
2109 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2110 boff
= font_info
->baseline_offset
;
2111 if (font_info
->vertical_centering
)
2112 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2115 pcm
= x_per_char_metric (font
, &char2b
);
2119 ascent
= pcm
->ascent
;
2120 descent
= pcm
->descent
;
2124 width
= FONT_WIDTH (font
);
2125 ascent
= font
->ascent
;
2126 descent
= font
->descent
;
2129 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2131 /* Relative composition with or without
2133 left
= (leftmost
+ rightmost
- width
) / 2;
2134 btm
= - descent
+ boff
;
2135 if (font_info
&& font_info
->relative_compose
2136 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2137 || NILP (Faref (Vignore_relative_composition
,
2138 make_number (ch
)))))
2141 if (- descent
>= font_info
->relative_compose
)
2142 /* One extra pixel between two glyphs. */
2144 else if (ascent
<= 0)
2145 /* One extra pixel between two glyphs. */
2146 btm
= lowest
- 1 - ascent
- descent
;
2151 /* A composition rule is specified by an integer
2152 value that encodes global and new reference
2153 points (GREF and NREF). GREF and NREF are
2154 specified by numbers as below:
2162 ---3---4---5--- baseline
2164 6---7---8 -- descent
2166 int rule
= COMPOSITION_RULE (cmp
, i
);
2167 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2169 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2170 grefx
= gref
% 3, nrefx
= nref
% 3;
2171 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2174 + grefx
* (rightmost
- leftmost
) / 2
2175 - nrefx
* width
/ 2);
2176 btm
= ((grefy
== 0 ? highest
2178 : grefy
== 2 ? lowest
2179 : (highest
+ lowest
) / 2)
2180 - (nrefy
== 0 ? ascent
+ descent
2181 : nrefy
== 1 ? descent
- boff
2183 : (ascent
+ descent
) / 2));
2186 cmp
->offsets
[i
* 2] = left
;
2187 cmp
->offsets
[i
* 2 + 1] = btm
+ descent
;
2189 /* Update the bounding box of the overall glyphs. */
2190 right
= left
+ width
;
2191 top
= btm
+ descent
+ ascent
;
2192 if (left
< leftmost
)
2194 if (right
> rightmost
)
2202 /* If there are glyphs whose x-offsets are negative,
2203 shift all glyphs to the right and make all x-offsets
2207 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2208 cmp
->offsets
[i
* 2] -= leftmost
;
2209 rightmost
-= leftmost
;
2212 cmp
->pixel_width
= rightmost
;
2213 cmp
->ascent
= highest
;
2214 cmp
->descent
= - lowest
;
2215 if (cmp
->ascent
< font_ascent
)
2216 cmp
->ascent
= font_ascent
;
2217 if (cmp
->descent
< font_descent
)
2218 cmp
->descent
= font_descent
;
2221 it
->pixel_width
= cmp
->pixel_width
;
2222 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2223 it
->descent
= it
->phys_descent
= cmp
->descent
;
2225 if (face
->box
!= FACE_NO_BOX
)
2227 int thick
= face
->box_line_width
;
2228 it
->ascent
+= thick
;
2229 it
->descent
+= thick
;
2231 if (it
->start_of_box_run_p
)
2232 it
->pixel_width
+= thick
;
2233 if (it
->end_of_box_run_p
)
2234 it
->pixel_width
+= thick
;
2237 /* If face has an overline, add the height of the overline
2238 (1 pixel) and a 1 pixel margin to the character height. */
2239 if (face
->overline_p
)
2242 take_vertical_position_into_account (it
);
2245 x_append_composite_glyph (it
);
2247 else if (it
->what
== IT_IMAGE
)
2248 x_produce_image_glyph (it
);
2249 else if (it
->what
== IT_STRETCH
)
2250 x_produce_stretch_glyph (it
);
2252 /* Accumulate dimensions. */
2253 xassert (it
->ascent
>= 0 && it
->descent
> 0);
2254 if (it
->area
== TEXT_AREA
)
2255 it
->current_x
+= it
->pixel_width
;
2257 it
->descent
+= it
->extra_line_spacing
;
2259 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2260 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2261 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2262 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
2266 /* Estimate the pixel height of the mode or top line on frame F.
2267 FACE_ID specifies what line's height to estimate. */
2270 x_estimate_mode_line_height (f
, face_id
)
2272 enum face_id face_id
;
2276 /* This function is called so early when Emacs starts that the face
2277 cache and mode line face are not yet initialized. */
2278 if (FRAME_FACE_CACHE (f
))
2280 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2282 height
= FONT_HEIGHT (face
->font
) + 2 * face
->box_line_width
;
2289 /***********************************************************************
2291 ***********************************************************************/
2293 /* A sequence of glyphs to be drawn in the same face.
2295 This data structure is not really completely X specific, so it
2296 could possibly, at least partially, be useful for other systems. It
2297 is currently not part of the external redisplay interface because
2298 it's not clear what other systems will need. */
2302 /* X-origin of the string. */
2305 /* Y-origin and y-position of the base line of this string. */
2308 /* The width of the string, not including a face extension. */
2311 /* The width of the string, including a face extension. */
2312 int background_width
;
2314 /* The height of this string. This is the height of the line this
2315 string is drawn in, and can be different from the height of the
2316 font the string is drawn in. */
2319 /* Number of pixels this string overwrites in front of its x-origin.
2320 This number is zero if the string has an lbearing >= 0; it is
2321 -lbearing, if the string has an lbearing < 0. */
2324 /* Number of pixels this string overwrites past its right-most
2325 nominal x-position, i.e. x + width. Zero if the string's
2326 rbearing is <= its nominal width, rbearing - width otherwise. */
2329 /* The frame on which the glyph string is drawn. */
2332 /* The window on which the glyph string is drawn. */
2335 /* X display and window for convenience. */
2339 /* The glyph row for which this string was built. It determines the
2340 y-origin and height of the string. */
2341 struct glyph_row
*row
;
2343 /* The area within row. */
2344 enum glyph_row_area area
;
2346 /* Characters to be drawn, and number of characters. */
2350 /* A face-override for drawing cursors, mouse face and similar. */
2351 enum draw_glyphs_face hl
;
2353 /* Face in which this string is to be drawn. */
2356 /* Font in which this string is to be drawn. */
2359 /* Font info for this string. */
2360 struct font_info
*font_info
;
2362 /* Non-null means this string describes (part of) a composition.
2363 All characters from char2b are drawn composed. */
2364 struct composition
*cmp
;
2366 /* Index of this glyph string's first character in the glyph
2367 definition of CMP. If this is zero, this glyph string describes
2368 the first character of a composition. */
2371 /* 1 means this glyph strings face has to be drawn to the right end
2372 of the window's drawing area. */
2373 unsigned extends_to_end_of_line_p
: 1;
2375 /* 1 means the background of this string has been drawn. */
2376 unsigned background_filled_p
: 1;
2378 /* 1 means glyph string must be drawn with 16-bit functions. */
2379 unsigned two_byte_p
: 1;
2381 /* 1 means that the original font determined for drawing this glyph
2382 string could not be loaded. The member `font' has been set to
2383 the frame's default font in this case. */
2384 unsigned font_not_found_p
: 1;
2386 /* 1 means that the face in which this glyph string is drawn has a
2388 unsigned stippled_p
: 1;
2390 /* 1 means only the foreground of this glyph string must be drawn,
2391 and we should use the physical height of the line this glyph
2392 string appears in as clip rect. */
2393 unsigned for_overlaps_p
: 1;
2395 /* The GC to use for drawing this glyph string. */
2398 /* A pointer to the first glyph in the string. This glyph
2399 corresponds to char2b[0]. Needed to draw rectangles if
2400 font_not_found_p is 1. */
2401 struct glyph
*first_glyph
;
2403 /* Image, if any. */
2406 struct glyph_string
*next
, *prev
;
2413 x_dump_glyph_string (s
)
2414 struct glyph_string
*s
;
2416 fprintf (stderr
, "glyph string\n");
2417 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2418 s
->x
, s
->y
, s
->width
, s
->height
);
2419 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2420 fprintf (stderr
, " hl = %d\n", s
->hl
);
2421 fprintf (stderr
, " left overhang = %d, right = %d\n",
2422 s
->left_overhang
, s
->right_overhang
);
2423 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2424 fprintf (stderr
, " extends to end of line = %d\n",
2425 s
->extends_to_end_of_line_p
);
2426 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2427 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2430 #endif /* GLYPH_DEBUG */
2434 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2435 struct glyph_string
**,
2436 struct glyph_string
*,
2437 struct glyph_string
*));
2438 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2439 struct glyph_string
**,
2440 struct glyph_string
*,
2441 struct glyph_string
*));
2442 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2443 struct glyph_string
**,
2444 struct glyph_string
*));
2445 static int x_left_overwritten
P_ ((struct glyph_string
*));
2446 static int x_left_overwriting
P_ ((struct glyph_string
*));
2447 static int x_right_overwritten
P_ ((struct glyph_string
*));
2448 static int x_right_overwriting
P_ ((struct glyph_string
*));
2449 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2451 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2452 XChar2b
*, struct window
*,
2454 enum glyph_row_area
, int,
2455 enum draw_glyphs_face
));
2456 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2457 enum glyph_row_area
, int, int,
2458 enum draw_glyphs_face
, int *, int *, int));
2459 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2460 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2461 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2463 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2464 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2465 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2466 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2467 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2468 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2469 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2470 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2471 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2473 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2474 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2475 unsigned long *, double, int));
2476 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2477 double, int, unsigned long));
2478 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2479 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2480 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2481 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2482 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2483 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2484 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2486 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2487 int, int, int, int, XRectangle
*));
2488 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2489 int, int, int, XRectangle
*));
2490 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2491 enum glyph_row_area
));
2494 /* Append the list of glyph strings with head H and tail T to the list
2495 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2498 x_append_glyph_string_lists (head
, tail
, h
, t
)
2499 struct glyph_string
**head
, **tail
;
2500 struct glyph_string
*h
, *t
;
2514 /* Prepend the list of glyph strings with head H and tail T to the
2515 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2519 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2520 struct glyph_string
**head
, **tail
;
2521 struct glyph_string
*h
, *t
;
2535 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2536 Set *HEAD and *TAIL to the resulting list. */
2539 x_append_glyph_string (head
, tail
, s
)
2540 struct glyph_string
**head
, **tail
;
2541 struct glyph_string
*s
;
2543 s
->next
= s
->prev
= NULL
;
2544 x_append_glyph_string_lists (head
, tail
, s
, s
);
2548 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2553 struct glyph_string
*s
;
2555 if (s
->font
== FRAME_FONT (s
->f
)
2556 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2557 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2559 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2562 /* Cursor on non-default face: must merge. */
2566 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2567 xgcv
.foreground
= s
->face
->background
;
2569 /* If the glyph would be invisible, try a different foreground. */
2570 if (xgcv
.foreground
== xgcv
.background
)
2571 xgcv
.foreground
= s
->face
->foreground
;
2572 if (xgcv
.foreground
== xgcv
.background
)
2573 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2574 if (xgcv
.foreground
== xgcv
.background
)
2575 xgcv
.foreground
= s
->face
->foreground
;
2577 /* Make sure the cursor is distinct from text in this face. */
2578 if (xgcv
.background
== s
->face
->background
2579 && xgcv
.foreground
== s
->face
->foreground
)
2581 xgcv
.background
= s
->face
->foreground
;
2582 xgcv
.foreground
= s
->face
->background
;
2585 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2586 xgcv
.font
= s
->font
->fid
;
2587 xgcv
.graphics_exposures
= False
;
2588 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2590 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2591 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2594 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2595 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2597 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2602 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2605 x_set_mouse_face_gc (s
)
2606 struct glyph_string
*s
;
2611 /* What face has to be used for the mouse face? */
2612 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2613 face
= FACE_FROM_ID (s
->f
, face_id
);
2614 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2615 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2616 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2618 /* If font in this face is same as S->font, use it. */
2619 if (s
->font
== s
->face
->font
)
2620 s
->gc
= s
->face
->gc
;
2623 /* Otherwise construct scratch_cursor_gc with values from FACE
2628 xgcv
.background
= s
->face
->background
;
2629 xgcv
.foreground
= s
->face
->foreground
;
2630 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2631 xgcv
.font
= s
->font
->fid
;
2632 xgcv
.graphics_exposures
= False
;
2633 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2635 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2636 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2639 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2640 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2642 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2645 xassert (s
->gc
!= 0);
2649 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2650 Faces to use in the mode line have already been computed when the
2651 matrix was built, so there isn't much to do, here. */
2654 x_set_mode_line_face_gc (s
)
2655 struct glyph_string
*s
;
2657 s
->gc
= s
->face
->gc
;
2658 xassert (s
->gc
!= 0);
2662 /* Set S->gc of glyph string S for drawing that glyph string. Set
2663 S->stippled_p to a non-zero value if the face of S has a stipple
2667 x_set_glyph_string_gc (s
)
2668 struct glyph_string
*s
;
2670 if (s
->hl
== DRAW_NORMAL_TEXT
)
2672 s
->gc
= s
->face
->gc
;
2673 s
->stippled_p
= s
->face
->stipple
!= 0;
2675 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2677 x_set_mode_line_face_gc (s
);
2678 s
->stippled_p
= s
->face
->stipple
!= 0;
2680 else if (s
->hl
== DRAW_CURSOR
)
2682 x_set_cursor_gc (s
);
2685 else if (s
->hl
== DRAW_MOUSE_FACE
)
2687 x_set_mouse_face_gc (s
);
2688 s
->stippled_p
= s
->face
->stipple
!= 0;
2690 else if (s
->hl
== DRAW_IMAGE_RAISED
2691 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2693 s
->gc
= s
->face
->gc
;
2694 s
->stippled_p
= s
->face
->stipple
!= 0;
2698 s
->gc
= s
->face
->gc
;
2699 s
->stippled_p
= s
->face
->stipple
!= 0;
2702 /* GC must have been set. */
2703 xassert (s
->gc
!= 0);
2707 /* Return in *R the clipping rectangle for glyph string S. */
2710 x_get_glyph_string_clip_rect (s
, r
)
2711 struct glyph_string
*s
;
2714 if (s
->row
->full_width_p
)
2716 /* Draw full-width. X coordinates are relative to S->w->left. */
2717 int canon_x
= CANON_X_UNIT (s
->f
);
2719 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2720 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2722 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2724 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2725 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2729 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2731 /* Unless displaying a mode or menu bar line, which are always
2732 fully visible, clip to the visible part of the row. */
2733 if (s
->w
->pseudo_window_p
)
2734 r
->height
= s
->row
->visible_height
;
2736 r
->height
= s
->height
;
2740 /* This is a text line that may be partially visible. */
2741 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2742 r
->width
= window_box_width (s
->w
, s
->area
);
2743 r
->height
= s
->row
->visible_height
;
2746 /* Don't use S->y for clipping because it doesn't take partially
2747 visible lines into account. For example, it can be negative for
2748 partially visible lines at the top of a window. */
2749 if (!s
->row
->full_width_p
2750 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2751 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2753 r
->y
= max (0, s
->row
->y
);
2755 /* If drawing a tool-bar window, draw it over the internal border
2756 at the top of the window. */
2757 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2758 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2760 /* If S draws overlapping rows, it's sufficient to use the top and
2761 bottom of the window for clipping because this glyph string
2762 intentionally draws over other lines. */
2763 if (s
->for_overlaps_p
)
2765 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2766 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2769 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2773 /* Set clipping for output of glyph string S. S may be part of a mode
2774 line or menu if we don't have X toolkit support. */
2777 x_set_glyph_string_clipping (s
)
2778 struct glyph_string
*s
;
2781 x_get_glyph_string_clip_rect (s
, &r
);
2782 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2786 /* Compute left and right overhang of glyph string S. If S is a glyph
2787 string for a composition, assume overhangs don't exist. */
2790 x_compute_glyph_string_overhangs (s
)
2791 struct glyph_string
*s
;
2794 && s
->first_glyph
->type
== CHAR_GLYPH
)
2797 int direction
, font_ascent
, font_descent
;
2798 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2799 &font_ascent
, &font_descent
, &cs
);
2800 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2801 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2806 /* Compute overhangs and x-positions for glyph string S and its
2807 predecessors, or successors. X is the starting x-position for S.
2808 BACKWARD_P non-zero means process predecessors. */
2811 x_compute_overhangs_and_x (s
, x
, backward_p
)
2812 struct glyph_string
*s
;
2820 x_compute_glyph_string_overhangs (s
);
2830 x_compute_glyph_string_overhangs (s
);
2839 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2840 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2841 assumed to be zero. */
2844 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2845 struct glyph
*glyph
;
2853 if (glyph
->type
== CHAR_GLYPH
)
2857 struct font_info
*font_info
;
2861 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
, NULL
);
2863 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2865 && (pcm
= x_per_char_metric (font
, &char2b
)))
2867 if (pcm
->rbearing
> pcm
->width
)
2868 *right
= pcm
->rbearing
- pcm
->width
;
2869 if (pcm
->lbearing
< 0)
2870 *left
= -pcm
->lbearing
;
2876 /* Return the index of the first glyph preceding glyph string S that
2877 is overwritten by S because of S's left overhang. Value is -1
2878 if no glyphs are overwritten. */
2881 x_left_overwritten (s
)
2882 struct glyph_string
*s
;
2886 if (s
->left_overhang
)
2889 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2890 int first
= s
->first_glyph
- glyphs
;
2892 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2893 x
-= glyphs
[i
].pixel_width
;
2904 /* Return the index of the first glyph preceding glyph string S that
2905 is overwriting S because of its right overhang. Value is -1 if no
2906 glyph in front of S overwrites S. */
2909 x_left_overwriting (s
)
2910 struct glyph_string
*s
;
2913 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2914 int first
= s
->first_glyph
- glyphs
;
2918 for (i
= first
- 1; i
>= 0; --i
)
2921 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2924 x
-= glyphs
[i
].pixel_width
;
2931 /* Return the index of the last glyph following glyph string S that is
2932 not overwritten by S because of S's right overhang. Value is -1 if
2933 no such glyph is found. */
2936 x_right_overwritten (s
)
2937 struct glyph_string
*s
;
2941 if (s
->right_overhang
)
2944 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2945 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
2946 int end
= s
->row
->used
[s
->area
];
2948 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
2949 x
+= glyphs
[i
].pixel_width
;
2958 /* Return the index of the last glyph following glyph string S that
2959 overwrites S because of its left overhang. Value is negative
2960 if no such glyph is found. */
2963 x_right_overwriting (s
)
2964 struct glyph_string
*s
;
2967 int end
= s
->row
->used
[s
->area
];
2968 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2969 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
2973 for (i
= first
; i
< end
; ++i
)
2976 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2979 x
+= glyphs
[i
].pixel_width
;
2986 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2989 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2990 struct glyph_string
*s
;
2994 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
2995 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2996 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2997 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3001 /* Draw the background of glyph_string S. If S->background_filled_p
3002 is non-zero don't draw it. FORCE_P non-zero means draw the
3003 background even if it wouldn't be drawn normally. This is used
3004 when a string preceding S draws into the background of S, or S
3005 contains the first component of a composition. */
3008 x_draw_glyph_string_background (s
, force_p
)
3009 struct glyph_string
*s
;
3012 /* Nothing to do if background has already been drawn or if it
3013 shouldn't be drawn in the first place. */
3014 if (!s
->background_filled_p
)
3018 /* Fill background with a stipple pattern. */
3019 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3020 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
3021 s
->y
+ s
->face
->box_line_width
,
3022 s
->background_width
,
3023 s
->height
- 2 * s
->face
->box_line_width
);
3024 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3025 s
->background_filled_p
= 1;
3027 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * s
->face
->box_line_width
3028 || s
->font_not_found_p
3029 || s
->extends_to_end_of_line_p
3032 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ s
->face
->box_line_width
,
3033 s
->background_width
,
3034 s
->height
- 2 * s
->face
->box_line_width
);
3035 s
->background_filled_p
= 1;
3041 /* Draw the foreground of glyph string S. */
3044 x_draw_glyph_string_foreground (s
)
3045 struct glyph_string
*s
;
3049 /* If first glyph of S has a left box line, start drawing the text
3050 of S to the right of that box line. */
3051 if (s
->face
->box
!= FACE_NO_BOX
3052 && s
->first_glyph
->left_box_line_p
)
3053 x
= s
->x
+ s
->face
->box_line_width
;
3057 /* Draw characters of S as rectangles if S's font could not be
3059 if (s
->font_not_found_p
)
3061 for (i
= 0; i
< s
->nchars
; ++i
)
3063 struct glyph
*g
= s
->first_glyph
+ i
;
3064 XDrawRectangle (s
->display
, s
->window
,
3065 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3067 x
+= g
->pixel_width
;
3072 char *char1b
= (char *) s
->char2b
;
3073 int boff
= s
->font_info
->baseline_offset
;
3075 if (s
->font_info
->vertical_centering
)
3076 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3078 /* If we can use 8-bit functions, condense S->char2b. */
3080 for (i
= 0; i
< s
->nchars
; ++i
)
3081 char1b
[i
] = s
->char2b
[i
].byte2
;
3083 /* Draw text with XDrawString if background has already been
3084 filled. Otherwise, use XDrawImageString. (Note that
3085 XDrawImageString is usually faster than XDrawString.) Always
3086 use XDrawImageString when drawing the cursor so that there is
3087 no chance that characters under a box cursor are invisible. */
3088 if (s
->for_overlaps_p
3089 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3091 /* Draw characters with 16-bit or 8-bit functions. */
3093 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3094 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3096 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3097 s
->ybase
- boff
, char1b
, s
->nchars
);
3102 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3103 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3105 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3106 s
->ybase
- boff
, char1b
, s
->nchars
);
3111 /* Draw the foreground of composite glyph string S. */
3114 x_draw_composite_glyph_string_foreground (s
)
3115 struct glyph_string
*s
;
3119 /* If first glyph of S has a left box line, start drawing the text
3120 of S to the right of that box line. */
3121 if (s
->face
->box
!= FACE_NO_BOX
3122 && s
->first_glyph
->left_box_line_p
)
3123 x
= s
->x
+ s
->face
->box_line_width
;
3127 /* S is a glyph string for a composition. S->gidx is the index of
3128 the first character drawn for glyphs of this composition.
3129 S->gidx == 0 means we are drawing the very first character of
3130 this composition. */
3132 /* Draw a rectangle for the composition if the font for the very
3133 first character of the composition could not be loaded. */
3134 if (s
->font_not_found_p
)
3137 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3138 s
->width
- 1, s
->height
- 1);
3142 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3143 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3144 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3145 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3151 #ifdef USE_X_TOOLKIT
3153 /* Allocate the color COLOR->pixel on the screen and display of
3154 widget WIDGET in colormap CMAP. If an exact match cannot be
3155 allocated, try the nearest color available. Value is non-zero
3156 if successful. This is called from lwlib. */
3159 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3165 struct x_display_info
*dpyinfo
;
3168 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3170 /* Find the top-level shell of the widget. Note that this function
3171 can be called when the widget is not yet realized, so XtWindow
3172 (widget) == 0. That's the reason we can't simply use
3173 x_any_window_to_frame. */
3174 while (!XtIsTopLevelShell (widget
))
3175 widget
= XtParent (widget
);
3177 /* Look for a frame with that top-level widget. Allocate the color
3178 on that frame to get the right gamma correction value. */
3179 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3180 if (GC_FRAMEP (XCAR (tail
))
3181 && (f
= XFRAME (XCAR (tail
)),
3182 (f
->output_data
.nothing
!= 1
3183 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3184 && f
->output_data
.x
->widget
== widget
)
3185 return x_alloc_nearest_color (f
, cmap
, color
);
3190 #endif /* USE_X_TOOLKIT */
3193 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3194 CMAP. If an exact match can't be allocated, try the nearest color
3195 available. Value is non-zero if successful. Set *COLOR to the
3199 x_alloc_nearest_color (f
, cmap
, color
)
3204 Display
*display
= FRAME_X_DISPLAY (f
);
3205 Screen
*screen
= FRAME_X_SCREEN (f
);
3208 gamma_correct (f
, color
);
3209 rc
= XAllocColor (display
, cmap
, color
);
3212 /* If we got to this point, the colormap is full, so we're going
3213 to try to get the next closest color. The algorithm used is
3214 a least-squares matching, which is what X uses for closest
3215 color matching with StaticColor visuals. */
3217 unsigned long nearest_delta
= ~0;
3218 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3219 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3221 for (i
= 0; i
< ncells
; ++i
)
3223 XQueryColors (display
, cmap
, cells
, ncells
);
3225 for (nearest
= i
= 0; i
< ncells
; ++i
)
3227 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3228 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3229 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3230 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3232 if (delta
< nearest_delta
)
3235 nearest_delta
= delta
;
3239 color
->red
= cells
[nearest
].red
;
3240 color
->green
= cells
[nearest
].green
;
3241 color
->blue
= cells
[nearest
].blue
;
3242 rc
= XAllocColor (display
, cmap
, color
);
3245 #ifdef DEBUG_X_COLORS
3247 register_color (color
->pixel
);
3248 #endif /* DEBUG_X_COLORS */
3254 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3255 It's necessary to do this instead of just using PIXEL directly to
3256 get color reference counts right. */
3259 x_copy_color (f
, pixel
)
3261 unsigned long pixel
;
3265 color
.pixel
= pixel
;
3267 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3268 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
3270 #ifdef DEBUG_X_COLORS
3271 register_color (pixel
);
3277 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3278 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3279 If this produces the same color as PIXEL, try a color where all RGB
3280 values have DELTA added. Return the allocated color in *PIXEL.
3281 DISPLAY is the X display, CMAP is the colormap to operate on.
3282 Value is non-zero if successful. */
3285 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3289 unsigned long *pixel
;
3296 /* Get RGB color values. */
3297 color
.pixel
= *pixel
;
3298 XQueryColor (display
, cmap
, &color
);
3300 /* Change RGB values by specified FACTOR. Avoid overflow! */
3301 xassert (factor
>= 0);
3302 new.red
= min (0xffff, factor
* color
.red
);
3303 new.green
= min (0xffff, factor
* color
.green
);
3304 new.blue
= min (0xffff, factor
* color
.blue
);
3306 /* Try to allocate the color. */
3307 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3310 if (new.pixel
== *pixel
)
3312 /* If we end up with the same color as before, try adding
3313 delta to the RGB values. */
3314 x_free_colors (f
, &new.pixel
, 1);
3316 new.red
= min (0xffff, delta
+ color
.red
);
3317 new.green
= min (0xffff, delta
+ color
.green
);
3318 new.blue
= min (0xffff, delta
+ color
.blue
);
3319 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3330 /* Set up the foreground color for drawing relief lines of glyph
3331 string S. RELIEF is a pointer to a struct relief containing the GC
3332 with which lines will be drawn. Use a color that is FACTOR or
3333 DELTA lighter or darker than the relief's background which is found
3334 in S->f->output_data.x->relief_background. If such a color cannot
3335 be allocated, use DEFAULT_PIXEL, instead. */
3338 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3340 struct relief
*relief
;
3343 unsigned long default_pixel
;
3346 struct x_output
*di
= f
->output_data
.x
;
3347 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3348 unsigned long pixel
;
3349 unsigned long background
= di
->relief_background
;
3350 Colormap cmap
= FRAME_X_COLORMAP (f
);
3351 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3352 Display
*dpy
= FRAME_X_DISPLAY (f
);
3354 xgcv
.graphics_exposures
= False
;
3355 xgcv
.line_width
= 1;
3357 /* Free previously allocated color. The color cell will be reused
3358 when it has been freed as many times as it was allocated, so this
3359 doesn't affect faces using the same colors. */
3361 && relief
->allocated_p
)
3363 /* If display has an immutable color map, freeing colors is not
3364 necessary and some servers don't allow it. So don't do it. */
3365 x_free_colors (f
, &relief
->pixel
, 1);
3366 relief
->allocated_p
= 0;
3369 /* Allocate new color. */
3370 xgcv
.foreground
= default_pixel
;
3372 if (dpyinfo
->n_planes
!= 1
3373 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3375 relief
->allocated_p
= 1;
3376 xgcv
.foreground
= relief
->pixel
= pixel
;
3379 if (relief
->gc
== 0)
3381 xgcv
.stipple
= dpyinfo
->gray
;
3383 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3386 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3390 /* Set up colors for the relief lines around glyph string S. */
3393 x_setup_relief_colors (s
)
3394 struct glyph_string
*s
;
3396 struct x_output
*di
= s
->f
->output_data
.x
;
3397 unsigned long color
;
3399 if (s
->face
->use_box_color_for_shadows_p
)
3400 color
= s
->face
->box_color
;
3405 /* Get the background color of the face. */
3406 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3407 color
= xgcv
.background
;
3410 if (di
->white_relief
.gc
== 0
3411 || color
!= di
->relief_background
)
3413 di
->relief_background
= color
;
3414 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3415 WHITE_PIX_DEFAULT (s
->f
));
3416 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3417 BLACK_PIX_DEFAULT (s
->f
));
3422 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3423 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3424 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3425 relief. LEFT_P non-zero means draw a relief on the left side of
3426 the rectangle. RIGHT_P non-zero means draw a relief on the right
3427 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3431 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3432 raised_p
, left_p
, right_p
, clip_rect
)
3434 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3435 XRectangle
*clip_rect
;
3441 gc
= f
->output_data
.x
->white_relief
.gc
;
3443 gc
= f
->output_data
.x
->black_relief
.gc
;
3444 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3447 for (i
= 0; i
< width
; ++i
)
3448 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3449 left_x
+ i
* left_p
, top_y
+ i
,
3450 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3454 for (i
= 0; i
< width
; ++i
)
3455 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3456 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3458 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3460 gc
= f
->output_data
.x
->black_relief
.gc
;
3462 gc
= f
->output_data
.x
->white_relief
.gc
;
3463 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3466 for (i
= 0; i
< width
; ++i
)
3467 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3468 left_x
+ i
* left_p
, bottom_y
- i
,
3469 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3473 for (i
= 0; i
< width
; ++i
)
3474 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3475 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3477 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3481 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3482 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3483 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3484 left side of the rectangle. RIGHT_P non-zero means draw a line
3485 on the right side of the rectangle. CLIP_RECT is the clipping
3486 rectangle to use when drawing. */
3489 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3490 left_p
, right_p
, clip_rect
)
3491 struct glyph_string
*s
;
3492 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3493 XRectangle
*clip_rect
;
3497 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3498 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3499 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3502 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3503 left_x
, top_y
, right_x
- left_x
, width
);
3507 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3508 left_x
, top_y
, width
, bottom_y
- top_y
);
3511 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3512 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
3516 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3517 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
3519 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3520 XSetClipMask (s
->display
, s
->gc
, None
);
3524 /* Draw a box around glyph string S. */
3527 x_draw_glyph_string_box (s
)
3528 struct glyph_string
*s
;
3530 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3531 int left_p
, right_p
;
3532 struct glyph
*last_glyph
;
3533 XRectangle clip_rect
;
3535 last_x
= window_box_right (s
->w
, s
->area
);
3536 if (s
->row
->full_width_p
3537 && !s
->w
->pseudo_window_p
)
3539 last_x
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s
->f
);
3540 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3541 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3544 /* The glyph that may have a right box line. */
3545 last_glyph
= (s
->cmp
|| s
->img
3547 : s
->first_glyph
+ s
->nchars
- 1);
3549 width
= s
->face
->box_line_width
;
3550 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3552 right_x
= ((s
->row
->full_width_p
3554 : min (last_x
, s
->x
+ s
->background_width
) - 1));
3556 bottom_y
= top_y
+ s
->height
- 1;
3558 left_p
= (s
->first_glyph
->left_box_line_p
3559 || (s
->hl
== DRAW_MOUSE_FACE
3561 || s
->prev
->hl
!= s
->hl
)));
3562 right_p
= (last_glyph
->right_box_line_p
3563 || (s
->hl
== DRAW_MOUSE_FACE
3565 || s
->next
->hl
!= s
->hl
)));
3567 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3569 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3570 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3571 left_p
, right_p
, &clip_rect
);
3574 x_setup_relief_colors (s
);
3575 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3576 width
, raised_p
, left_p
, right_p
, &clip_rect
);
3581 /* Draw foreground of image glyph string S. */
3584 x_draw_image_foreground (s
)
3585 struct glyph_string
*s
;
3588 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
3590 /* If first glyph of S has a left box line, start drawing it to the
3591 right of that line. */
3592 if (s
->face
->box
!= FACE_NO_BOX
3593 && s
->first_glyph
->left_box_line_p
)
3594 x
= s
->x
+ s
->face
->box_line_width
;
3598 /* If there is a margin around the image, adjust x- and y-position
3602 x
+= s
->img
->margin
;
3603 y
+= s
->img
->margin
;
3610 /* We can't set both a clip mask and use XSetClipRectangles
3611 because the latter also sets a clip mask. We also can't
3612 trust on the shape extension to be available
3613 (XShapeCombineRegion). So, compute the rectangle to draw
3615 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3618 XRectangle clip_rect
, image_rect
, r
;
3620 xgcv
.clip_mask
= s
->img
->mask
;
3621 xgcv
.clip_x_origin
= x
;
3622 xgcv
.clip_y_origin
= y
;
3623 xgcv
.function
= GXcopy
;
3624 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3626 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3629 image_rect
.width
= s
->img
->width
;
3630 image_rect
.height
= s
->img
->height
;
3631 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3632 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3633 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3637 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3638 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3640 /* When the image has a mask, we can expect that at
3641 least part of a mouse highlight or a block cursor will
3642 be visible. If the image doesn't have a mask, make
3643 a block cursor visible by drawing a rectangle around
3644 the image. I believe it's looking better if we do
3645 nothing here for mouse-face. */
3646 if (s
->hl
== DRAW_CURSOR
)
3647 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3648 s
->img
->width
- 1, s
->img
->height
- 1);
3652 /* Draw a rectangle if image could not be loaded. */
3653 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3654 s
->img
->width
- 1, s
->img
->height
- 1);
3658 /* Draw a relief around the image glyph string S. */
3661 x_draw_image_relief (s
)
3662 struct glyph_string
*s
;
3664 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3667 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
);
3669 /* If first glyph of S has a left box line, start drawing it to the
3670 right of that line. */
3671 if (s
->face
->box
!= FACE_NO_BOX
3672 && s
->first_glyph
->left_box_line_p
)
3673 x
= s
->x
+ s
->face
->box_line_width
;
3677 /* If there is a margin around the image, adjust x- and y-position
3681 x
+= s
->img
->margin
;
3682 y
+= s
->img
->margin
;
3685 if (s
->hl
== DRAW_IMAGE_SUNKEN
3686 || s
->hl
== DRAW_IMAGE_RAISED
)
3688 thick
= tool_bar_button_relief
> 0 ? tool_bar_button_relief
: 3;
3689 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3693 thick
= abs (s
->img
->relief
);
3694 raised_p
= s
->img
->relief
> 0;
3699 x1
= x
+ s
->img
->width
+ thick
- 1;
3700 y1
= y
+ s
->img
->height
+ thick
- 1;
3702 x_setup_relief_colors (s
);
3703 x_get_glyph_string_clip_rect (s
, &r
);
3704 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
3708 /* Draw the foreground of image glyph string S to PIXMAP. */
3711 x_draw_image_foreground_1 (s
, pixmap
)
3712 struct glyph_string
*s
;
3716 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
);
3718 /* If first glyph of S has a left box line, start drawing it to the
3719 right of that line. */
3720 if (s
->face
->box
!= FACE_NO_BOX
3721 && s
->first_glyph
->left_box_line_p
)
3722 x
= s
->face
->box_line_width
;
3726 /* If there is a margin around the image, adjust x- and y-position
3730 x
+= s
->img
->margin
;
3731 y
+= s
->img
->margin
;
3738 /* We can't set both a clip mask and use XSetClipRectangles
3739 because the latter also sets a clip mask. We also can't
3740 trust on the shape extension to be available
3741 (XShapeCombineRegion). So, compute the rectangle to draw
3743 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3747 xgcv
.clip_mask
= s
->img
->mask
;
3748 xgcv
.clip_x_origin
= x
;
3749 xgcv
.clip_y_origin
= y
;
3750 xgcv
.function
= GXcopy
;
3751 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3753 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3754 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3755 XSetClipMask (s
->display
, s
->gc
, None
);
3759 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3760 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3762 /* When the image has a mask, we can expect that at
3763 least part of a mouse highlight or a block cursor will
3764 be visible. If the image doesn't have a mask, make
3765 a block cursor visible by drawing a rectangle around
3766 the image. I believe it's looking better if we do
3767 nothing here for mouse-face. */
3768 if (s
->hl
== DRAW_CURSOR
)
3769 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3770 s
->img
->width
- 1, s
->img
->height
- 1);
3774 /* Draw a rectangle if image could not be loaded. */
3775 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3776 s
->img
->width
- 1, s
->img
->height
- 1);
3780 /* Draw part of the background of glyph string S. X, Y, W, and H
3781 give the rectangle to draw. */
3784 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3785 struct glyph_string
*s
;
3790 /* Fill background with a stipple pattern. */
3791 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3792 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3793 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3796 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3800 /* Draw image glyph string S.
3803 s->x +-------------------------
3806 | +-------------------------
3809 | | +-------------------
3815 x_draw_image_glyph_string (s
)
3816 struct glyph_string
*s
;
3819 int box_line_width
= s
->face
->box_line_width
;
3820 int margin
= s
->img
->margin
;
3822 Pixmap pixmap
= None
;
3824 height
= s
->height
- 2 * box_line_width
;
3826 /* Fill background with face under the image. Do it only if row is
3827 taller than image or if image has a clip mask to reduce
3829 s
->stippled_p
= s
->face
->stipple
!= 0;
3830 if (height
> s
->img
->height
3833 || s
->img
->pixmap
== 0
3834 || s
->width
!= s
->background_width
)
3836 if (box_line_width
&& s
->first_glyph
->left_box_line_p
)
3837 x
= s
->x
+ box_line_width
;
3841 y
= s
->y
+ box_line_width
;
3845 /* Create a pixmap as large as the glyph string Fill it with
3846 the background color. Copy the image to it, using its
3847 mask. Copy the temporary pixmap to the display. */
3848 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
3849 int depth
= DefaultDepthOfScreen (screen
);
3851 /* Create a pixmap as large as the glyph string. */
3852 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3853 s
->background_width
,
3856 /* Don't clip in the following because we're working on the
3858 XSetClipMask (s
->display
, s
->gc
, None
);
3860 /* Fill the pixmap with the background color/stipple. */
3863 /* Fill background with a stipple pattern. */
3864 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3865 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3866 0, 0, s
->background_width
, s
->height
);
3867 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3872 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3874 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3875 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3876 0, 0, s
->background_width
, s
->height
);
3877 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3881 /* Implementation idea: Is it possible to construct a mask?
3882 We could look at the color at the margins of the image, and
3883 say that this color is probably the background color of the
3885 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3887 s
->background_filled_p
= 1;
3890 /* Draw the foreground. */
3893 x_draw_image_foreground_1 (s
, pixmap
);
3894 x_set_glyph_string_clipping (s
);
3895 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
3896 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3897 XFreePixmap (s
->display
, pixmap
);
3900 x_draw_image_foreground (s
);
3902 /* If we must draw a relief around the image, do it. */
3904 || s
->hl
== DRAW_IMAGE_RAISED
3905 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3906 x_draw_image_relief (s
);
3910 /* Draw stretch glyph string S. */
3913 x_draw_stretch_glyph_string (s
)
3914 struct glyph_string
*s
;
3916 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3917 s
->stippled_p
= s
->face
->stipple
!= 0;
3919 if (s
->hl
== DRAW_CURSOR
3920 && !x_stretch_cursor_p
)
3922 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3923 as wide as the stretch glyph. */
3924 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
3927 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3929 /* Clear rest using the GC of the original non-cursor face. */
3930 if (width
< s
->background_width
)
3932 GC gc
= s
->face
->gc
;
3933 int x
= s
->x
+ width
, y
= s
->y
;
3934 int w
= s
->background_width
- width
, h
= s
->height
;
3937 x_get_glyph_string_clip_rect (s
, &r
);
3938 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
3940 if (s
->face
->stipple
)
3942 /* Fill background with a stipple pattern. */
3943 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3944 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3945 XSetFillStyle (s
->display
, gc
, FillSolid
);
3950 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3951 XSetForeground (s
->display
, gc
, xgcv
.background
);
3952 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3953 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3958 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3961 s
->background_filled_p
= 1;
3965 /* Draw glyph string S. */
3968 x_draw_glyph_string (s
)
3969 struct glyph_string
*s
;
3971 /* If S draws into the background of its successor, draw the
3972 background of the successor first so that S can draw into it.
3973 This makes S->next use XDrawString instead of XDrawImageString. */
3974 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3976 xassert (s
->next
->img
== NULL
);
3977 x_set_glyph_string_gc (s
->next
);
3978 x_set_glyph_string_clipping (s
->next
);
3979 x_draw_glyph_string_background (s
->next
, 1);
3982 /* Set up S->gc, set clipping and draw S. */
3983 x_set_glyph_string_gc (s
);
3984 x_set_glyph_string_clipping (s
);
3986 switch (s
->first_glyph
->type
)
3989 x_draw_image_glyph_string (s
);
3993 x_draw_stretch_glyph_string (s
);
3997 if (s
->for_overlaps_p
)
3998 s
->background_filled_p
= 1;
4000 x_draw_glyph_string_background (s
, 0);
4001 x_draw_glyph_string_foreground (s
);
4004 case COMPOSITE_GLYPH
:
4005 if (s
->for_overlaps_p
|| s
->gidx
> 0)
4006 s
->background_filled_p
= 1;
4008 x_draw_glyph_string_background (s
, 1);
4009 x_draw_composite_glyph_string_foreground (s
);
4016 if (!s
->for_overlaps_p
)
4018 /* Draw underline. */
4019 if (s
->face
->underline_p
)
4021 unsigned long dy
, h
;
4023 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
4025 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &dy
))
4028 if (s
->face
->underline_defaulted_p
)
4029 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4034 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4035 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
4036 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4038 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4042 /* Draw overline. */
4043 if (s
->face
->overline_p
)
4045 unsigned long dy
= 0, h
= 1;
4047 if (s
->face
->overline_color_defaulted_p
)
4048 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4053 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4054 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4055 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4057 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4061 /* Draw strike-through. */
4062 if (s
->face
->strike_through_p
)
4064 unsigned long h
= 1;
4065 unsigned long dy
= (s
->height
- h
) / 2;
4067 if (s
->face
->strike_through_color_defaulted_p
)
4068 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4073 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4074 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4075 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4077 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4082 if (s
->face
->box
!= FACE_NO_BOX
)
4083 x_draw_glyph_string_box (s
);
4086 /* Reset clipping. */
4087 XSetClipMask (s
->display
, s
->gc
, None
);
4091 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4092 struct face
**, int));
4095 /* Load glyph string S with a composition components specified by S->cmp.
4096 FACES is an array of faces for all components of this composition.
4097 S->gidx is the index of the first component for S.
4098 OVERLAPS_P non-zero means S should draw the foreground only, and
4099 use its lines physical height for clipping.
4101 Value is the index of a component not in S. */
4104 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4105 struct glyph_string
*s
;
4106 struct face
**faces
;
4113 s
->for_overlaps_p
= overlaps_p
;
4115 s
->face
= faces
[s
->gidx
];
4116 s
->font
= s
->face
->font
;
4117 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4119 /* For all glyphs of this composition, starting at the offset
4120 S->gidx, until we reach the end of the definition or encounter a
4121 glyph that requires the different face, add it to S. */
4123 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4126 /* All glyph strings for the same composition has the same width,
4127 i.e. the width set for the first component of the composition. */
4129 s
->width
= s
->first_glyph
->pixel_width
;
4131 /* If the specified font could not be loaded, use the frame's
4132 default font, but record the fact that we couldn't load it in
4133 the glyph string so that we can draw rectangles for the
4134 characters of the glyph string. */
4135 if (s
->font
== NULL
)
4137 s
->font_not_found_p
= 1;
4138 s
->font
= FRAME_FONT (s
->f
);
4141 /* Adjust base line for subscript/superscript text. */
4142 s
->ybase
+= s
->first_glyph
->voffset
;
4144 xassert (s
->face
&& s
->face
->gc
);
4146 /* This glyph string must always be drawn with 16-bit functions. */
4149 return s
->gidx
+ s
->nchars
;
4153 /* Load glyph string S with a sequence characters.
4154 FACE_ID is the face id of the string. START is the index of the
4155 first glyph to consider, END is the index of the last + 1.
4156 OVERLAPS_P non-zero means S should draw the foreground only, and
4157 use its lines physical height for clipping.
4159 Value is the index of the first glyph not in S. */
4162 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4163 struct glyph_string
*s
;
4165 int start
, end
, overlaps_p
;
4167 struct glyph
*glyph
, *last
;
4169 int glyph_not_available_p
;
4171 xassert (s
->f
== XFRAME (s
->w
->frame
));
4172 xassert (s
->nchars
== 0);
4173 xassert (start
>= 0 && end
> start
);
4175 s
->for_overlaps_p
= overlaps_p
,
4176 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4177 last
= s
->row
->glyphs
[s
->area
] + end
;
4178 voffset
= glyph
->voffset
;
4180 glyph_not_available_p
= glyph
->glyph_not_available_p
;
4183 && glyph
->type
== CHAR_GLYPH
4184 && glyph
->voffset
== voffset
4185 /* Same face id implies same font, nowadays. */
4186 && glyph
->face_id
== face_id
4187 && glyph
->glyph_not_available_p
== glyph_not_available_p
)
4191 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
4192 s
->char2b
+ s
->nchars
,
4194 s
->two_byte_p
= two_byte_p
;
4196 xassert (s
->nchars
<= end
- start
);
4197 s
->width
+= glyph
->pixel_width
;
4201 s
->font
= s
->face
->font
;
4202 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4204 /* If the specified font could not be loaded, use the frame's font,
4205 but record the fact that we couldn't load it in
4206 S->font_not_found_p so that we can draw rectangles for the
4207 characters of the glyph string. */
4208 if (s
->font
== NULL
|| glyph_not_available_p
)
4210 s
->font_not_found_p
= 1;
4211 s
->font
= FRAME_FONT (s
->f
);
4214 /* Adjust base line for subscript/superscript text. */
4215 s
->ybase
+= voffset
;
4217 xassert (s
->face
&& s
->face
->gc
);
4218 return glyph
- s
->row
->glyphs
[s
->area
];
4222 /* Fill glyph string S from image glyph S->first_glyph. */
4225 x_fill_image_glyph_string (s
)
4226 struct glyph_string
*s
;
4228 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4229 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img_id
);
4231 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
4232 s
->font
= s
->face
->font
;
4233 s
->width
= s
->first_glyph
->pixel_width
;
4235 /* Adjust base line for subscript/superscript text. */
4236 s
->ybase
+= s
->first_glyph
->voffset
;
4240 /* Fill glyph string S from stretch glyph S->first_glyph. */
4243 x_fill_stretch_glyph_string (s
)
4244 struct glyph_string
*s
;
4246 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4247 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->face_id
);
4248 s
->font
= s
->face
->font
;
4249 s
->width
= s
->first_glyph
->pixel_width
;
4251 /* Adjust base line for subscript/superscript text. */
4252 s
->ybase
+= s
->first_glyph
->voffset
;
4256 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4257 of XChar2b structures for S; it can't be allocated in
4258 x_init_glyph_string because it must be allocated via `alloca'. W
4259 is the window on which S is drawn. ROW and AREA are the glyph row
4260 and area within the row from which S is constructed. START is the
4261 index of the first glyph structure covered by S. HL is a
4262 face-override for drawing S. */
4265 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4266 struct glyph_string
*s
;
4269 struct glyph_row
*row
;
4270 enum glyph_row_area area
;
4272 enum draw_glyphs_face hl
;
4274 bzero (s
, sizeof *s
);
4276 s
->f
= XFRAME (w
->frame
);
4277 s
->display
= FRAME_X_DISPLAY (s
->f
);
4278 s
->window
= FRAME_X_WINDOW (s
->f
);
4283 s
->first_glyph
= row
->glyphs
[area
] + start
;
4284 s
->height
= row
->height
;
4285 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4287 /* Display the internal border below the tool-bar window. */
4288 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4289 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4291 s
->ybase
= s
->y
+ row
->ascent
;
4295 /* Set background width of glyph string S. START is the index of the
4296 first glyph following S. LAST_X is the right-most x-position + 1
4297 in the drawing area. */
4300 x_set_glyph_string_background_width (s
, start
, last_x
)
4301 struct glyph_string
*s
;
4305 /* If the face of this glyph string has to be drawn to the end of
4306 the drawing area, set S->extends_to_end_of_line_p. */
4307 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4309 if (start
== s
->row
->used
[s
->area
]
4310 && s
->hl
== DRAW_NORMAL_TEXT
4311 && ((s
->area
== TEXT_AREA
&& s
->row
->fill_line_p
)
4312 || s
->face
->background
!= default_face
->background
4313 || s
->face
->stipple
!= default_face
->stipple
))
4314 s
->extends_to_end_of_line_p
= 1;
4316 /* If S extends its face to the end of the line, set its
4317 background_width to the distance to the right edge of the drawing
4319 if (s
->extends_to_end_of_line_p
)
4320 s
->background_width
= last_x
- s
->x
+ 1;
4322 s
->background_width
= s
->width
;
4326 /* Add a glyph string for a stretch glyph to the list of strings
4327 between HEAD and TAIL. START is the index of the stretch glyph in
4328 row area AREA of glyph row ROW. END is the index of the last glyph
4329 in that glyph row area. X is the current output position assigned
4330 to the new glyph string constructed. HL overrides that face of the
4331 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4332 is the right-most x-position of the drawing area. */
4334 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4335 and below -- keep them on one line. */
4336 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4339 s = (struct glyph_string *) alloca (sizeof *s); \
4340 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4341 x_fill_stretch_glyph_string (s); \
4342 x_append_glyph_string (&HEAD, &TAIL, s); \
4349 /* Add a glyph string for an image glyph to the list of strings
4350 between HEAD and TAIL. START is the index of the image glyph in
4351 row area AREA of glyph row ROW. END is the index of the last glyph
4352 in that glyph row area. X is the current output position assigned
4353 to the new glyph string constructed. HL overrides that face of the
4354 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4355 is the right-most x-position of the drawing area. */
4357 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4360 s = (struct glyph_string *) alloca (sizeof *s); \
4361 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4362 x_fill_image_glyph_string (s); \
4363 x_append_glyph_string (&HEAD, &TAIL, s); \
4370 /* Add a glyph string for a sequence of character glyphs to the list
4371 of strings between HEAD and TAIL. START is the index of the first
4372 glyph in row area AREA of glyph row ROW that is part of the new
4373 glyph string. END is the index of the last glyph in that glyph row
4374 area. X is the current output position assigned to the new glyph
4375 string constructed. HL overrides that face of the glyph; e.g. it
4376 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4377 right-most x-position of the drawing area. */
4379 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4382 int c, charset, face_id; \
4385 c = (ROW)->glyphs[AREA][START].u.ch; \
4386 face_id = (ROW)->glyphs[AREA][START].face_id; \
4388 s = (struct glyph_string *) alloca (sizeof *s); \
4389 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4390 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4391 x_append_glyph_string (&HEAD, &TAIL, s); \
4393 START = x_fill_glyph_string (s, face_id, START, END, \
4399 /* Add a glyph string for a composite sequence to the list of strings
4400 between HEAD and TAIL. START is the index of the first glyph in
4401 row area AREA of glyph row ROW that is part of the new glyph
4402 string. END is the index of the last glyph in that glyph row area.
4403 X is the current output position assigned to the new glyph string
4404 constructed. HL overrides that face of the glyph; e.g. it is
4405 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4406 x-position of the drawing area. */
4408 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4410 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4411 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4412 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4413 struct composition *cmp = composition_table[cmp_id]; \
4414 int glyph_len = cmp->glyph_len; \
4416 struct face **faces; \
4417 struct glyph_string *first_s = NULL; \
4420 base_face = base_face->ascii_face; \
4421 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4422 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4423 /* At first, fill in `char2b' and `faces'. */ \
4424 for (n = 0; n < glyph_len; n++) \
4426 int c = COMPOSITION_GLYPH (cmp, n); \
4427 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4428 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4429 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4430 this_face_id, char2b + n, 1); \
4433 /* Make glyph_strings for each glyph sequence that is drawable by \
4434 the same face, and append them to HEAD/TAIL. */ \
4435 for (n = 0; n < cmp->glyph_len;) \
4437 s = (struct glyph_string *) alloca (sizeof *s); \
4438 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4439 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4447 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4455 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4456 of AREA of glyph row ROW on window W between indices START and END.
4457 HL overrides the face for drawing glyph strings, e.g. it is
4458 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4459 x-positions of the drawing area.
4461 This is an ugly monster macro construct because we must use alloca
4462 to allocate glyph strings (because x_draw_glyphs can be called
4465 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4468 HEAD = TAIL = NULL; \
4469 while (START < END) \
4471 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4472 switch (first_glyph->type) \
4475 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4476 TAIL, HL, X, LAST_X, \
4480 case COMPOSITE_GLYPH: \
4481 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4482 HEAD, TAIL, HL, X, LAST_X,\
4486 case STRETCH_GLYPH: \
4487 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4488 HEAD, TAIL, HL, X, LAST_X); \
4492 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4493 TAIL, HL, X, LAST_X); \
4500 x_set_glyph_string_background_width (s, START, LAST_X); \
4507 /* Draw glyphs between START and END in AREA of ROW on window W,
4508 starting at x-position X. X is relative to AREA in W. HL is a
4509 face-override with the following meaning:
4511 DRAW_NORMAL_TEXT draw normally
4512 DRAW_CURSOR draw in cursor face
4513 DRAW_MOUSE_FACE draw in mouse face.
4514 DRAW_INVERSE_VIDEO draw in mode line face
4515 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4516 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4518 If REAL_START is non-null, return in *REAL_START the real starting
4519 position for display. This can be different from START in case
4520 overlapping glyphs must be displayed. If REAL_END is non-null,
4521 return in *REAL_END the real end position for display. This can be
4522 different from END in case overlapping glyphs must be displayed.
4524 If OVERLAPS_P is non-zero, draw only the foreground of characters
4525 and clip to the physical height of ROW.
4527 Value is the x-position reached, relative to AREA of W. */
4530 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, real_start
, real_end
,
4534 struct glyph_row
*row
;
4535 enum glyph_row_area area
;
4537 enum draw_glyphs_face hl
;
4538 int *real_start
, *real_end
;
4541 struct glyph_string
*head
, *tail
;
4542 struct glyph_string
*s
;
4543 int last_x
, area_width
;
4547 /* Let's rather be paranoid than getting a SEGV. */
4548 start
= max (0, start
);
4549 end
= min (end
, row
->used
[area
]);
4551 *real_start
= start
;
4555 /* Translate X to frame coordinates. Set last_x to the right
4556 end of the drawing area. */
4557 if (row
->full_width_p
)
4559 /* X is relative to the left edge of W, without scroll bars
4561 struct frame
*f
= XFRAME (w
->frame
);
4562 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4563 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
4566 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4567 last_x
= window_left_x
+ area_width
;
4569 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4571 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4572 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4578 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
4579 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
4583 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
4584 area_width
= window_box_width (w
, area
);
4585 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
4588 /* Build a doubly-linked list of glyph_string structures between
4589 head and tail from what we have to draw. Note that the macro
4590 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4591 the reason we use a separate variable `i'. */
4593 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
4596 x_reached
= tail
->x
+ tail
->background_width
;
4600 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4601 the row, redraw some glyphs in front or following the glyph
4602 strings built above. */
4603 if (!overlaps_p
&& row
->contains_overlapping_glyphs_p
)
4606 struct glyph_string
*h
, *t
;
4608 /* Compute overhangs for all glyph strings. */
4609 for (s
= head
; s
; s
= s
->next
)
4610 x_compute_glyph_string_overhangs (s
);
4612 /* Prepend glyph strings for glyphs in front of the first glyph
4613 string that are overwritten because of the first glyph
4614 string's left overhang. The background of all strings
4615 prepended must be drawn because the first glyph string
4617 i
= x_left_overwritten (head
);
4621 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
4622 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4626 *real_start
= start
;
4627 x_compute_overhangs_and_x (t
, head
->x
, 1);
4628 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4631 /* Prepend glyph strings for glyphs in front of the first glyph
4632 string that overwrite that glyph string because of their
4633 right overhang. For these strings, only the foreground must
4634 be drawn, because it draws over the glyph string at `head'.
4635 The background must not be drawn because this would overwrite
4636 right overhangs of preceding glyphs for which no glyph
4638 i
= x_left_overwriting (head
);
4641 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
4642 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4644 for (s
= h
; s
; s
= s
->next
)
4645 s
->background_filled_p
= 1;
4648 x_compute_overhangs_and_x (t
, head
->x
, 1);
4649 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4652 /* Append glyphs strings for glyphs following the last glyph
4653 string tail that are overwritten by tail. The background of
4654 these strings has to be drawn because tail's foreground draws
4656 i
= x_right_overwritten (tail
);
4659 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4660 DRAW_NORMAL_TEXT
, x
, last_x
,
4662 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4663 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4668 /* Append glyph strings for glyphs following the last glyph
4669 string tail that overwrite tail. The foreground of such
4670 glyphs has to be drawn because it writes into the background
4671 of tail. The background must not be drawn because it could
4672 paint over the foreground of following glyphs. */
4673 i
= x_right_overwriting (tail
);
4676 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4677 DRAW_NORMAL_TEXT
, x
, last_x
,
4679 for (s
= h
; s
; s
= s
->next
)
4680 s
->background_filled_p
= 1;
4681 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4682 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4688 /* Draw all strings. */
4689 for (s
= head
; s
; s
= s
->next
)
4690 x_draw_glyph_string (s
);
4692 /* Value is the x-position up to which drawn, relative to AREA of W.
4693 This doesn't include parts drawn because of overhangs. */
4694 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
4695 if (!row
->full_width_p
)
4697 if (area
> LEFT_MARGIN_AREA
)
4698 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
4699 if (area
> TEXT_AREA
)
4700 x_reached
-= window_box_width (w
, TEXT_AREA
);
4706 /* Fix the display of area AREA of overlapping row ROW in window W. */
4709 x_fix_overlapping_area (w
, row
, area
)
4711 struct glyph_row
*row
;
4712 enum glyph_row_area area
;
4718 if (area
== LEFT_MARGIN_AREA
)
4720 else if (area
== TEXT_AREA
)
4721 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
4723 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
4724 + window_box_width (w
, TEXT_AREA
));
4726 for (i
= 0; i
< row
->used
[area
];)
4728 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
4730 int start
= i
, start_x
= x
;
4734 x
+= row
->glyphs
[area
][i
].pixel_width
;
4737 while (i
< row
->used
[area
]
4738 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
4740 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
4742 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4747 x
+= row
->glyphs
[area
][i
].pixel_width
;
4756 /* Output LEN glyphs starting at START at the nominal cursor position.
4757 Advance the nominal cursor over the text. The global variable
4758 updated_window contains the window being updated, updated_row is
4759 the glyph row being updated, and updated_area is the area of that
4760 row being updated. */
4763 x_write_glyphs (start
, len
)
4764 struct glyph
*start
;
4767 int x
, hpos
, real_start
, real_end
;
4769 xassert (updated_window
&& updated_row
);
4774 hpos
= start
- updated_row
->glyphs
[updated_area
];
4775 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
4776 updated_row
, updated_area
,
4778 (updated_row
->inverse_p
4779 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4780 &real_start
, &real_end
, 0);
4782 /* If we drew over the cursor, note that it is not visible any more. */
4783 note_overwritten_text_cursor (updated_window
, real_start
,
4784 real_end
- real_start
);
4788 /* Advance the output cursor. */
4789 output_cursor
.hpos
+= len
;
4790 output_cursor
.x
= x
;
4794 /* Insert LEN glyphs from START at the nominal cursor position. */
4797 x_insert_glyphs (start
, len
)
4798 struct glyph
*start
;
4803 int line_height
, shift_by_width
, shifted_region_width
;
4804 struct glyph_row
*row
;
4805 struct glyph
*glyph
;
4806 int frame_x
, frame_y
, hpos
, real_start
, real_end
;
4808 xassert (updated_window
&& updated_row
);
4811 f
= XFRAME (WINDOW_FRAME (w
));
4813 /* Get the height of the line we are in. */
4815 line_height
= row
->height
;
4817 /* Get the width of the glyphs to insert. */
4819 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
4820 shift_by_width
+= glyph
->pixel_width
;
4822 /* Get the width of the region to shift right. */
4823 shifted_region_width
= (window_box_width (w
, updated_area
)
4828 frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, output_cursor
.x
);
4829 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
4830 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4831 f
->output_data
.x
->normal_gc
,
4833 shifted_region_width
, line_height
,
4834 frame_x
+ shift_by_width
, frame_y
);
4836 /* Write the glyphs. */
4837 hpos
= start
- row
->glyphs
[updated_area
];
4838 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
4839 DRAW_NORMAL_TEXT
, &real_start
, &real_end
, 0);
4840 note_overwritten_text_cursor (w
, real_start
, real_end
- real_start
);
4842 /* Advance the output cursor. */
4843 output_cursor
.hpos
+= len
;
4844 output_cursor
.x
+= shift_by_width
;
4849 /* Delete N glyphs at the nominal cursor position. Not implemented
4860 /* Erase the current text line from the nominal cursor position
4861 (inclusive) to pixel column TO_X (exclusive). The idea is that
4862 everything from TO_X onward is already erased.
4864 TO_X is a pixel position relative to updated_area of
4865 updated_window. TO_X == -1 means clear to the end of this area. */
4868 x_clear_end_of_line (to_x
)
4872 struct window
*w
= updated_window
;
4873 int max_x
, min_y
, max_y
;
4874 int from_x
, from_y
, to_y
;
4876 xassert (updated_window
&& updated_row
);
4877 f
= XFRAME (w
->frame
);
4879 if (updated_row
->full_width_p
)
4881 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4882 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4883 && !w
->pseudo_window_p
)
4884 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4887 max_x
= window_box_width (w
, updated_area
);
4888 max_y
= window_text_bottom_y (w
);
4890 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4891 of window. For TO_X > 0, truncate to end of drawing area. */
4897 to_x
= min (to_x
, max_x
);
4899 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
4901 /* Notice if the cursor will be cleared by this operation. */
4902 if (!updated_row
->full_width_p
)
4903 note_overwritten_text_cursor (w
, output_cursor
.hpos
, -1);
4905 from_x
= output_cursor
.x
;
4907 /* Translate to frame coordinates. */
4908 if (updated_row
->full_width_p
)
4910 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
4911 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
4915 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
4916 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
4919 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
4920 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
4921 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
4923 /* Prevent inadvertently clearing to end of the X window. */
4924 if (to_x
> from_x
&& to_y
> from_y
)
4927 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4928 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
4935 /* Clear entire frame. If updating_frame is non-null, clear that
4936 frame. Otherwise clear the selected frame. */
4946 f
= SELECTED_FRAME ();
4948 /* Clearing the frame will erase any cursor, so mark them all as no
4950 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4951 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4952 output_cursor
.x
= -1;
4954 /* We don't set the output cursor here because there will always
4955 follow an explicit cursor_to. */
4957 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4959 /* We have to clear the scroll bars, too. If we have changed
4960 colors or something like that, then they should be notified. */
4961 x_scroll_bar_clear (f
);
4963 XFlush (FRAME_X_DISPLAY (f
));
4969 /* Invert the middle quarter of the frame for .15 sec. */
4971 /* We use the select system call to do the waiting, so we have to make
4972 sure it's available. If it isn't, we just won't do visual bells. */
4974 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4977 /* Subtract the `struct timeval' values X and Y, storing the result in
4978 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4981 timeval_subtract (result
, x
, y
)
4982 struct timeval
*result
, x
, y
;
4984 /* Perform the carry for the later subtraction by updating y. This
4985 is safer because on some systems the tv_sec member is unsigned. */
4986 if (x
.tv_usec
< y
.tv_usec
)
4988 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4989 y
.tv_usec
-= 1000000 * nsec
;
4993 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4995 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4996 y
.tv_usec
+= 1000000 * nsec
;
5000 /* Compute the time remaining to wait. tv_usec is certainly
5002 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
5003 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
5005 /* Return indication of whether the result should be considered
5007 return x
.tv_sec
< y
.tv_sec
;
5019 /* Create a GC that will use the GXxor function to flip foreground
5020 pixels into background pixels. */
5024 values
.function
= GXxor
;
5025 values
.foreground
= (f
->output_data
.x
->foreground_pixel
5026 ^ f
->output_data
.x
->background_pixel
);
5028 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5029 GCFunction
| GCForeground
, &values
);
5033 /* Get the height not including a menu bar widget. */
5034 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
5035 /* Height of each line to flash. */
5036 int flash_height
= FRAME_LINE_HEIGHT (f
);
5037 /* These will be the left and right margins of the rectangles. */
5038 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
5039 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
5043 /* Don't flash the area between a scroll bar and the frame
5044 edge it is next to. */
5045 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
5047 case vertical_scroll_bar_left
:
5048 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5051 case vertical_scroll_bar_right
:
5052 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5059 width
= flash_right
- flash_left
;
5061 /* If window is tall, flash top and bottom line. */
5062 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5064 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5066 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5067 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5068 width
, flash_height
);
5069 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5071 (height
- flash_height
5072 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5073 width
, flash_height
);
5076 /* If it is short, flash it all. */
5077 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5078 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5079 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5084 struct timeval wakeup
;
5086 EMACS_GET_TIME (wakeup
);
5088 /* Compute time to wait until, propagating carry from usecs. */
5089 wakeup
.tv_usec
+= 150000;
5090 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5091 wakeup
.tv_usec
%= 1000000;
5093 /* Keep waiting until past the time wakeup. */
5096 struct timeval timeout
;
5098 EMACS_GET_TIME (timeout
);
5100 /* In effect, timeout = wakeup - timeout.
5101 Break if result would be negative. */
5102 if (timeval_subtract (&timeout
, wakeup
, timeout
))
5105 /* Try to wait that long--but we might wake up sooner. */
5106 select (0, NULL
, NULL
, NULL
, &timeout
);
5110 /* If window is tall, flash top and bottom line. */
5111 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5113 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5115 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5116 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5117 width
, flash_height
);
5118 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5120 (height
- flash_height
5121 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5122 width
, flash_height
);
5125 /* If it is short, flash it all. */
5126 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5127 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5128 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5130 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5138 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5141 /* Make audible bell. */
5146 struct frame
*f
= SELECTED_FRAME ();
5148 if (FRAME_X_DISPLAY (f
))
5150 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5157 XBell (FRAME_X_DISPLAY (f
), 0);
5158 XFlush (FRAME_X_DISPLAY (f
));
5165 /* Specify how many text lines, from the top of the window,
5166 should be affected by insert-lines and delete-lines operations.
5167 This, and those operations, are used only within an update
5168 that is bounded by calls to x_update_begin and x_update_end. */
5171 XTset_terminal_window (n
)
5174 /* This function intentionally left blank. */
5179 /***********************************************************************
5181 ***********************************************************************/
5183 /* Perform an insert-lines or delete-lines operation, inserting N
5184 lines or deleting -N lines at vertical position VPOS. */
5187 x_ins_del_lines (vpos
, n
)
5194 /* Scroll part of the display as described by RUN. */
5197 x_scroll_run (w
, run
)
5201 struct frame
*f
= XFRAME (w
->frame
);
5202 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5204 /* Get frame-relative bounding box of the text display area of W,
5205 without mode lines. Include in this box the flags areas to the
5206 left and right of W. */
5207 window_box (w
, -1, &x
, &y
, &width
, &height
);
5208 width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
5209 x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
5211 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5212 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5213 bottom_y
= y
+ height
;
5217 /* Scrolling up. Make sure we don't copy part of the mode
5218 line at the bottom. */
5219 if (from_y
+ run
->height
> bottom_y
)
5220 height
= bottom_y
- from_y
;
5222 height
= run
->height
;
5226 /* Scolling down. Make sure we don't copy over the mode line.
5228 if (to_y
+ run
->height
> bottom_y
)
5229 height
= bottom_y
- to_y
;
5231 height
= run
->height
;
5236 /* Cursor off. Will be switched on again in x_update_window_end. */
5240 XCopyArea (FRAME_X_DISPLAY (f
),
5241 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5242 f
->output_data
.x
->normal_gc
,
5252 /***********************************************************************
5254 ***********************************************************************/
5256 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5257 corner of the exposed rectangle. W and H are width and height of
5258 the exposed area. All are pixel values. W or H zero means redraw
5259 the entire frame. */
5262 expose_frame (f
, x
, y
, w
, h
)
5268 TRACE ((stderr
, "expose_frame "));
5270 /* No need to redraw if frame will be redrawn soon. */
5271 if (FRAME_GARBAGED_P (f
))
5273 TRACE ((stderr
, " garbaged\n"));
5277 /* If basic faces haven't been realized yet, there is no point in
5278 trying to redraw anything. This can happen when we get an expose
5279 event while Emacs is starting, e.g. by moving another window. */
5280 if (FRAME_FACE_CACHE (f
) == NULL
5281 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5283 TRACE ((stderr
, " no faces\n"));
5287 if (w
== 0 || h
== 0)
5290 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5291 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5301 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5302 expose_window_tree (XWINDOW (f
->root_window
), &r
);
5304 if (WINDOWP (f
->tool_bar_window
))
5306 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5307 XRectangle window_rect
;
5308 XRectangle intersection_rect
;
5309 int window_x
, window_y
, window_width
, window_height
;
5312 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5313 window_rect
.x
= window_x
;
5314 window_rect
.y
= window_y
;
5315 window_rect
.width
= window_width
;
5316 window_rect
.height
= window_height
;
5318 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5319 expose_window (w
, &intersection_rect
);
5322 #ifndef USE_X_TOOLKIT
5323 if (WINDOWP (f
->menu_bar_window
))
5325 struct window
*w
= XWINDOW (f
->menu_bar_window
);
5326 XRectangle window_rect
;
5327 XRectangle intersection_rect
;
5328 int window_x
, window_y
, window_width
, window_height
;
5331 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5332 window_rect
.x
= window_x
;
5333 window_rect
.y
= window_y
;
5334 window_rect
.width
= window_width
;
5335 window_rect
.height
= window_height
;
5337 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5338 expose_window (w
, &intersection_rect
);
5340 #endif /* not USE_X_TOOLKIT */
5344 /* Redraw (parts) of all windows in the window tree rooted at W that
5345 intersect R. R contains frame pixel coordinates. */
5348 expose_window_tree (w
, r
)
5354 if (!NILP (w
->hchild
))
5355 expose_window_tree (XWINDOW (w
->hchild
), r
);
5356 else if (!NILP (w
->vchild
))
5357 expose_window_tree (XWINDOW (w
->vchild
), r
);
5360 XRectangle window_rect
;
5361 XRectangle intersection_rect
;
5362 struct frame
*f
= XFRAME (w
->frame
);
5363 int window_x
, window_y
, window_width
, window_height
;
5365 /* Frame-relative pixel rectangle of W. */
5366 window_box (w
, -1, &window_x
, &window_y
, &window_width
,
5370 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
5371 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5372 window_rect
.y
= window_y
;
5375 + FRAME_X_FLAGS_AREA_WIDTH (f
)
5376 + FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5378 = window_height
+ CURRENT_MODE_LINE_HEIGHT (w
);
5380 if (x_intersect_rectangles (r
, &window_rect
, &intersection_rect
))
5381 expose_window (w
, &intersection_rect
);
5384 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5389 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5390 which intersects rectangle R. R is in window-relative coordinates. */
5393 expose_area (w
, row
, r
, area
)
5395 struct glyph_row
*row
;
5397 enum glyph_row_area area
;
5400 struct glyph
*first
= row
->glyphs
[area
];
5401 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5405 /* Set x to the window-relative start position for drawing glyphs of
5406 AREA. The first glyph of the text area can be partially visible.
5407 The first glyphs of other areas cannot. */
5408 if (area
== LEFT_MARGIN_AREA
)
5410 else if (area
== TEXT_AREA
)
5411 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5413 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5414 + window_box_width (w
, TEXT_AREA
));
5416 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5417 /* If row extends face to end of line write the whole line. */
5418 x_draw_glyphs (w
, x
, row
, area
,
5420 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5424 /* Find the first glyph that must be redrawn. */
5426 && x
+ first
->pixel_width
< r
->x
)
5428 x
+= first
->pixel_width
;
5432 /* Find the last one. */
5436 && x
< r
->x
+ r
->width
)
5438 x
+= last
->pixel_width
;
5444 x_draw_glyphs (w
, first_x
, row
, area
,
5445 first
- row
->glyphs
[area
],
5446 last
- row
->glyphs
[area
],
5447 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5453 /* Redraw the parts of the glyph row ROW on window W intersecting
5454 rectangle R. R is in window-relative coordinates. */
5457 expose_line (w
, row
, r
)
5459 struct glyph_row
*row
;
5462 xassert (row
->enabled_p
);
5464 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5465 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5466 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5470 if (row
->used
[LEFT_MARGIN_AREA
])
5471 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5472 if (row
->used
[TEXT_AREA
])
5473 expose_area (w
, row
, r
, TEXT_AREA
);
5474 if (row
->used
[RIGHT_MARGIN_AREA
])
5475 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5476 x_draw_row_bitmaps (w
, row
);
5481 /* Return non-zero if W's cursor intersects rectangle R. */
5484 x_phys_cursor_in_rect_p (w
, r
)
5488 XRectangle cr
, result
;
5489 struct glyph
*cursor_glyph
;
5491 cursor_glyph
= get_phys_cursor_glyph (w
);
5494 cr
.x
= w
->phys_cursor
.x
;
5495 cr
.y
= w
->phys_cursor
.y
;
5496 cr
.width
= cursor_glyph
->pixel_width
;
5497 cr
.height
= w
->phys_cursor_height
;
5498 return x_intersect_rectangles (&cr
, r
, &result
);
5505 /* Redraw a rectangle of window W. R is a rectangle in window
5506 relative coordinates. Call this function with input blocked. */
5509 expose_window (w
, r
)
5513 struct glyph_row
*row
;
5515 int yb
= window_text_bottom_y (w
);
5516 int cursor_cleared_p
;
5518 /* If window is not yet fully initialized, do nothing. This can
5519 happen when toolkit scroll bars are used and a window is split.
5520 Reconfiguring the scroll bar will generate an expose for a newly
5522 if (w
->current_matrix
== NULL
)
5525 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
5526 r
->x
, r
->y
, r
->width
, r
->height
));
5528 /* Convert to window coordinates. */
5529 r
->x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
->x
);
5530 r
->y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
->y
);
5532 /* Turn off the cursor. */
5533 if (!w
->pseudo_window_p
5534 && x_phys_cursor_in_rect_p (w
, r
))
5537 cursor_cleared_p
= 1;
5540 cursor_cleared_p
= 0;
5542 /* Find the first row intersecting the rectangle R. */
5543 row
= w
->current_matrix
->rows
;
5545 while (row
->enabled_p
5547 && y
+ row
->height
< r
->y
)
5553 /* Display the text in the rectangle, one text line at a time. */
5554 while (row
->enabled_p
5556 && y
< r
->y
+ r
->height
)
5558 expose_line (w
, row
, r
);
5563 /* Display the mode line if there is one. */
5564 if (WINDOW_WANTS_MODELINE_P (w
)
5565 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
5567 && row
->y
< r
->y
+ r
->height
)
5568 expose_line (w
, row
, r
);
5570 if (!w
->pseudo_window_p
)
5572 /* Draw border between windows. */
5573 x_draw_vertical_border (w
);
5575 /* Turn the cursor on again. */
5576 if (cursor_cleared_p
)
5577 x_update_window_cursor (w
, 1);
5582 /* Determine the intersection of two rectangles R1 and R2. Return
5583 the intersection in *RESULT. Value is non-zero if RESULT is not
5587 x_intersect_rectangles (r1
, r2
, result
)
5588 XRectangle
*r1
, *r2
, *result
;
5590 XRectangle
*left
, *right
;
5591 XRectangle
*upper
, *lower
;
5592 int intersection_p
= 0;
5594 /* Rearrange so that R1 is the left-most rectangle. */
5596 left
= r1
, right
= r2
;
5598 left
= r2
, right
= r1
;
5600 /* X0 of the intersection is right.x0, if this is inside R1,
5601 otherwise there is no intersection. */
5602 if (right
->x
<= left
->x
+ left
->width
)
5604 result
->x
= right
->x
;
5606 /* The right end of the intersection is the minimum of the
5607 the right ends of left and right. */
5608 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
5611 /* Same game for Y. */
5613 upper
= r1
, lower
= r2
;
5615 upper
= r2
, lower
= r1
;
5617 /* The upper end of the intersection is lower.y0, if this is inside
5618 of upper. Otherwise, there is no intersection. */
5619 if (lower
->y
<= upper
->y
+ upper
->height
)
5621 result
->y
= lower
->y
;
5623 /* The lower end of the intersection is the minimum of the lower
5624 ends of upper and lower. */
5625 result
->height
= (min (lower
->y
+ lower
->height
,
5626 upper
->y
+ upper
->height
)
5632 return intersection_p
;
5643 /* We used to only do this if Vx_no_window_manager was non-nil, but
5644 the ICCCM (section 4.1.6) says that the window's border pixmap
5645 and border pixel are window attributes which are "private to the
5646 client", so we can always change it to whatever we want. */
5648 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5649 f
->output_data
.x
->border_pixel
);
5651 x_update_cursor (f
, 1);
5655 frame_unhighlight (f
)
5658 /* We used to only do this if Vx_no_window_manager was non-nil, but
5659 the ICCCM (section 4.1.6) says that the window's border pixmap
5660 and border pixel are window attributes which are "private to the
5661 client", so we can always change it to whatever we want. */
5663 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5664 f
->output_data
.x
->border_tile
);
5666 x_update_cursor (f
, 1);
5669 /* The focus has changed. Update the frames as necessary to reflect
5670 the new situation. Note that we can't change the selected frame
5671 here, because the Lisp code we are interrupting might become confused.
5672 Each event gets marked with the frame in which it occurred, so the
5673 Lisp code can tell when the switch took place by examining the events. */
5676 x_new_focus_frame (dpyinfo
, frame
)
5677 struct x_display_info
*dpyinfo
;
5678 struct frame
*frame
;
5680 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5682 if (frame
!= dpyinfo
->x_focus_frame
)
5684 /* Set this before calling other routines, so that they see
5685 the correct value of x_focus_frame. */
5686 dpyinfo
->x_focus_frame
= frame
;
5688 if (old_focus
&& old_focus
->auto_lower
)
5689 x_lower_frame (old_focus
);
5692 selected_frame
= frame
;
5693 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
5695 Fselect_window (selected_frame
->selected_window
);
5696 choose_minibuf_frame ();
5699 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
5700 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
5702 pending_autoraise_frame
= 0;
5705 x_frame_rehighlight (dpyinfo
);
5708 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5711 x_mouse_leave (dpyinfo
)
5712 struct x_display_info
*dpyinfo
;
5714 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
5717 /* The focus has changed, or we have redirected a frame's focus to
5718 another frame (this happens when a frame uses a surrogate
5719 mini-buffer frame). Shift the highlight as appropriate.
5721 The FRAME argument doesn't necessarily have anything to do with which
5722 frame is being highlighted or un-highlighted; we only use it to find
5723 the appropriate X display info. */
5726 XTframe_rehighlight (frame
)
5727 struct frame
*frame
;
5729 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
5733 x_frame_rehighlight (dpyinfo
)
5734 struct x_display_info
*dpyinfo
;
5736 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
5738 if (dpyinfo
->x_focus_frame
)
5740 dpyinfo
->x_highlight_frame
5741 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
5742 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
5743 : dpyinfo
->x_focus_frame
);
5744 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
5746 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
5747 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
5751 dpyinfo
->x_highlight_frame
= 0;
5753 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
5756 frame_unhighlight (old_highlight
);
5757 if (dpyinfo
->x_highlight_frame
)
5758 frame_highlight (dpyinfo
->x_highlight_frame
);
5764 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5766 /* Initialize mode_switch_bit and modifier_meaning. */
5768 x_find_modifier_meanings (dpyinfo
)
5769 struct x_display_info
*dpyinfo
;
5771 int min_code
, max_code
;
5774 XModifierKeymap
*mods
;
5776 dpyinfo
->meta_mod_mask
= 0;
5777 dpyinfo
->shift_lock_mask
= 0;
5778 dpyinfo
->alt_mod_mask
= 0;
5779 dpyinfo
->super_mod_mask
= 0;
5780 dpyinfo
->hyper_mod_mask
= 0;
5783 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
5785 min_code
= dpyinfo
->display
->min_keycode
;
5786 max_code
= dpyinfo
->display
->max_keycode
;
5789 syms
= XGetKeyboardMapping (dpyinfo
->display
,
5790 min_code
, max_code
- min_code
+ 1,
5792 mods
= XGetModifierMapping (dpyinfo
->display
);
5794 /* Scan the modifier table to see which modifier bits the Meta and
5795 Alt keysyms are on. */
5797 int row
, col
; /* The row and column in the modifier table. */
5799 for (row
= 3; row
< 8; row
++)
5800 for (col
= 0; col
< mods
->max_keypermod
; col
++)
5803 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
5805 /* Zeroes are used for filler. Skip them. */
5809 /* Are any of this keycode's keysyms a meta key? */
5813 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
5815 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
5821 dpyinfo
->meta_mod_mask
|= (1 << row
);
5826 dpyinfo
->alt_mod_mask
|= (1 << row
);
5831 dpyinfo
->hyper_mod_mask
|= (1 << row
);
5836 dpyinfo
->super_mod_mask
|= (1 << row
);
5840 /* Ignore this if it's not on the lock modifier. */
5841 if ((1 << row
) == LockMask
)
5842 dpyinfo
->shift_lock_mask
= LockMask
;
5850 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5851 if (! dpyinfo
->meta_mod_mask
)
5853 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
5854 dpyinfo
->alt_mod_mask
= 0;
5857 /* If some keys are both alt and meta,
5858 make them just meta, not alt. */
5859 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
5861 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
5864 XFree ((char *) syms
);
5865 XFreeModifiermap (mods
);
5868 /* Convert between the modifier bits X uses and the modifier bits
5872 x_x_to_emacs_modifiers (dpyinfo
, state
)
5873 struct x_display_info
*dpyinfo
;
5876 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
5877 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
5878 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
5879 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
5880 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
5881 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
5885 x_emacs_to_x_modifiers (dpyinfo
, state
)
5886 struct x_display_info
*dpyinfo
;
5889 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
5890 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
5891 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
5892 | ((state
& shift_modifier
) ? ShiftMask
: 0)
5893 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
5894 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
5897 /* Convert a keysym to its name. */
5900 x_get_keysym_name (keysym
)
5906 value
= XKeysymToString (keysym
);
5914 /* Mouse clicks and mouse movement. Rah. */
5916 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5917 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5918 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5919 not force the value into range. */
5922 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
5924 register int pix_x
, pix_y
;
5925 register int *x
, *y
;
5929 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5930 even for negative values. */
5932 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
5934 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
5936 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
5937 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
5941 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
5942 bounds
->height
= f
->output_data
.x
->line_height
;
5943 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
5944 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
5951 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
5952 pix_x
= FRAME_WINDOW_WIDTH (f
);
5956 else if (pix_y
> f
->height
)
5965 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5966 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5967 can't tell the positions because W's display is not up to date,
5971 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
5974 int *frame_x
, *frame_y
;
5978 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
5979 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
5981 if (display_completed
)
5983 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
5984 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
5985 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
5991 *frame_x
+= glyph
->pixel_width
;
5999 *frame_y
= *frame_x
= 0;
6003 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
6004 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
6009 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6011 If the event is a button press, then note that we have grabbed
6015 construct_mouse_click (result
, event
, f
)
6016 struct input_event
*result
;
6017 XButtonEvent
*event
;
6020 /* Make the event type no_event; we'll change that when we decide
6022 result
->kind
= mouse_click
;
6023 result
->code
= event
->button
- Button1
;
6024 result
->timestamp
= event
->time
;
6025 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6027 | (event
->type
== ButtonRelease
6031 XSETINT (result
->x
, event
->x
);
6032 XSETINT (result
->y
, event
->y
);
6033 XSETFRAME (result
->frame_or_window
, f
);
6037 #if 0 /* This function isn't called. --gerd */
6039 /* Prepare a menu-event in *RESULT for placement in the input queue. */
6042 construct_menu_click (result
, event
, f
)
6043 struct input_event
*result
;
6044 XButtonEvent
*event
;
6047 /* Make the event type no_event; we'll change that when we decide
6049 result
->kind
= mouse_click
;
6050 result
->code
= event
->button
- Button1
;
6051 result
->timestamp
= event
->time
;
6052 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6054 | (event
->type
== ButtonRelease
6058 XSETINT (result
->x
, event
->x
);
6059 XSETINT (result
->y
, -1);
6060 XSETFRAME (result
->frame_or_window
, f
);
6066 /* Function to report a mouse movement to the mainstream Emacs code.
6067 The input handler calls this.
6069 We have received a mouse movement event, which is given in *event.
6070 If the mouse is over a different glyph than it was last time, tell
6071 the mainstream emacs code by setting mouse_moved. If not, ask for
6072 another motion event, so we can check again the next time it moves. */
6074 static XMotionEvent last_mouse_motion_event
;
6075 static Lisp_Object last_mouse_motion_frame
;
6078 note_mouse_movement (frame
, event
)
6080 XMotionEvent
*event
;
6082 last_mouse_movement_time
= event
->time
;
6083 last_mouse_motion_event
= *event
;
6084 XSETFRAME (last_mouse_motion_frame
, frame
);
6086 if (event
->window
!= FRAME_X_WINDOW (frame
))
6088 frame
->mouse_moved
= 1;
6089 last_mouse_scroll_bar
= Qnil
;
6090 note_mouse_highlight (frame
, -1, -1);
6093 /* Has the mouse moved off the glyph it was on at the last sighting? */
6094 else if (event
->x
< last_mouse_glyph
.x
6095 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
6096 || event
->y
< last_mouse_glyph
.y
6097 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
6099 frame
->mouse_moved
= 1;
6100 last_mouse_scroll_bar
= Qnil
;
6101 note_mouse_highlight (frame
, event
->x
, event
->y
);
6105 /* This is used for debugging, to turn off note_mouse_highlight. */
6107 int disable_mouse_highlight
;
6111 /************************************************************************
6113 ************************************************************************/
6115 /* Find the glyph under window-relative coordinates X/Y in window W.
6116 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6117 strings. Return in *HPOS and *VPOS the row and column number of
6118 the glyph found. Return in *AREA the glyph area containing X.
6119 Value is a pointer to the glyph found or null if X/Y is not on
6120 text, or we can't tell because W's current matrix is not up to
6123 static struct glyph
*
6124 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
)
6127 int *hpos
, *vpos
, *area
;
6129 struct glyph
*glyph
, *end
;
6130 struct glyph_row
*row
;
6131 int x0
, i
, left_area_width
;
6133 /* Find row containing Y. Give up if some row is not enabled. */
6134 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6136 row
= MATRIX_ROW (w
->current_matrix
, i
);
6137 if (!row
->enabled_p
)
6139 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6146 /* Give up if Y is not in the window. */
6147 if (i
== w
->current_matrix
->nrows
)
6150 /* Get the glyph area containing X. */
6151 if (w
->pseudo_window_p
)
6158 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6159 if (x
< left_area_width
)
6161 *area
= LEFT_MARGIN_AREA
;
6164 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6167 x0
= row
->x
+ left_area_width
;
6171 *area
= RIGHT_MARGIN_AREA
;
6172 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6176 /* Find glyph containing X. */
6177 glyph
= row
->glyphs
[*area
];
6178 end
= glyph
+ row
->used
[*area
];
6181 if (x
< x0
+ glyph
->pixel_width
)
6183 if (w
->pseudo_window_p
)
6185 else if (BUFFERP (glyph
->object
))
6189 x0
+= glyph
->pixel_width
;
6196 *hpos
= glyph
- row
->glyphs
[*area
];
6201 /* Convert frame-relative x/y to coordinates relative to window W.
6202 Takes pseudo-windows into account. */
6205 frame_to_window_pixel_xy (w
, x
, y
)
6209 if (w
->pseudo_window_p
)
6211 /* A pseudo-window is always full-width, and starts at the
6212 left edge of the frame, plus a frame border. */
6213 struct frame
*f
= XFRAME (w
->frame
);
6214 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6215 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6219 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6220 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6225 /* Take proper action when mouse has moved to the mode or top line of
6226 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6227 mode line. X is relative to the start of the text display area of
6228 W, so the width of bitmap areas and scroll bars must be subtracted
6229 to get a position relative to the start of the mode line. */
6232 note_mode_line_highlight (w
, x
, mode_line_p
)
6236 struct frame
*f
= XFRAME (w
->frame
);
6237 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6238 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6239 struct glyph_row
*row
;
6242 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6244 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
6248 struct glyph
*glyph
, *end
;
6249 Lisp_Object help
, map
;
6252 /* Find the glyph under X. */
6253 glyph
= row
->glyphs
[TEXT_AREA
];
6254 end
= glyph
+ row
->used
[TEXT_AREA
];
6255 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
6256 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
));
6258 && x
>= x0
+ glyph
->pixel_width
)
6260 x0
+= glyph
->pixel_width
;
6265 && STRINGP (glyph
->object
)
6266 && XSTRING (glyph
->object
)->intervals
6267 && glyph
->charpos
>= 0
6268 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6270 /* If we're on a string with `help-echo' text property,
6271 arrange for the help to be displayed. This is done by
6272 setting the global variable help_echo to the help string. */
6273 help
= Fget_text_property (make_number (glyph
->charpos
),
6274 Qhelp_echo
, glyph
->object
);
6278 /* Change the mouse pointer according to what is under X/Y. */
6279 map
= Fget_text_property (make_number (glyph
->charpos
),
6280 Qlocal_map
, glyph
->object
);
6281 if (!NILP (Fkeymapp (map
)))
6282 cursor
= f
->output_data
.x
->nontext_cursor
;
6286 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
6290 /* Take proper action when the mouse has moved to position X, Y on
6291 frame F as regards highlighting characters that have mouse-face
6292 properties. Also de-highlighting chars where the mouse was before.
6293 X and Y can be negative or out of range. */
6296 note_mouse_highlight (f
, x
, y
)
6300 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6305 /* When a menu is active, don't highlight because this looks odd. */
6306 #ifdef USE_X_TOOLKIT
6307 if (popup_activated ())
6311 if (disable_mouse_highlight
6312 || !f
->glyphs_initialized_p
)
6315 dpyinfo
->mouse_face_mouse_x
= x
;
6316 dpyinfo
->mouse_face_mouse_y
= y
;
6317 dpyinfo
->mouse_face_mouse_frame
= f
;
6319 if (dpyinfo
->mouse_face_defer
)
6324 dpyinfo
->mouse_face_deferred_gc
= 1;
6328 /* Which window is that in? */
6329 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
6331 /* If we were displaying active text in another window, clear that. */
6332 if (! EQ (window
, dpyinfo
->mouse_face_window
))
6333 clear_mouse_face (dpyinfo
);
6335 /* Not on a window -> return. */
6336 if (!WINDOWP (window
))
6339 /* Convert to window-relative pixel coordinates. */
6340 w
= XWINDOW (window
);
6341 frame_to_window_pixel_xy (w
, &x
, &y
);
6343 /* Handle tool-bar window differently since it doesn't display a
6345 if (EQ (window
, f
->tool_bar_window
))
6347 note_tool_bar_highlight (f
, x
, y
);
6351 if (portion
== 1 || portion
== 3)
6353 /* Mouse is on the mode or top line. */
6354 note_mode_line_highlight (w
, x
, portion
== 1);
6358 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6359 f
->output_data
.x
->text_cursor
);
6361 /* Are we in a window whose display is up to date?
6362 And verify the buffer's text has not changed. */
6363 if (/* Within text portion of the window. */
6365 && EQ (w
->window_end_valid
, w
->buffer
)
6366 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
6367 && (XFASTINT (w
->last_overlay_modified
)
6368 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
6370 int hpos
, vpos
, pos
, i
, area
;
6371 struct glyph
*glyph
;
6373 /* Find the glyph under X/Y. */
6374 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
);
6376 /* Clear mouse face if X/Y not over text. */
6378 || area
!= TEXT_AREA
6379 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6381 clear_mouse_face (dpyinfo
);
6385 pos
= glyph
->charpos
;
6386 xassert (w
->pseudo_window_p
|| BUFFERP (glyph
->object
));
6388 /* Check for mouse-face and help-echo. */
6390 Lisp_Object mouse_face
, overlay
, position
;
6391 Lisp_Object
*overlay_vec
;
6393 struct buffer
*obuf
;
6396 /* If we get an out-of-range value, return now; avoid an error. */
6397 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
6400 /* Make the window's buffer temporarily current for
6401 overlays_at and compute_char_face. */
6402 obuf
= current_buffer
;
6403 current_buffer
= XBUFFER (w
->buffer
);
6409 /* Is this char mouse-active or does it have help-echo? */
6410 XSETINT (position
, pos
);
6412 /* Put all the overlays we want in a vector in overlay_vec.
6413 Store the length in len. If there are more than 10, make
6414 enough space for all, and try again. */
6416 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6417 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6418 if (noverlays
> len
)
6421 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6422 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6425 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
6427 /* Check mouse-face highlighting. */
6428 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
6429 && vpos
>= dpyinfo
->mouse_face_beg_row
6430 && vpos
<= dpyinfo
->mouse_face_end_row
6431 && (vpos
> dpyinfo
->mouse_face_beg_row
6432 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6433 && (vpos
< dpyinfo
->mouse_face_end_row
6434 || hpos
< dpyinfo
->mouse_face_end_col
6435 || dpyinfo
->mouse_face_past_end
)))
6437 /* Clear the display of the old active region, if any. */
6438 clear_mouse_face (dpyinfo
);
6440 /* Find the highest priority overlay that has a mouse-face prop. */
6442 for (i
= 0; i
< noverlays
; i
++)
6444 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
6445 if (!NILP (mouse_face
))
6447 overlay
= overlay_vec
[i
];
6452 /* If no overlay applies, get a text property. */
6454 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
6456 /* Handle the overlay case. */
6457 if (! NILP (overlay
))
6459 /* Find the range of text around this char that
6460 should be active. */
6461 Lisp_Object before
, after
;
6464 before
= Foverlay_start (overlay
);
6465 after
= Foverlay_end (overlay
);
6466 /* Record this as the current active region. */
6467 fast_find_position (w
, XFASTINT (before
),
6468 &dpyinfo
->mouse_face_beg_col
,
6469 &dpyinfo
->mouse_face_beg_row
,
6470 &dpyinfo
->mouse_face_beg_x
,
6471 &dpyinfo
->mouse_face_beg_y
);
6472 dpyinfo
->mouse_face_past_end
6473 = !fast_find_position (w
, XFASTINT (after
),
6474 &dpyinfo
->mouse_face_end_col
,
6475 &dpyinfo
->mouse_face_end_row
,
6476 &dpyinfo
->mouse_face_end_x
,
6477 &dpyinfo
->mouse_face_end_y
);
6478 dpyinfo
->mouse_face_window
= window
;
6479 dpyinfo
->mouse_face_face_id
6480 = face_at_buffer_position (w
, pos
, 0, 0,
6481 &ignore
, pos
+ 1, 1);
6483 /* Display it as active. */
6484 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6486 /* Handle the text property case. */
6487 else if (! NILP (mouse_face
))
6489 /* Find the range of text around this char that
6490 should be active. */
6491 Lisp_Object before
, after
, beginning
, end
;
6494 beginning
= Fmarker_position (w
->start
);
6495 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
6496 - XFASTINT (w
->window_end_pos
)));
6498 = Fprevious_single_property_change (make_number (pos
+ 1),
6500 w
->buffer
, beginning
);
6502 = Fnext_single_property_change (position
, Qmouse_face
,
6504 /* Record this as the current active region. */
6505 fast_find_position (w
, XFASTINT (before
),
6506 &dpyinfo
->mouse_face_beg_col
,
6507 &dpyinfo
->mouse_face_beg_row
,
6508 &dpyinfo
->mouse_face_beg_x
,
6509 &dpyinfo
->mouse_face_beg_y
);
6510 dpyinfo
->mouse_face_past_end
6511 = !fast_find_position (w
, XFASTINT (after
),
6512 &dpyinfo
->mouse_face_end_col
,
6513 &dpyinfo
->mouse_face_end_row
,
6514 &dpyinfo
->mouse_face_end_x
,
6515 &dpyinfo
->mouse_face_end_y
);
6516 dpyinfo
->mouse_face_window
= window
;
6517 dpyinfo
->mouse_face_face_id
6518 = face_at_buffer_position (w
, pos
, 0, 0,
6519 &ignore
, pos
+ 1, 1);
6521 /* Display it as active. */
6522 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6526 /* Look for a `help-echo' property. */
6530 /* Check overlays first. */
6532 for (i
= 0; i
< noverlays
&& !STRINGP (help
); ++i
)
6533 help
= Foverlay_get (overlay_vec
[i
], Qhelp_echo
);
6535 /* Try text properties. */
6537 && ((STRINGP (glyph
->object
)
6538 && glyph
->charpos
>= 0
6539 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6540 || (BUFFERP (glyph
->object
)
6541 && glyph
->charpos
>= BEGV
6542 && glyph
->charpos
< ZV
)))
6543 help
= Fget_text_property (make_number (glyph
->charpos
),
6544 Qhelp_echo
, glyph
->object
);
6552 current_buffer
= obuf
;
6558 redo_mouse_highlight ()
6560 if (!NILP (last_mouse_motion_frame
)
6561 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
6562 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
6563 last_mouse_motion_event
.x
,
6564 last_mouse_motion_event
.y
);
6569 /***********************************************************************
6571 ***********************************************************************/
6573 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
6574 struct glyph
**, int *, int *, int *));
6576 /* Tool-bar item index of the item on which a mouse button was pressed
6579 static int last_tool_bar_item
;
6582 /* Get information about the tool-bar item at position X/Y on frame F.
6583 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6584 the current matrix of the tool-bar window of F, or NULL if not
6585 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6586 item in F->current_tool_bar_items. Value is
6588 -1 if X/Y is not on a tool-bar item
6589 0 if X/Y is on the same item that was highlighted before.
6593 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
6596 struct glyph
**glyph
;
6597 int *hpos
, *vpos
, *prop_idx
;
6599 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6600 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6603 /* Find the glyph under X/Y. */
6604 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
);
6608 /* Get the start of this tool-bar item's properties in
6609 f->current_tool_bar_items. */
6610 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
6613 /* Is mouse on the highlighted item? */
6614 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
6615 && *vpos
>= dpyinfo
->mouse_face_beg_row
6616 && *vpos
<= dpyinfo
->mouse_face_end_row
6617 && (*vpos
> dpyinfo
->mouse_face_beg_row
6618 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
6619 && (*vpos
< dpyinfo
->mouse_face_end_row
6620 || *hpos
< dpyinfo
->mouse_face_end_col
6621 || dpyinfo
->mouse_face_past_end
))
6628 /* Handle mouse button event on the tool-bar of frame F, at
6629 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6633 x_handle_tool_bar_click (f
, button_event
)
6635 XButtonEvent
*button_event
;
6637 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6638 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6639 int hpos
, vpos
, prop_idx
;
6640 struct glyph
*glyph
;
6641 Lisp_Object enabled_p
;
6642 int x
= button_event
->x
;
6643 int y
= button_event
->y
;
6645 /* If not on the highlighted tool-bar item, return. */
6646 frame_to_window_pixel_xy (w
, &x
, &y
);
6647 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
6650 /* If item is disabled, do nothing. */
6651 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6652 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6653 if (NILP (enabled_p
))
6656 if (button_event
->type
== ButtonPress
)
6658 /* Show item in pressed state. */
6659 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
6660 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
6661 last_tool_bar_item
= prop_idx
;
6665 Lisp_Object key
, frame
;
6666 struct input_event event
;
6668 /* Show item in released state. */
6669 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
6670 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
6672 key
= (XVECTOR (f
->current_tool_bar_items
)
6673 ->contents
[prop_idx
+ TOOL_BAR_ITEM_KEY
]);
6675 XSETFRAME (frame
, f
);
6676 event
.kind
= TOOL_BAR_EVENT
;
6677 event
.frame_or_window
= Fcons (frame
, Fcons (Qtool_bar
, Qnil
));
6678 kbd_buffer_store_event (&event
);
6680 event
.kind
= TOOL_BAR_EVENT
;
6681 event
.frame_or_window
= Fcons (frame
, key
);
6682 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6683 button_event
->state
);
6684 kbd_buffer_store_event (&event
);
6685 last_tool_bar_item
= -1;
6690 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6691 tool-bar window-relative coordinates X/Y. Called from
6692 note_mouse_highlight. */
6695 note_tool_bar_highlight (f
, x
, y
)
6699 Lisp_Object window
= f
->tool_bar_window
;
6700 struct window
*w
= XWINDOW (window
);
6701 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6703 struct glyph
*glyph
;
6704 struct glyph_row
*row
;
6706 Lisp_Object enabled_p
;
6708 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
6709 int mouse_down_p
, rc
;
6711 /* Function note_mouse_highlight is called with negative x(y
6712 values when mouse moves outside of the frame. */
6713 if (x
<= 0 || y
<= 0)
6715 clear_mouse_face (dpyinfo
);
6719 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
6722 /* Not on tool-bar item. */
6723 clear_mouse_face (dpyinfo
);
6727 /* On same tool-bar item as before. */
6730 clear_mouse_face (dpyinfo
);
6732 /* Mouse is down, but on different tool-bar item? */
6733 mouse_down_p
= (dpyinfo
->grabbed
6734 && f
== last_mouse_frame
6735 && FRAME_LIVE_P (f
));
6737 && last_tool_bar_item
!= prop_idx
)
6740 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
6741 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
6743 /* If tool-bar item is not enabled, don't highlight it. */
6744 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6745 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6746 if (!NILP (enabled_p
))
6748 /* Compute the x-position of the glyph. In front and past the
6749 image is a space. We include this is the highlighted area. */
6750 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6751 for (i
= x
= 0; i
< hpos
; ++i
)
6752 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
6754 /* Record this as the current active region. */
6755 dpyinfo
->mouse_face_beg_col
= hpos
;
6756 dpyinfo
->mouse_face_beg_row
= vpos
;
6757 dpyinfo
->mouse_face_beg_x
= x
;
6758 dpyinfo
->mouse_face_beg_y
= row
->y
;
6759 dpyinfo
->mouse_face_past_end
= 0;
6761 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
6762 dpyinfo
->mouse_face_end_row
= vpos
;
6763 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
6764 dpyinfo
->mouse_face_end_y
= row
->y
;
6765 dpyinfo
->mouse_face_window
= window
;
6766 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
6768 /* Display it as active. */
6769 show_mouse_face (dpyinfo
, draw
);
6770 dpyinfo
->mouse_face_image_state
= draw
;
6775 /* Set help_echo to a help string.to display for this tool-bar item.
6776 XTread_socket does the rest. */
6777 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6778 ->contents
[prop_idx
+ TOOL_BAR_ITEM_HELP
]);
6779 if (!STRINGP (help_echo
))
6780 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6781 ->contents
[prop_idx
+ TOOL_BAR_ITEM_CAPTION
]);
6786 /* Find the glyph matrix position of buffer position POS in window W.
6787 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6788 current glyphs must be up to date. If POS is above window start
6789 return (0, 0, 0, 0). If POS is after end of W, return end of
6793 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
)
6796 int *hpos
, *vpos
, *x
, *y
;
6800 int maybe_next_line_p
= 0;
6801 int line_start_position
;
6802 int yb
= window_text_bottom_y (w
);
6803 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0);
6804 struct glyph_row
*best_row
= row
;
6805 int row_vpos
= 0, best_row_vpos
= 0;
6810 if (row
->used
[TEXT_AREA
])
6811 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
6813 line_start_position
= 0;
6815 if (line_start_position
> pos
)
6817 /* If the position sought is the end of the buffer,
6818 don't include the blank lines at the bottom of the window. */
6819 else if (line_start_position
== pos
6820 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
6822 maybe_next_line_p
= 1;
6825 else if (line_start_position
> 0)
6828 best_row_vpos
= row_vpos
;
6831 if (row
->y
+ row
->height
>= yb
)
6838 /* Find the right column within BEST_ROW. */
6840 current_x
= best_row
->x
;
6841 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
6843 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
6846 charpos
= glyph
->charpos
;
6850 *vpos
= best_row_vpos
;
6855 else if (charpos
> pos
)
6857 else if (charpos
> 0)
6860 current_x
+= glyph
->pixel_width
;
6863 /* If we're looking for the end of the buffer,
6864 and we didn't find it in the line we scanned,
6865 use the start of the following line. */
6866 if (maybe_next_line_p
)
6871 current_x
= best_row
->x
;
6874 *vpos
= best_row_vpos
;
6875 *hpos
= lastcol
+ 1;
6882 /* Display the active region described by mouse_face_*
6883 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6886 show_mouse_face (dpyinfo
, draw
)
6887 struct x_display_info
*dpyinfo
;
6888 enum draw_glyphs_face draw
;
6890 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
6891 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6893 int cursor_off_p
= 0;
6894 struct cursor_pos saved_cursor
;
6896 saved_cursor
= output_cursor
;
6898 /* If window is in the process of being destroyed, don't bother
6900 if (w
->current_matrix
== NULL
)
6903 /* Recognize when we are called to operate on rows that don't exist
6904 anymore. This can happen when a window is split. */
6905 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
6908 set_output_cursor (&w
->phys_cursor
);
6910 /* Note that mouse_face_beg_row etc. are window relative. */
6911 for (i
= dpyinfo
->mouse_face_beg_row
;
6912 i
<= dpyinfo
->mouse_face_end_row
;
6915 int start_hpos
, end_hpos
, start_x
;
6916 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
6918 /* Don't do anything if row doesn't have valid contents. */
6919 if (!row
->enabled_p
)
6922 /* For all but the first row, the highlight starts at column 0. */
6923 if (i
== dpyinfo
->mouse_face_beg_row
)
6925 start_hpos
= dpyinfo
->mouse_face_beg_col
;
6926 start_x
= dpyinfo
->mouse_face_beg_x
;
6934 if (i
== dpyinfo
->mouse_face_end_row
)
6935 end_hpos
= dpyinfo
->mouse_face_end_col
;
6937 end_hpos
= row
->used
[TEXT_AREA
];
6939 /* If the cursor's in the text we are about to rewrite, turn the
6941 if (!w
->pseudo_window_p
6942 && i
== output_cursor
.vpos
6943 && output_cursor
.hpos
>= start_hpos
- 1
6944 && output_cursor
.hpos
<= end_hpos
)
6946 x_update_window_cursor (w
, 0);
6950 if (end_hpos
> start_hpos
)
6951 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
6952 start_hpos
, end_hpos
, draw
, NULL
, NULL
, 0);
6955 /* If we turned the cursor off, turn it back on. */
6957 x_display_cursor (w
, 1,
6958 output_cursor
.hpos
, output_cursor
.vpos
,
6959 output_cursor
.x
, output_cursor
.y
);
6961 output_cursor
= saved_cursor
;
6965 /* Change the mouse cursor. */
6966 if (draw
== DRAW_NORMAL_TEXT
)
6967 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6968 f
->output_data
.x
->text_cursor
);
6969 else if (draw
== DRAW_MOUSE_FACE
)
6970 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6971 f
->output_data
.x
->cross_cursor
);
6973 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6974 f
->output_data
.x
->nontext_cursor
);
6977 /* Clear out the mouse-highlighted active region.
6978 Redraw it un-highlighted first. */
6981 clear_mouse_face (dpyinfo
)
6982 struct x_display_info
*dpyinfo
;
6987 if (! NILP (dpyinfo
->mouse_face_window
))
6988 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
6990 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6991 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6992 dpyinfo
->mouse_face_window
= Qnil
;
6995 /* Just discard the mouse face information for frame F, if any.
6996 This is used when the size of F is changed. */
6999 cancel_mouse_face (f
)
7003 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7005 window
= dpyinfo
->mouse_face_window
;
7006 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
7008 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7009 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7010 dpyinfo
->mouse_face_window
= Qnil
;
7014 static struct scroll_bar
*x_window_to_scroll_bar ();
7015 static void x_scroll_bar_report_motion ();
7017 /* Return the current position of the mouse.
7018 *fp should be a frame which indicates which display to ask about.
7020 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7021 and *part to the frame, window, and scroll bar part that the mouse
7022 is over. Set *x and *y to the portion and whole of the mouse's
7023 position on the scroll bar.
7025 If the mouse movement started elsewhere, set *fp to the frame the
7026 mouse is on, *bar_window to nil, and *x and *y to the character cell
7029 Set *time to the server time-stamp for the time at which the mouse
7030 was at this position.
7032 Don't store anything if we don't have a valid set of values to report.
7034 This clears the mouse_moved flag, so we can wait for the next mouse
7038 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
7041 Lisp_Object
*bar_window
;
7042 enum scroll_bar_part
*part
;
7044 unsigned long *time
;
7050 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
7051 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
7057 Window dummy_window
;
7060 Lisp_Object frame
, tail
;
7062 /* Clear the mouse-moved flag for every frame on this display. */
7063 FOR_EACH_FRAME (tail
, frame
)
7064 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
7065 XFRAME (frame
)->mouse_moved
= 0;
7067 last_mouse_scroll_bar
= Qnil
;
7069 /* Figure out which root window we're on. */
7070 XQueryPointer (FRAME_X_DISPLAY (*fp
),
7071 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
7073 /* The root window which contains the pointer. */
7076 /* Trash which we can't trust if the pointer is on
7077 a different screen. */
7080 /* The position on that root window. */
7083 /* More trash we can't trust. */
7086 /* Modifier keys and pointer buttons, about which
7088 (unsigned int *) &dummy
);
7090 /* Now we have a position on the root; find the innermost window
7091 containing the pointer. */
7095 int parent_x
= 0, parent_y
= 0;
7100 /* XTranslateCoordinates can get errors if the window
7101 structure is changing at the same time this function
7102 is running. So at least we must not crash from them. */
7104 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
7106 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
7107 && FRAME_LIVE_P (last_mouse_frame
))
7109 /* If mouse was grabbed on a frame, give coords for that frame
7110 even if the mouse is now outside it. */
7111 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7113 /* From-window, to-window. */
7114 root
, FRAME_X_WINDOW (last_mouse_frame
),
7116 /* From-position, to-position. */
7117 root_x
, root_y
, &win_x
, &win_y
,
7121 f1
= last_mouse_frame
;
7127 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7129 /* From-window, to-window. */
7132 /* From-position, to-position. */
7133 root_x
, root_y
, &win_x
, &win_y
,
7138 if (child
== None
|| child
== win
)
7146 /* Now we know that:
7147 win is the innermost window containing the pointer
7148 (XTC says it has no child containing the pointer),
7149 win_x and win_y are the pointer's position in it
7150 (XTC did this the last time through), and
7151 parent_x and parent_y are the pointer's position in win's parent.
7152 (They are what win_x and win_y were when win was child.
7153 If win is the root window, it has no parent, and
7154 parent_{x,y} are invalid, but that's okay, because we'll
7155 never use them in that case.) */
7157 /* Is win one of our frames? */
7158 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
7161 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
7164 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
7166 /* If not, is it one of our scroll bars? */
7169 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
7173 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7179 if (f1
== 0 && insist
> 0)
7180 f1
= SELECTED_FRAME ();
7184 /* Ok, we found a frame. Store all the values.
7185 last_mouse_glyph is a rectangle used to reduce the
7186 generation of mouse events. To not miss any motion
7187 events, we must divide the frame into rectangles of the
7188 size of the smallest character that could be displayed
7189 on it, i.e. into the same rectangles that matrices on
7190 the frame are divided into. */
7192 #if OLD_REDISPLAY_CODE
7193 int ignore1
, ignore2
;
7194 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
7196 FRAME_X_DISPLAY_INFO (f1
)->grabbed
7200 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
7201 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
7205 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7206 round down even for negative values. */
7212 last_mouse_glyph
.width
= width
;
7213 last_mouse_glyph
.height
= height
;
7214 last_mouse_glyph
.x
= (x
+ width
- 1) / width
* width
;
7215 last_mouse_glyph
.y
= (y
+ height
- 1) / height
* height
;
7222 XSETINT (*x
, win_x
);
7223 XSETINT (*y
, win_y
);
7224 *time
= last_mouse_movement_time
;
7233 #ifdef USE_X_TOOLKIT
7235 /* Atimer callback function for TIMER. Called every 0.1s to process
7236 Xt timeouts, if needed. We must avoid calling XtAppPending as
7237 much as possible because that function does an implicit XFlush
7238 that slows us down. */
7241 x_process_timeouts (timer
)
7242 struct atimer
*timer
;
7244 if (toolkit_scroll_bar_interaction
|| popup_activated_flag
)
7247 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
7248 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
7253 #endif /* USE_X_TOOLKIT */
7256 /* Scroll bar support. */
7258 /* Given an X window ID, find the struct scroll_bar which manages it.
7259 This can be called in GC, so we have to make sure to strip off mark
7262 static struct scroll_bar
*
7263 x_window_to_scroll_bar (window_id
)
7268 for (tail
= Vframe_list
;
7269 XGCTYPE (tail
) == Lisp_Cons
;
7272 Lisp_Object frame
, bar
, condemned
;
7274 frame
= XCAR (tail
);
7275 /* All elements of Vframe_list should be frames. */
7276 if (! GC_FRAMEP (frame
))
7279 /* Scan this frame's scroll bar list for a scroll bar with the
7281 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
7282 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
7283 /* This trick allows us to search both the ordinary and
7284 condemned scroll bar lists with one loop. */
7285 ! GC_NILP (bar
) || (bar
= condemned
,
7288 bar
= XSCROLL_BAR (bar
)->next
)
7289 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
7290 return XSCROLL_BAR (bar
);
7298 /************************************************************************
7300 ************************************************************************/
7302 #if USE_TOOLKIT_SCROLL_BARS
7304 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
7305 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
7306 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
7307 struct scroll_bar
*));
7308 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
7312 /* Id of action hook installed for scroll bars. */
7314 static XtActionHookId action_hook_id
;
7316 /* Lisp window being scrolled. Set when starting to interact with
7317 a toolkit scroll bar, reset to nil when ending the interaction. */
7319 static Lisp_Object window_being_scrolled
;
7321 /* Last scroll bar part sent in xm_scroll_callback. */
7323 static int last_scroll_bar_part
;
7325 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7326 that movements of 1/20 of the screen size are mapped to up/down. */
7328 static Boolean xaw3d_arrow_scroll
;
7330 /* Whether the drag scrolling maintains the mouse at the top of the
7331 thumb. If not, resizing the thumb needs to be done more carefully
7332 to avoid jerkyness. */
7334 static Boolean xaw3d_pick_top
;
7337 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7338 bars are used.. The hook is responsible for detecting when
7339 the user ends an interaction with the scroll bar, and generates
7340 a `end-scroll' scroll_bar_click' event if so. */
7343 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
7346 XtPointer client_data
;
7350 Cardinal
*num_params
;
7356 scroll_bar_p
= XmIsScrollBar (widget
);
7357 end_action
= "Release";
7358 #else /* !USE_MOTIF i.e. use Xaw */
7359 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
7360 end_action
= "EndScroll";
7361 #endif /* USE_MOTIF */
7364 && strcmp (action_name
, end_action
) == 0
7365 && WINDOWP (window_being_scrolled
))
7369 x_send_scroll_bar_event (window_being_scrolled
,
7370 scroll_bar_end_scroll
, 0, 0);
7371 w
= XWINDOW (window_being_scrolled
);
7372 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
7373 window_being_scrolled
= Qnil
;
7374 last_scroll_bar_part
= -1;
7376 /* Xt timeouts no longer needed. */
7377 toolkit_scroll_bar_interaction
= 0;
7382 /* Send a client message with message type Xatom_Scrollbar for a
7383 scroll action to the frame of WINDOW. PART is a value identifying
7384 the part of the scroll bar that was clicked on. PORTION is the
7385 amount to scroll of a whole of WHOLE. */
7388 x_send_scroll_bar_event (window
, part
, portion
, whole
)
7390 int part
, portion
, whole
;
7393 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
7394 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7396 /* Construct a ClientMessage event to send to the frame. */
7397 ev
->type
= ClientMessage
;
7398 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
7399 ev
->display
= FRAME_X_DISPLAY (f
);
7400 ev
->window
= FRAME_X_WINDOW (f
);
7402 ev
->data
.l
[0] = (long) window
;
7403 ev
->data
.l
[1] = (long) part
;
7404 ev
->data
.l
[2] = (long) 0;
7405 ev
->data
.l
[3] = (long) portion
;
7406 ev
->data
.l
[4] = (long) whole
;
7408 /* Make Xt timeouts work while the scroll bar is active. */
7409 toolkit_scroll_bar_interaction
= 1;
7411 /* Setting the event mask to zero means that the message will
7412 be sent to the client that created the window, and if that
7413 window no longer exists, no event will be sent. */
7415 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
7420 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7424 x_scroll_bar_to_input_event (event
, ievent
)
7426 struct input_event
*ievent
;
7428 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
7429 Lisp_Object window
= (Lisp_Object
) ev
->data
.l
[0];
7430 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7432 ievent
->kind
= scroll_bar_click
;
7433 ievent
->frame_or_window
= window
;
7434 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
7435 ievent
->part
= ev
->data
.l
[1];
7436 ievent
->code
= ev
->data
.l
[2];
7437 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
7438 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
7439 ievent
->modifiers
= 0;
7445 /* Minimum and maximum values used for Motif scroll bars. */
7448 #define XM_SB_MAX 10000000
7449 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7452 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7453 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7454 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7457 xm_scroll_callback (widget
, client_data
, call_data
)
7459 XtPointer client_data
, call_data
;
7461 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7462 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
7464 int part
= -1, whole
= 0, portion
= 0;
7468 case XmCR_DECREMENT
:
7469 bar
->dragging
= Qnil
;
7470 part
= scroll_bar_up_arrow
;
7473 case XmCR_INCREMENT
:
7474 bar
->dragging
= Qnil
;
7475 part
= scroll_bar_down_arrow
;
7478 case XmCR_PAGE_DECREMENT
:
7479 bar
->dragging
= Qnil
;
7480 part
= scroll_bar_above_handle
;
7483 case XmCR_PAGE_INCREMENT
:
7484 bar
->dragging
= Qnil
;
7485 part
= scroll_bar_below_handle
;
7489 bar
->dragging
= Qnil
;
7490 part
= scroll_bar_to_top
;
7493 case XmCR_TO_BOTTOM
:
7494 bar
->dragging
= Qnil
;
7495 part
= scroll_bar_to_bottom
;
7501 int dragging_down_p
= (INTEGERP (bar
->dragging
)
7502 && XINT (bar
->dragging
) <= cs
->value
);
7504 /* Get the slider size. */
7506 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
7509 /* At the max position of the scroll bar, do a line-wise
7510 movement. Without doing anything, the LessTif scroll bar
7511 calls us with the same cs->value again and again. If we
7512 want to make sure that we can reach the end of the buffer,
7513 we have to do something.
7515 Implementation note: setting bar->dragging always to
7516 cs->value gives a smoother movement at the max position.
7517 Setting it to nil when doing line-wise movement gives
7518 a better slider behavior. */
7520 if (cs
->value
+ slider_size
== XM_SB_MAX
7522 && last_scroll_bar_part
== scroll_bar_down_arrow
))
7524 part
= scroll_bar_down_arrow
;
7525 bar
->dragging
= Qnil
;
7529 whole
= XM_SB_RANGE
;
7530 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
7531 part
= scroll_bar_handle
;
7532 bar
->dragging
= make_number (cs
->value
);
7537 case XmCR_VALUE_CHANGED
:
7543 window_being_scrolled
= bar
->window
;
7544 last_scroll_bar_part
= part
;
7545 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7550 #else /* !USE_MOTIF, i.e. Xaw. */
7553 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7554 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7555 scroll bar struct. CALL_DATA is a pointer to a float saying where
7559 xaw_jump_callback (widget
, client_data
, call_data
)
7561 XtPointer client_data
, call_data
;
7563 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7564 float top
= *(float *) call_data
;
7566 int whole
, portion
, height
;
7569 /* Get the size of the thumb, a value between 0 and 1. */
7571 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
7575 portion
= shown
< 1 ? top
* whole
: 0;
7577 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
7578 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7579 the bottom, so we force the scrolling whenever we see that we're
7580 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7581 we try to ensure that we always stay two pixels away from the
7583 part
= scroll_bar_down_arrow
;
7585 part
= scroll_bar_handle
;
7587 window_being_scrolled
= bar
->window
;
7588 bar
->dragging
= make_number (portion
);
7589 last_scroll_bar_part
= part
;
7590 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7594 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7595 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7596 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7597 the scroll bar. CALL_DATA is an integer specifying the action that
7598 has taken place. It's magnitude is in the range 0..height of the
7599 scroll bar. Negative values mean scroll towards buffer start.
7600 Values < height of scroll bar mean line-wise movement. */
7603 xaw_scroll_callback (widget
, client_data
, call_data
)
7605 XtPointer client_data
, call_data
;
7607 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7608 int position
= (int) call_data
;
7612 /* Get the height of the scroll bar. */
7614 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
7617 if (abs (position
) >= height
)
7618 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
7620 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7621 it maps line-movement to call_data = max(5, height/20). */
7622 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
7623 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
7625 part
= scroll_bar_move_ratio
;
7627 window_being_scrolled
= bar
->window
;
7628 bar
->dragging
= Qnil
;
7629 last_scroll_bar_part
= part
;
7630 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
7634 #endif /* not USE_MOTIF */
7637 /* Create the widget for scroll bar BAR on frame F. Record the widget
7638 and X window of the scroll bar in BAR. */
7641 x_create_toolkit_scroll_bar (f
, bar
)
7643 struct scroll_bar
*bar
;
7649 char *scroll_bar_name
= "verticalScrollBar";
7650 unsigned long pixel
;
7655 /* LessTif 0.85, problems:
7657 1. When the mouse if over the scroll bar, the scroll bar will
7658 get keyboard events. I didn't find a way to turn this off.
7660 2. Do we have to explicitly set the cursor to get an arrow
7661 cursor (see below)? */
7663 /* Set resources. Create the widget. */
7664 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7665 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
7666 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
7667 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
7668 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
7669 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
7670 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
7672 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7675 XtSetArg (av
[ac
], XmNforeground
, pixel
);
7679 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7682 XtSetArg (av
[ac
], XmNbackground
, pixel
);
7686 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
7687 scroll_bar_name
, av
, ac
);
7689 /* Add one callback for everything that can happen. */
7690 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
7692 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
7694 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
7696 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
7698 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
7700 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
7702 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
7705 /* Realize the widget. Only after that is the X window created. */
7706 XtRealizeWidget (widget
);
7708 /* Set the cursor to an arrow. I didn't find a resource to do that.
7709 And I'm wondering why it hasn't an arrow cursor by default. */
7710 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
7711 f
->output_data
.x
->nontext_cursor
);
7713 #else /* !USE_MOTIF i.e. use Xaw */
7715 /* Set resources. Create the widget. The background of the
7716 Xaw3d scroll bar widget is a little bit light for my taste.
7717 We don't alter it here to let users change it according
7718 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7719 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7720 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
7721 /* For smoother scrolling with Xaw3d -sm */
7722 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7723 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7725 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7728 XtSetArg (av
[ac
], XtNforeground
, pixel
);
7732 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7735 XtSetArg (av
[ac
], XtNbackground
, pixel
);
7739 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
7740 f
->output_data
.x
->edit_widget
, av
, ac
);
7744 char *val
= initial
;
7745 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
7746 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
7748 { /* ARROW_SCROLL */
7749 xaw3d_arrow_scroll
= True
;
7750 /* Isn't that just a personal preference ? -sm */
7751 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
7755 /* Define callbacks. */
7756 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
7757 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
7760 /* Realize the widget. Only after that is the X window created. */
7761 XtRealizeWidget (widget
);
7763 #endif /* !USE_MOTIF */
7765 /* Install an action hook that let's us detect when the user
7766 finishes interacting with a scroll bar. */
7767 if (action_hook_id
== 0)
7768 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
7770 /* Remember X window and widget in the scroll bar vector. */
7771 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
7772 xwindow
= XtWindow (widget
);
7773 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
7779 /* Set the thumb size and position of scroll bar BAR. We are currently
7780 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7783 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
7784 struct scroll_bar
*bar
;
7785 int portion
, position
, whole
;
7788 Widget widget
= SCROLL_BAR_X_WIDGET (bar
);
7794 top
= (float) position
/ whole
;
7795 shown
= (float) portion
/ whole
;
7803 Boolean arrow1_selected
, arrow2_selected
;
7804 unsigned char flags
;
7805 XmScrollBarWidget sb
;
7807 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7808 is the scroll bar's maximum and MIN is the scroll bar's minimum
7810 size
= shown
* XM_SB_RANGE
;
7811 size
= min (size
, XM_SB_RANGE
);
7812 size
= max (size
, 1);
7814 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7815 value
= top
* XM_SB_RANGE
;
7816 value
= min (value
, XM_SB_MAX
- size
);
7817 value
= max (value
, XM_SB_MIN
);
7819 /* LessTif: Calling XmScrollBarSetValues after an increment or
7820 decrement turns off auto-repeat LessTif-internally. This can
7821 be seen in ScrollBar.c which resets Arrow1Selected and
7822 Arrow2Selected. It also sets internal flags so that LessTif
7823 believes the mouse is in the slider. We either have to change
7824 our code, or work around that by accessing private data. */
7826 sb
= (XmScrollBarWidget
) widget
;
7827 arrow1_selected
= sb
->scrollBar
.arrow1_selected
;
7828 arrow2_selected
= sb
->scrollBar
.arrow2_selected
;
7829 flags
= sb
->scrollBar
.flags
;
7831 if (NILP (bar
->dragging
))
7832 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
7833 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7834 /* This has the negative side effect that the slider value is
7835 not what it would be if we scrolled here using line-wise or
7836 page-wise movement. */
7837 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
7840 /* If currently dragging, only update the slider size.
7841 This reduces flicker effects. */
7842 int old_value
, old_size
, increment
, page_increment
;
7844 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
7845 &increment
, &page_increment
);
7846 XmScrollBarSetValues (widget
, old_value
,
7847 min (size
, XM_SB_RANGE
- old_value
),
7851 sb
->scrollBar
.arrow1_selected
= arrow1_selected
;
7852 sb
->scrollBar
.arrow2_selected
= arrow2_selected
;
7853 sb
->scrollBar
.flags
= flags
;
7855 #else /* !USE_MOTIF i.e. use Xaw */
7857 float old_top
, old_shown
;
7859 XtVaGetValues (widget
,
7860 XtNtopOfThumb
, &old_top
,
7861 XtNshown
, &old_shown
,
7865 /* Massage the top+shown values. */
7866 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
7867 top
= max (0, min (1, top
));
7870 /* Keep two pixels available for moving the thumb down. */
7871 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
7873 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7874 check that your system's configuration file contains a define
7875 for `NARROWPROTO'. See s/freebsd.h for an example. */
7876 if (top
!= old_top
|| shown
!= old_shown
)
7878 if (NILP (bar
->dragging
))
7879 XawScrollbarSetThumb (widget
, top
, shown
);
7883 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
7886 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7887 if (xaw3d_arrow_scroll
)
7889 /* Xaw3d stupidly ignores resize requests while dragging
7890 so we have to make it believe it's not in dragging mode. */
7891 scroll_mode
= sb
->scrollbar
.scroll_mode
;
7892 if (scroll_mode
== 2)
7893 sb
->scrollbar
.scroll_mode
= 0;
7896 /* Try to make the scrolling a tad smoother. */
7897 if (!xaw3d_pick_top
)
7898 shown
= min (shown
, old_shown
);
7900 XawScrollbarSetThumb (widget
, top
, shown
);
7903 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
7904 sb
->scrollbar
.scroll_mode
= scroll_mode
;
7909 #endif /* !USE_MOTIF */
7914 #endif /* USE_TOOLKIT_SCROLL_BARS */
7918 /************************************************************************
7919 Scroll bars, general
7920 ************************************************************************/
7922 /* Create a scroll bar and return the scroll bar vector for it. W is
7923 the Emacs window on which to create the scroll bar. TOP, LEFT,
7924 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7927 static struct scroll_bar
*
7928 x_scroll_bar_create (w
, top
, left
, width
, height
)
7930 int top
, left
, width
, height
;
7932 struct frame
*f
= XFRAME (w
->frame
);
7933 struct scroll_bar
*bar
7934 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
7938 #if USE_TOOLKIT_SCROLL_BARS
7939 x_create_toolkit_scroll_bar (f
, bar
);
7940 #else /* not USE_TOOLKIT_SCROLL_BARS */
7942 XSetWindowAttributes a
;
7946 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7947 if (a
.background_pixel
== -1)
7948 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
7950 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
7951 | ButtonMotionMask
| PointerMotionHintMask
7953 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
7955 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
7957 /* Clear the area of W that will serve as a scroll bar. This is
7958 for the case that a window has been split horizontally. In
7959 this case, no clear_frame is generated to reduce flickering. */
7960 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7962 window_box_height (w
), False
);
7964 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7965 /* Position and size of scroll bar. */
7966 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7968 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7970 /* Border width, depth, class, and visual. */
7977 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
7979 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7981 XSETWINDOW (bar
->window
, w
);
7982 XSETINT (bar
->top
, top
);
7983 XSETINT (bar
->left
, left
);
7984 XSETINT (bar
->width
, width
);
7985 XSETINT (bar
->height
, height
);
7986 XSETINT (bar
->start
, 0);
7987 XSETINT (bar
->end
, 0);
7988 bar
->dragging
= Qnil
;
7990 /* Add bar to its frame's list of scroll bars. */
7991 bar
->next
= FRAME_SCROLL_BARS (f
);
7993 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
7994 if (!NILP (bar
->next
))
7995 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
7997 /* Map the window/widget. */
7998 #if USE_TOOLKIT_SCROLL_BARS
7999 XtMapWidget (SCROLL_BAR_X_WIDGET (bar
));
8000 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
8001 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8003 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8005 #else /* not USE_TOOLKIT_SCROLL_BARS */
8006 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
8007 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8014 /* Draw BAR's handle in the proper position.
8016 If the handle is already drawn from START to END, don't bother
8017 redrawing it, unless REBUILD is non-zero; in that case, always
8018 redraw it. (REBUILD is handy for drawing the handle after expose
8021 Normally, we want to constrain the start and end of the handle to
8022 fit inside its rectangle, but if the user is dragging the scroll
8023 bar handle, we want to let them drag it down all the way, so that
8024 the bar's top is as far down as it goes; otherwise, there's no way
8025 to move to the very end of the buffer. */
8027 #ifndef USE_TOOLKIT_SCROLL_BARS
8030 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
8031 struct scroll_bar
*bar
;
8035 int dragging
= ! NILP (bar
->dragging
);
8036 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8037 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8038 GC gc
= f
->output_data
.x
->normal_gc
;
8040 /* If the display is already accurate, do nothing. */
8042 && start
== XINT (bar
->start
)
8043 && end
== XINT (bar
->end
))
8049 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
8050 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8051 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8053 /* Make sure the values are reasonable, and try to preserve
8054 the distance between start and end. */
8056 int length
= end
- start
;
8060 else if (start
> top_range
)
8062 end
= start
+ length
;
8066 else if (end
> top_range
&& ! dragging
)
8070 /* Store the adjusted setting in the scroll bar. */
8071 XSETINT (bar
->start
, start
);
8072 XSETINT (bar
->end
, end
);
8074 /* Clip the end position, just for display. */
8075 if (end
> top_range
)
8078 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8079 below top positions, to make sure the handle is always at least
8080 that many pixels tall. */
8081 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
8083 /* Draw the empty space above the handle. Note that we can't clear
8084 zero-height areas; that means "clear to end of window." */
8086 XClearArea (FRAME_X_DISPLAY (f
), w
,
8088 /* x, y, width, height, and exposures. */
8089 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8090 VERTICAL_SCROLL_BAR_TOP_BORDER
,
8091 inside_width
, start
,
8094 /* Change to proper foreground color if one is specified. */
8095 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8096 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8097 f
->output_data
.x
->scroll_bar_foreground_pixel
);
8099 /* Draw the handle itself. */
8100 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8102 /* x, y, width, height */
8103 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8104 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
8105 inside_width
, end
- start
);
8107 /* Restore the foreground color of the GC if we changed it above. */
8108 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8109 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8110 f
->output_data
.x
->foreground_pixel
);
8112 /* Draw the empty space below the handle. Note that we can't
8113 clear zero-height areas; that means "clear to end of window." */
8114 if (end
< inside_height
)
8115 XClearArea (FRAME_X_DISPLAY (f
), w
,
8117 /* x, y, width, height, and exposures. */
8118 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8119 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
8120 inside_width
, inside_height
- end
,
8128 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8130 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8134 x_scroll_bar_remove (bar
)
8135 struct scroll_bar
*bar
;
8139 #if USE_TOOLKIT_SCROLL_BARS
8140 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar
));
8141 #else /* not USE_TOOLKIT_SCROLL_BARS */
8143 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8144 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
8146 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8148 /* Disassociate this scroll bar from its window. */
8149 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
8155 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8156 that we are displaying PORTION characters out of a total of WHOLE
8157 characters, starting at POSITION. If WINDOW has no scroll bar,
8161 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
8163 int portion
, whole
, position
;
8165 struct frame
*f
= XFRAME (w
->frame
);
8166 struct scroll_bar
*bar
;
8167 int top
, height
, left
, sb_left
, width
, sb_width
;
8168 int window_x
, window_y
, window_width
, window_height
;
8170 /* Get window dimensions. */
8171 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8173 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8174 height
= window_height
;
8176 /* Compute the left edge of the scroll bar area. */
8177 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8178 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
8180 left
= XFASTINT (w
->left
);
8181 left
*= CANON_X_UNIT (f
);
8182 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
8184 /* Compute the width of the scroll bar which might be less than
8185 the width of the area reserved for the scroll bar. */
8186 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
8187 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
8191 /* Compute the left edge of the scroll bar. */
8192 #ifdef USE_TOOLKIT_SCROLL_BARS
8193 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8194 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
8196 sb_left
= left
+ (width
- sb_width
) / 2;
8198 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8199 sb_left
= left
+ width
- sb_width
;
8204 /* Does the scroll bar exist yet? */
8205 if (NILP (w
->vertical_scroll_bar
))
8208 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8209 left
, top
, width
, height
, False
);
8211 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
8215 /* It may just need to be moved and resized. */
8216 unsigned int mask
= 0;
8218 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
8222 if (sb_left
!= XINT (bar
->left
))
8224 if (top
!= XINT (bar
->top
))
8226 if (sb_width
!= XINT (bar
->width
))
8228 if (height
!= XINT (bar
->height
))
8231 #ifdef USE_TOOLKIT_SCROLL_BARS
8233 /* Since toolkit scroll bars are smaller than the space reserved
8234 for them on the frame, we have to clear "under" them. */
8235 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8236 left
, top
, width
, height
, False
);
8238 /* Move/size the scroll bar widget. */
8240 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
8241 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8243 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8246 #else /* not USE_TOOLKIT_SCROLL_BARS */
8248 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
8250 /* Clear areas not covered by the scroll bar. This makes sure a
8251 previous mode line display is cleared after C-x 2 C-x 1, for
8252 example. Non-toolkit scroll bars are as wide as the area
8253 reserved for scroll bars - trim at both sides. */
8254 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8255 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8257 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8258 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8259 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8263 /* Move/size the scroll bar window. */
8268 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8270 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
8272 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
8276 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8278 /* Remember new settings. */
8279 XSETINT (bar
->left
, sb_left
);
8280 XSETINT (bar
->top
, top
);
8281 XSETINT (bar
->width
, sb_width
);
8282 XSETINT (bar
->height
, height
);
8287 #if USE_TOOLKIT_SCROLL_BARS
8288 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
8289 #else /* not USE_TOOLKIT_SCROLL_BARS */
8290 /* Set the scroll bar's current state, unless we're currently being
8292 if (NILP (bar
->dragging
))
8294 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8297 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8300 int start
= ((double) position
* top_range
) / whole
;
8301 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8302 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8305 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8307 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8311 /* The following three hooks are used when we're doing a thorough
8312 redisplay of the frame. We don't explicitly know which scroll bars
8313 are going to be deleted, because keeping track of when windows go
8314 away is a real pain - "Can you say set-window-configuration, boys
8315 and girls?" Instead, we just assert at the beginning of redisplay
8316 that *all* scroll bars are to be removed, and then save a scroll bar
8317 from the fiery pit when we actually redisplay its window. */
8319 /* Arrange for all scroll bars on FRAME to be removed at the next call
8320 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8321 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8324 XTcondemn_scroll_bars (frame
)
8327 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8328 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8331 bar
= FRAME_SCROLL_BARS (frame
);
8332 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8333 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8334 XSCROLL_BAR (bar
)->prev
= Qnil
;
8335 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8336 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8337 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8341 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8342 Note that WINDOW isn't necessarily condemned at all. */
8344 XTredeem_scroll_bar (window
)
8345 struct window
*window
;
8347 struct scroll_bar
*bar
;
8349 /* We can't redeem this window's scroll bar if it doesn't have one. */
8350 if (NILP (window
->vertical_scroll_bar
))
8353 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8355 /* Unlink it from the condemned list. */
8357 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
8359 if (NILP (bar
->prev
))
8361 /* If the prev pointer is nil, it must be the first in one of
8363 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8364 /* It's not condemned. Everything's fine. */
8366 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8367 window
->vertical_scroll_bar
))
8368 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8370 /* If its prev pointer is nil, it must be at the front of
8371 one or the other! */
8375 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8377 if (! NILP (bar
->next
))
8378 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8380 bar
->next
= FRAME_SCROLL_BARS (f
);
8382 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8383 if (! NILP (bar
->next
))
8384 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8388 /* Remove all scroll bars on FRAME that haven't been saved since the
8389 last call to `*condemn_scroll_bars_hook'. */
8392 XTjudge_scroll_bars (f
)
8395 Lisp_Object bar
, next
;
8397 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8399 /* Clear out the condemned list now so we won't try to process any
8400 more events on the hapless scroll bars. */
8401 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8403 for (; ! NILP (bar
); bar
= next
)
8405 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8407 x_scroll_bar_remove (b
);
8410 b
->next
= b
->prev
= Qnil
;
8413 /* Now there should be no references to the condemned scroll bars,
8414 and they should get garbage-collected. */
8418 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8419 is a no-op when using toolkit scroll bars.
8421 This may be called from a signal handler, so we have to ignore GC
8425 x_scroll_bar_expose (bar
, event
)
8426 struct scroll_bar
*bar
;
8429 #ifndef USE_TOOLKIT_SCROLL_BARS
8431 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8432 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8433 GC gc
= f
->output_data
.x
->normal_gc
;
8434 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8438 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
8440 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8441 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8443 /* x, y, width, height */
8445 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
8446 XINT (bar
->height
) - 1);
8450 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8453 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8454 is set to something other than no_event, it is enqueued.
8456 This may be called from a signal handler, so we have to ignore GC
8459 #ifndef USE_TOOLKIT_SCROLL_BARS
8462 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
8463 struct scroll_bar
*bar
;
8465 struct input_event
*emacs_event
;
8467 if (! GC_WINDOWP (bar
->window
))
8470 emacs_event
->kind
= scroll_bar_click
;
8471 emacs_event
->code
= event
->xbutton
.button
- Button1
;
8472 emacs_event
->modifiers
8473 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8474 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
8475 event
->xbutton
.state
)
8476 | (event
->type
== ButtonRelease
8479 emacs_event
->frame_or_window
= bar
->window
;
8480 emacs_event
->timestamp
= event
->xbutton
.time
;
8483 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8485 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8488 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8489 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
8492 if (y
> top_range
) y
= top_range
;
8494 if (y
< XINT (bar
->start
))
8495 emacs_event
->part
= scroll_bar_above_handle
;
8496 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8497 emacs_event
->part
= scroll_bar_handle
;
8499 emacs_event
->part
= scroll_bar_below_handle
;
8501 /* Just because the user has clicked on the handle doesn't mean
8502 they want to drag it. Lisp code needs to be able to decide
8503 whether or not we're dragging. */
8505 /* If the user has just clicked on the handle, record where they're
8507 if (event
->type
== ButtonPress
8508 && emacs_event
->part
== scroll_bar_handle
)
8509 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
8512 /* If the user has released the handle, set it to its final position. */
8513 if (event
->type
== ButtonRelease
8514 && ! NILP (bar
->dragging
))
8516 int new_start
= y
- XINT (bar
->dragging
);
8517 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8519 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8520 bar
->dragging
= Qnil
;
8523 /* Same deal here as the other #if 0. */
8525 /* Clicks on the handle are always reported as occurring at the top of
8527 if (emacs_event
->part
== scroll_bar_handle
)
8528 emacs_event
->x
= bar
->start
;
8530 XSETINT (emacs_event
->x
, y
);
8532 XSETINT (emacs_event
->x
, y
);
8535 XSETINT (emacs_event
->y
, top_range
);
8539 /* Handle some mouse motion while someone is dragging the scroll bar.
8541 This may be called from a signal handler, so we have to ignore GC
8545 x_scroll_bar_note_movement (bar
, event
)
8546 struct scroll_bar
*bar
;
8549 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8551 last_mouse_movement_time
= event
->xmotion
.time
;
8554 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8556 /* If we're dragging the bar, display it. */
8557 if (! GC_NILP (bar
->dragging
))
8559 /* Where should the handle be now? */
8560 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
8562 if (new_start
!= XINT (bar
->start
))
8564 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8566 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8571 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8573 /* Return information to the user about the current position of the mouse
8574 on the scroll bar. */
8577 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8579 Lisp_Object
*bar_window
;
8580 enum scroll_bar_part
*part
;
8582 unsigned long *time
;
8584 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8585 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8586 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8588 Window dummy_window
;
8590 unsigned int dummy_mask
;
8594 /* Get the mouse's position relative to the scroll bar window, and
8596 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
8598 /* Root, child, root x and root y. */
8599 &dummy_window
, &dummy_window
,
8600 &dummy_coord
, &dummy_coord
,
8602 /* Position relative to scroll bar. */
8605 /* Mouse buttons and modifier keys. */
8612 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8615 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8617 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8619 if (! NILP (bar
->dragging
))
8620 win_y
-= XINT (bar
->dragging
);
8624 if (win_y
> top_range
)
8628 *bar_window
= bar
->window
;
8630 if (! NILP (bar
->dragging
))
8631 *part
= scroll_bar_handle
;
8632 else if (win_y
< XINT (bar
->start
))
8633 *part
= scroll_bar_above_handle
;
8634 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8635 *part
= scroll_bar_handle
;
8637 *part
= scroll_bar_below_handle
;
8639 XSETINT (*x
, win_y
);
8640 XSETINT (*y
, top_range
);
8643 last_mouse_scroll_bar
= Qnil
;
8646 *time
= last_mouse_movement_time
;
8652 /* The screen has been cleared so we may have changed foreground or
8653 background colors, and the scroll bars may need to be redrawn.
8654 Clear out the scroll bars, and ask for expose events, so we can
8658 x_scroll_bar_clear (f
)
8661 #ifndef USE_TOOLKIT_SCROLL_BARS
8664 /* We can have scroll bars even if this is 0,
8665 if we just turned off scroll bar mode.
8666 But in that case we should not clear them. */
8667 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8668 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
8669 bar
= XSCROLL_BAR (bar
)->next
)
8670 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
8672 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8675 /* This processes Expose events from the menu-bar specific X event
8676 loop in xmenu.c. This allows to redisplay the frame if necessary
8677 when handling menu-bar or pop-up items. */
8680 process_expose_from_menu (event
)
8684 struct x_display_info
*dpyinfo
;
8685 int frame_exposed_p
= 0;
8689 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
8690 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8693 if (f
->async_visible
== 0)
8695 f
->async_visible
= 1;
8696 f
->async_iconified
= 0;
8697 f
->output_data
.x
->has_been_visible
= 1;
8698 SET_FRAME_GARBAGED (f
);
8702 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
8703 event
.xexpose
.x
, event
.xexpose
.y
,
8704 event
.xexpose
.width
, event
.xexpose
.height
);
8705 frame_exposed_p
= 1;
8710 struct scroll_bar
*bar
8711 = x_window_to_scroll_bar (event
.xexpose
.window
);
8714 x_scroll_bar_expose (bar
, &event
);
8718 return frame_exposed_p
;
8721 /* Define a queue to save up SelectionRequest events for later handling. */
8723 struct selection_event_queue
8726 struct selection_event_queue
*next
;
8729 static struct selection_event_queue
*queue
;
8731 /* Nonzero means queue up certain events--don't process them yet. */
8733 static int x_queue_selection_requests
;
8735 /* Queue up an X event *EVENT, to be processed later. */
8738 x_queue_event (f
, event
)
8742 struct selection_event_queue
*queue_tmp
8743 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
8745 if (queue_tmp
!= NULL
)
8747 queue_tmp
->event
= *event
;
8748 queue_tmp
->next
= queue
;
8753 /* Take all the queued events and put them back
8754 so that they get processed afresh. */
8757 x_unqueue_events (display
)
8760 while (queue
!= NULL
)
8762 struct selection_event_queue
*queue_tmp
= queue
;
8763 XPutBackEvent (display
, &queue_tmp
->event
);
8764 queue
= queue_tmp
->next
;
8765 xfree ((char *)queue_tmp
);
8769 /* Start queuing SelectionRequest events. */
8772 x_start_queuing_selection_requests (display
)
8775 x_queue_selection_requests
++;
8778 /* Stop queuing SelectionRequest events. */
8781 x_stop_queuing_selection_requests (display
)
8784 x_queue_selection_requests
--;
8785 x_unqueue_events (display
);
8788 /* The main X event-reading loop - XTread_socket. */
8790 /* Time stamp of enter window event. This is only used by XTread_socket,
8791 but we have to put it out here, since static variables within functions
8792 sometimes don't work. */
8794 static Time enter_timestamp
;
8796 /* This holds the state XLookupString needs to implement dead keys
8797 and other tricks known as "compose processing". _X Window System_
8798 says that a portable program can't use this, but Stephen Gildea assures
8799 me that letting the compiler initialize it to zeros will work okay.
8801 This must be defined outside of XTread_socket, for the same reasons
8802 given for enter_time stamp, above. */
8804 static XComposeStatus compose_status
;
8806 /* Record the last 100 characters stored
8807 to help debug the loss-of-chars-during-GC problem. */
8809 static int temp_index
;
8810 static short temp_buffer
[100];
8812 /* Set this to nonzero to fake an "X I/O error"
8813 on a particular display. */
8815 struct x_display_info
*XTread_socket_fake_io_error
;
8817 /* When we find no input here, we occasionally do a no-op command
8818 to verify that the X server is still running and we can still talk with it.
8819 We try all the open displays, one by one.
8820 This variable is used for cycling thru the displays. */
8822 static struct x_display_info
*next_noop_dpyinfo
;
8824 #define SET_SAVED_MENU_EVENT(size) \
8827 if (f->output_data.x->saved_menu_event == 0) \
8828 f->output_data.x->saved_menu_event \
8829 = (XEvent *) xmalloc (sizeof (XEvent)); \
8830 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8831 if (numchars >= 1) \
8833 bufp->kind = menu_bar_activate_event; \
8834 XSETFRAME (bufp->frame_or_window, f); \
8842 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8843 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8845 /* Read events coming from the X server.
8846 This routine is called by the SIGIO handler.
8847 We return as soon as there are no more events to be read.
8849 Events representing keys are stored in buffer BUFP,
8850 which can hold up to NUMCHARS characters.
8851 We return the number of characters stored into the buffer,
8852 thus pretending to be `read'.
8854 EXPECTED is nonzero if the caller knows input is available. */
8857 XTread_socket (sd
, bufp
, numchars
, expected
)
8859 /* register */ struct input_event
*bufp
;
8860 /* register */ int numchars
;
8867 int event_found
= 0;
8868 struct x_display_info
*dpyinfo
;
8870 if (interrupt_input_blocked
)
8872 interrupt_input_pending
= 1;
8876 interrupt_input_pending
= 0;
8879 /* So people can tell when we have read the available input. */
8880 input_signal_count
++;
8883 abort (); /* Don't think this happens. */
8885 /* Find the display we are supposed to read input for.
8886 It's the one communicating on descriptor SD. */
8887 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
8889 #if 0 /* This ought to be unnecessary; let's verify it. */
8891 /* If available, Xlib uses FIOSNBIO to make the socket
8892 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8893 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8894 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8895 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
8896 #endif /* ! defined (FIOSNBIO) */
8899 #if 0 /* This code can't be made to work, with multiple displays,
8900 and appears not to be used on any system any more.
8901 Also keyboard.c doesn't turn O_NDELAY on and off
8902 for X connections. */
8905 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
8907 extern int read_alarm_should_throw
;
8908 read_alarm_should_throw
= 1;
8909 XPeekEvent (dpyinfo
->display
, &event
);
8910 read_alarm_should_throw
= 0;
8912 #endif /* HAVE_SELECT */
8916 /* For debugging, this gives a way to fake an I/O error. */
8917 if (dpyinfo
== XTread_socket_fake_io_error
)
8919 XTread_socket_fake_io_error
= 0;
8920 x_io_error_quitter (dpyinfo
->display
);
8923 while (XPending (dpyinfo
->display
))
8925 XNextEvent (dpyinfo
->display
, &event
);
8929 /* Filter events for the current X input method.
8930 XFilterEvent returns non-zero if the input method has
8931 consumed the event. We pass the frame's X window to
8932 XFilterEvent because that's the one for which the IC
8934 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
8935 event
.xclient
.window
);
8936 if (XFilterEvent (&event
, f1
? FRAME_X_WINDOW (f1
) : None
))
8946 if (event
.xclient
.message_type
8947 == dpyinfo
->Xatom_wm_protocols
8948 && event
.xclient
.format
== 32)
8950 if (event
.xclient
.data
.l
[0]
8951 == dpyinfo
->Xatom_wm_take_focus
)
8953 /* Use x_any_window_to_frame because this
8954 could be the shell widget window
8955 if the frame has no title bar. */
8956 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8958 /* Not quite sure this is needed -pd */
8959 if (f
&& FRAME_XIC (f
))
8960 XSetICFocus (FRAME_XIC (f
));
8962 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8963 instructs the WM to set the input focus automatically for
8964 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8965 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8966 it has set the focus. So, XSetInputFocus below is not
8969 The call to XSetInputFocus below has also caused trouble. In
8970 cases where the XSetInputFocus done by the WM and the one
8971 below are temporally close (on a fast machine), the call
8972 below can generate additional FocusIn events which confuse
8975 /* Since we set WM_TAKE_FOCUS, we must call
8976 XSetInputFocus explicitly. But not if f is null,
8977 since that might be an event for a deleted frame. */
8980 Display
*d
= event
.xclient
.display
;
8981 /* Catch and ignore errors, in case window has been
8982 iconified by a window manager such as GWM. */
8983 int count
= x_catch_errors (d
);
8984 XSetInputFocus (d
, event
.xclient
.window
,
8985 /* The ICCCM says this is
8986 the only valid choice. */
8988 event
.xclient
.data
.l
[1]);
8989 /* This is needed to detect the error
8990 if there is an error. */
8992 x_uncatch_errors (d
, count
);
8994 /* Not certain about handling scroll bars here */
8997 else if (event
.xclient
.data
.l
[0]
8998 == dpyinfo
->Xatom_wm_save_yourself
)
9000 /* Save state modify the WM_COMMAND property to
9001 something which can reinstate us. This notifies
9002 the session manager, who's looking for such a
9003 PropertyNotify. Can restart processing when
9004 a keyboard or mouse event arrives. */
9007 f
= x_top_window_to_frame (dpyinfo
,
9008 event
.xclient
.window
);
9010 /* This is just so we only give real data once
9011 for a single Emacs process. */
9012 if (f
== SELECTED_FRAME ())
9013 XSetCommand (FRAME_X_DISPLAY (f
),
9014 event
.xclient
.window
,
9015 initial_argv
, initial_argc
);
9017 XSetCommand (FRAME_X_DISPLAY (f
),
9018 event
.xclient
.window
,
9022 else if (event
.xclient
.data
.l
[0]
9023 == dpyinfo
->Xatom_wm_delete_window
)
9026 = x_any_window_to_frame (dpyinfo
,
9027 event
.xclient
.window
);
9034 bufp
->kind
= delete_window_event
;
9035 XSETFRAME (bufp
->frame_or_window
, f
);
9043 else if (event
.xclient
.message_type
9044 == dpyinfo
->Xatom_wm_configure_denied
)
9047 else if (event
.xclient
.message_type
9048 == dpyinfo
->Xatom_wm_window_moved
)
9052 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9054 new_x
= event
.xclient
.data
.s
[0];
9055 new_y
= event
.xclient
.data
.s
[1];
9059 f
->output_data
.x
->left_pos
= new_x
;
9060 f
->output_data
.x
->top_pos
= new_y
;
9064 else if (event
.xclient
.message_type
9065 == dpyinfo
->Xatom_editres
)
9068 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
9069 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
9072 #endif /* HACK_EDITRES */
9073 else if ((event
.xclient
.message_type
9074 == dpyinfo
->Xatom_DONE
)
9075 || (event
.xclient
.message_type
9076 == dpyinfo
->Xatom_PAGE
))
9078 /* Ghostview job completed. Kill it. We could
9079 reply with "Next" if we received "Page", but we
9080 currently never do because we are interested in
9081 images, only, which should have 1 page. */
9082 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
9084 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9085 x_kill_gs_process (pixmap
, f
);
9086 expose_frame (f
, 0, 0, 0, 0);
9088 #ifdef USE_TOOLKIT_SCROLL_BARS
9089 /* Scroll bar callbacks send a ClientMessage from which
9090 we construct an input_event. */
9091 else if (event
.xclient
.message_type
9092 == dpyinfo
->Xatom_Scrollbar
)
9094 x_scroll_bar_to_input_event (&event
, bufp
);
9095 ++bufp
, ++count
, --numchars
;
9098 #endif /* USE_TOOLKIT_SCROLL_BARS */
9104 case SelectionNotify
:
9105 #ifdef USE_X_TOOLKIT
9106 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
9108 #endif /* not USE_X_TOOLKIT */
9109 x_handle_selection_notify (&event
.xselection
);
9112 case SelectionClear
: /* Someone has grabbed ownership. */
9113 #ifdef USE_X_TOOLKIT
9114 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
9116 #endif /* USE_X_TOOLKIT */
9118 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
9123 bufp
->kind
= selection_clear_event
;
9124 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9125 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9126 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9127 bufp
->frame_or_window
= Qnil
;
9135 case SelectionRequest
: /* Someone wants our selection. */
9136 #ifdef USE_X_TOOLKIT
9137 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
9139 #endif /* USE_X_TOOLKIT */
9140 if (x_queue_selection_requests
)
9141 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
9145 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
9150 bufp
->kind
= selection_request_event
;
9151 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9152 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
9153 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9154 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
9155 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
9156 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9157 bufp
->frame_or_window
= Qnil
;
9165 case PropertyNotify
:
9166 #ifdef USE_X_TOOLKIT
9167 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
9169 #endif /* not USE_X_TOOLKIT */
9170 x_handle_property_notify (&event
.xproperty
);
9173 case ReparentNotify
:
9174 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
9178 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
9179 x_real_positions (f
, &x
, &y
);
9180 f
->output_data
.x
->left_pos
= x
;
9181 f
->output_data
.x
->top_pos
= y
;
9186 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9189 if (f
->async_visible
== 0)
9191 f
->async_visible
= 1;
9192 f
->async_iconified
= 0;
9193 f
->output_data
.x
->has_been_visible
= 1;
9194 SET_FRAME_GARBAGED (f
);
9197 expose_frame (x_window_to_frame (dpyinfo
,
9198 event
.xexpose
.window
),
9199 event
.xexpose
.x
, event
.xexpose
.y
,
9200 event
.xexpose
.width
, event
.xexpose
.height
);
9204 #ifdef USE_TOOLKIT_SCROLL_BARS
9205 /* Dispatch event to the widget. */
9207 #else /* not USE_TOOLKIT_SCROLL_BARS */
9208 struct scroll_bar
*bar
9209 = x_window_to_scroll_bar (event
.xexpose
.window
);
9212 x_scroll_bar_expose (bar
, &event
);
9213 #ifdef USE_X_TOOLKIT
9216 #endif /* USE_X_TOOLKIT */
9217 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9221 case GraphicsExpose
: /* This occurs when an XCopyArea's
9222 source area was obscured or not
9224 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
9228 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
9229 event
.xgraphicsexpose
.width
,
9230 event
.xgraphicsexpose
.height
);
9232 #ifdef USE_X_TOOLKIT
9235 #endif /* USE_X_TOOLKIT */
9238 case NoExpose
: /* This occurs when an XCopyArea's
9239 source area was completely
9244 /* Redo the mouse-highlight after the tooltip has gone. */
9245 if (event
.xmap
.window
== tip_window
)
9248 redo_mouse_highlight ();
9251 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
9252 if (f
) /* F may no longer exist if
9253 the frame was deleted. */
9255 /* While a frame is unmapped, display generation is
9256 disabled; you don't want to spend time updating a
9257 display that won't ever be seen. */
9258 f
->async_visible
= 0;
9259 /* We can't distinguish, from the event, whether the window
9260 has become iconified or invisible. So assume, if it
9261 was previously visible, than now it is iconified.
9262 But x_make_frame_invisible clears both
9263 the visible flag and the iconified flag;
9264 and that way, we know the window is not iconified now. */
9265 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
9267 f
->async_iconified
= 1;
9269 bufp
->kind
= iconify_event
;
9270 XSETFRAME (bufp
->frame_or_window
, f
);
9279 if (event
.xmap
.window
== tip_window
)
9280 /* The tooltip has been drawn already. Avoid
9281 the SET_FRAME_GARBAGED below. */
9284 /* We use x_top_window_to_frame because map events can
9285 come for sub-windows and they don't mean that the
9286 frame is visible. */
9287 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
9290 f
->async_visible
= 1;
9291 f
->async_iconified
= 0;
9292 f
->output_data
.x
->has_been_visible
= 1;
9294 /* wait_reading_process_input will notice this and update
9295 the frame's display structures. */
9296 SET_FRAME_GARBAGED (f
);
9300 bufp
->kind
= deiconify_event
;
9301 XSETFRAME (bufp
->frame_or_window
, f
);
9306 else if (! NILP (Vframe_list
)
9307 && ! NILP (XCDR (Vframe_list
)))
9308 /* Force a redisplay sooner or later
9309 to update the frame titles
9310 in case this is the second frame. */
9311 record_asynch_buffer_change ();
9316 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
9319 /* I couldn't find a way to prevent LessTif scroll bars
9320 from consuming key events. */
9323 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
9325 if (widget
&& XmIsScrollBar (widget
))
9327 widget
= XtParent (widget
);
9328 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
9331 #endif /* USE_MOTIF */
9335 KeySym keysym
, orig_keysym
;
9336 /* al%imercury@uunet.uu.net says that making this 81 instead of
9337 80 fixed a bug whereby meta chars made his Emacs hang. */
9338 unsigned char copy_buffer
[81];
9342 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
9343 extra_keyboard_modifiers
);
9344 modifiers
= event
.xkey
.state
;
9346 /* This will have to go some day... */
9348 /* make_lispy_event turns chars into control chars.
9349 Don't do it here because XLookupString is too eager. */
9350 event
.xkey
.state
&= ~ControlMask
;
9351 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
9352 | dpyinfo
->super_mod_mask
9353 | dpyinfo
->hyper_mod_mask
9354 | dpyinfo
->alt_mod_mask
);
9356 /* In case Meta is ComposeCharacter,
9357 clear its status. According to Markus Ehrnsperger
9358 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9359 this enables ComposeCharacter to work whether or
9360 not it is combined with Meta. */
9361 if (modifiers
& dpyinfo
->meta_mod_mask
)
9362 bzero (&compose_status
, sizeof (compose_status
));
9367 unsigned char *copy_bufptr
= copy_buffer
;
9368 int copy_bufsiz
= sizeof (copy_buffer
);
9369 Status status_return
;
9371 nbytes
= XmbLookupString (FRAME_XIC (f
),
9372 &event
.xkey
, copy_bufptr
,
9373 copy_bufsiz
, &keysym
,
9375 if (status_return
== XBufferOverflow
)
9377 copy_bufsiz
= nbytes
+ 1;
9378 copy_bufptr
= (char *) alloca (copy_bufsiz
);
9379 nbytes
= XmbLookupString (FRAME_XIC (f
),
9380 &event
.xkey
, copy_bufptr
,
9381 copy_bufsiz
, &keysym
,
9385 if (status_return
== XLookupNone
)
9387 else if (status_return
== XLookupChars
)
9389 else if (status_return
!= XLookupKeySym
9390 && status_return
!= XLookupBoth
)
9394 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9395 80, &keysym
, &compose_status
);
9397 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9398 80, &keysym
, &compose_status
);
9401 orig_keysym
= keysym
;
9405 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
9406 || keysym
== XK_Delete
9407 #ifdef XK_ISO_Left_Tab
9408 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
9410 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
9411 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
9412 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
9414 /* This recognizes the "extended function keys".
9415 It seems there's no cleaner way.
9416 Test IsModifierKey to avoid handling mode_switch
9418 || ((unsigned) (keysym
) >= XK_Select
9419 && (unsigned)(keysym
) < XK_KP_Space
)
9421 #ifdef XK_dead_circumflex
9422 || orig_keysym
== XK_dead_circumflex
9424 #ifdef XK_dead_grave
9425 || orig_keysym
== XK_dead_grave
9427 #ifdef XK_dead_tilde
9428 || orig_keysym
== XK_dead_tilde
9430 #ifdef XK_dead_diaeresis
9431 || orig_keysym
== XK_dead_diaeresis
9433 #ifdef XK_dead_macron
9434 || orig_keysym
== XK_dead_macron
9436 #ifdef XK_dead_degree
9437 || orig_keysym
== XK_dead_degree
9439 #ifdef XK_dead_acute
9440 || orig_keysym
== XK_dead_acute
9442 #ifdef XK_dead_cedilla
9443 || orig_keysym
== XK_dead_cedilla
9445 #ifdef XK_dead_breve
9446 || orig_keysym
== XK_dead_breve
9448 #ifdef XK_dead_ogonek
9449 || orig_keysym
== XK_dead_ogonek
9451 #ifdef XK_dead_caron
9452 || orig_keysym
== XK_dead_caron
9454 #ifdef XK_dead_doubleacute
9455 || orig_keysym
== XK_dead_doubleacute
9457 #ifdef XK_dead_abovedot
9458 || orig_keysym
== XK_dead_abovedot
9460 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
9461 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
9462 /* Any "vendor-specific" key is ok. */
9463 || (orig_keysym
& (1 << 28)))
9464 && ! (IsModifierKey (orig_keysym
)
9466 #ifdef XK_Mode_switch
9467 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
9470 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
9472 #endif /* not HAVE_X11R5 */
9475 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9477 temp_buffer
[temp_index
++] = keysym
;
9478 bufp
->kind
= non_ascii_keystroke
;
9479 bufp
->code
= keysym
;
9480 XSETFRAME (bufp
->frame_or_window
, f
);
9482 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9484 bufp
->timestamp
= event
.xkey
.time
;
9489 else if (numchars
> nbytes
)
9493 for (i
= 0; i
< nbytes
; i
++)
9495 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9497 temp_buffer
[temp_index
++] = copy_buffer
[i
];
9498 bufp
->kind
= ascii_keystroke
;
9499 bufp
->code
= copy_buffer
[i
];
9500 XSETFRAME (bufp
->frame_or_window
, f
);
9502 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9504 bufp
->timestamp
= event
.xkey
.time
;
9511 if (keysym
== NoSymbol
)
9521 /* Don't dispatch this event since XtDispatchEvent calls
9522 XFilterEvent, and two calls in a row may freeze the
9531 /* Don't dispatch this event since XtDispatchEvent calls
9532 XFilterEvent, and two calls in a row may freeze the
9539 /* Here's a possible interpretation of the whole
9540 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9541 you get a FocusIn event, you have to get a FocusOut
9542 event before you relinquish the focus. If you
9543 haven't received a FocusIn event, then a mere
9544 LeaveNotify is enough to free you. */
9548 int from_menu_bar_p
= 0;
9550 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9552 #ifdef LESSTIF_VERSION
9553 /* When clicking outside of a menu bar popup to close
9554 it, we get a FocusIn/ EnterNotify sequence of
9555 events. The flag event.xcrossing.focus is not set
9556 in the EnterNotify event of that sequence because
9557 the focus is in the menu bar,
9558 event.xcrossing.window is the frame's X window.
9559 Unconditionally setting the focus frame to null in
9560 this case is not the right thing, because no event
9561 follows that could set the focus frame to the right
9564 This could be a LessTif bug, but I wasn't able to
9565 reproduce the behavior in a simple test program.
9567 (gerd, LessTif 0.88.1). */
9569 if (!event
.xcrossing
.focus
9571 && f
->output_data
.x
->menubar_widget
)
9576 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9577 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9578 from_menu_bar_p
= 1;
9580 #endif /* LESSTIF_VERSION */
9582 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9584 /* Avoid nasty pop/raise loops. */
9585 if (f
&& (!(f
->auto_raise
)
9587 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
9589 x_new_focus_frame (dpyinfo
, f
);
9590 enter_timestamp
= event
.xcrossing
.time
;
9593 else if (f
== dpyinfo
->x_focus_frame
)
9594 x_new_focus_frame (dpyinfo
, 0);
9596 /* EnterNotify counts as mouse movement,
9597 so update things that depend on mouse position. */
9598 if (f
&& !f
->output_data
.x
->busy_p
)
9599 note_mouse_movement (f
, &event
.xmotion
);
9604 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9605 if (event
.xfocus
.detail
!= NotifyPointer
)
9606 dpyinfo
->x_focus_event_frame
= f
;
9608 x_new_focus_frame (dpyinfo
, f
);
9611 if (f
&& FRAME_XIC (f
))
9612 XSetICFocus (FRAME_XIC (f
));
9618 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9622 int from_menu_bar_p
= 0;
9624 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9626 /* If we move outside the frame, then we're
9627 certainly no longer on any text in the frame. */
9628 clear_mouse_face (dpyinfo
);
9629 dpyinfo
->mouse_face_mouse_frame
= 0;
9632 /* Generate a nil HELP_EVENT to cancel a help-echo.
9633 Do it only if there's something to cancel.
9634 Otherwise, the startup message is cleared when
9635 the mouse leaves the frame. */
9636 if (any_help_event_p
)
9638 XSETFRAME (frame
, f
);
9639 bufp
->kind
= HELP_EVENT
;
9640 bufp
->frame_or_window
= Fcons (frame
, Qnil
);
9641 ++bufp
, ++count
, --numchars
;
9644 #ifdef LESSTIF_VERSION
9645 /* Please see the comment at the start of the
9646 EnterNotify case. */
9647 if (!event
.xcrossing
.focus
9648 && f
->output_data
.x
->menubar_widget
)
9652 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9653 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9654 from_menu_bar_p
= 1;
9656 #endif /* LESSTIF_VERSION */
9658 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9659 x_mouse_leave (dpyinfo
);
9662 if (f
== dpyinfo
->x_focus_event_frame
)
9663 dpyinfo
->x_focus_event_frame
= 0;
9664 if (f
== dpyinfo
->x_focus_frame
)
9665 x_new_focus_frame (dpyinfo
, 0);
9671 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9672 if (event
.xfocus
.detail
!= NotifyPointer
9673 && f
== dpyinfo
->x_focus_event_frame
)
9674 dpyinfo
->x_focus_event_frame
= 0;
9675 if (f
&& f
== dpyinfo
->x_focus_frame
)
9676 x_new_focus_frame (dpyinfo
, 0);
9679 if (f
&& FRAME_XIC (f
))
9680 XUnsetICFocus (FRAME_XIC (f
));
9687 previous_help_echo
= help_echo
;
9690 if (dpyinfo
->grabbed
&& last_mouse_frame
9691 && FRAME_LIVE_P (last_mouse_frame
))
9692 f
= last_mouse_frame
;
9694 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
9697 note_mouse_movement (f
, &event
.xmotion
);
9700 #ifndef USE_TOOLKIT_SCROLL_BARS
9701 struct scroll_bar
*bar
9702 = x_window_to_scroll_bar (event
.xmotion
.window
);
9705 x_scroll_bar_note_movement (bar
, &event
);
9706 #endif /* USE_TOOLKIT_SCROLL_BARS */
9708 /* If we move outside the frame, then we're
9709 certainly no longer on any text in the frame. */
9710 clear_mouse_face (dpyinfo
);
9713 /* If the contents of the global variable help_echo
9714 has changed, generate a HELP_EVENT. */
9715 if (STRINGP (help_echo
)
9716 || STRINGP (previous_help_echo
))
9721 XSETFRAME (frame
, f
);
9725 any_help_event_p
= 1;
9726 bufp
->kind
= HELP_EVENT
;
9727 bufp
->frame_or_window
= Fcons (frame
, help_echo
);
9728 ++bufp
, ++count
, --numchars
;
9734 case ConfigureNotify
:
9735 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
9738 #ifndef USE_X_TOOLKIT
9739 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
9740 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
9742 /* In the toolkit version, change_frame_size
9743 is called by the code that handles resizing
9744 of the EmacsFrame widget. */
9746 /* Even if the number of character rows and columns has
9747 not changed, the font size may have changed, so we need
9748 to check the pixel dimensions as well. */
9749 if (columns
!= f
->width
9750 || rows
!= f
->height
9751 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
9752 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
9754 change_frame_size (f
, rows
, columns
, 0, 1, 0);
9755 SET_FRAME_GARBAGED (f
);
9756 cancel_mouse_face (f
);
9760 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
9761 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
9763 /* What we have now is the position of Emacs's own window.
9764 Convert that to the position of the window manager window. */
9765 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
9766 &f
->output_data
.x
->top_pos
);
9769 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMStatusArea
))
9770 xic_set_statusarea (f
);
9773 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
9775 /* Since the WM decorations come below top_pos now,
9776 we must put them below top_pos in the future. */
9777 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9778 x_wm_set_size_hint (f
, (long) 0, 0);
9781 /* Some window managers pass (0,0) as the location of
9782 the window, and the Motif event handler stores it
9783 in the emacs widget, which messes up Motif menus. */
9784 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
9786 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
9787 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
9789 #endif /* USE_MOTIF */
9796 /* If we decide we want to generate an event to be seen
9797 by the rest of Emacs, we put it here. */
9798 struct input_event emacs_event
;
9801 emacs_event
.kind
= no_event
;
9802 bzero (&compose_status
, sizeof (compose_status
));
9804 if (dpyinfo
->grabbed
9806 && FRAME_LIVE_P (last_mouse_frame
))
9807 f
= last_mouse_frame
;
9809 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9813 /* Is this in the tool-bar? */
9814 if (WINDOWP (f
->tool_bar_window
)
9815 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
9820 x
= event
.xbutton
.x
;
9821 y
= event
.xbutton
.y
;
9824 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
9825 if (EQ (window
, f
->tool_bar_window
))
9827 x_handle_tool_bar_click (f
, &event
.xbutton
);
9833 if (!dpyinfo
->x_focus_frame
9834 || f
== dpyinfo
->x_focus_frame
)
9835 construct_mouse_click (&emacs_event
, &event
, f
);
9839 #ifndef USE_TOOLKIT_SCROLL_BARS
9840 struct scroll_bar
*bar
9841 = x_window_to_scroll_bar (event
.xbutton
.window
);
9844 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
9845 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9848 if (event
.type
== ButtonPress
)
9850 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
9851 last_mouse_frame
= f
;
9852 /* Ignore any mouse motion that happened
9853 before this event; any subsequent mouse-movement
9854 Emacs events should reflect only motion after
9860 last_tool_bar_item
= -1;
9864 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
9867 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
9869 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
9875 #ifdef USE_X_TOOLKIT
9876 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9877 /* For a down-event in the menu bar,
9878 don't pass it to Xt right now.
9879 Instead, save it away
9880 and we will pass it to Xt from kbd_buffer_get_event.
9881 That way, we can run some Lisp code first. */
9882 if (f
&& event
.type
== ButtonPress
9883 /* Verify the event is really within the menu bar
9884 and not just sent to it due to grabbing. */
9885 && event
.xbutton
.x
>= 0
9886 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
9887 && event
.xbutton
.y
>= 0
9888 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
9889 && event
.xbutton
.same_screen
)
9891 SET_SAVED_BUTTON_EVENT
;
9892 XSETFRAME (last_mouse_press_frame
, f
);
9894 else if (event
.type
== ButtonPress
)
9896 last_mouse_press_frame
= Qnil
;
9900 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9901 but I am trying to be cautious. */
9902 else if (event
.type
== ButtonRelease
)
9904 if (!NILP (last_mouse_press_frame
))
9906 f
= XFRAME (last_mouse_press_frame
);
9907 if (f
->output_data
.x
)
9908 SET_SAVED_BUTTON_EVENT
;
9913 #endif /* USE_MOTIF */
9916 #endif /* USE_X_TOOLKIT */
9920 case CirculateNotify
:
9923 case CirculateRequest
:
9926 case VisibilityNotify
:
9930 /* Someone has changed the keyboard mapping - update the
9932 switch (event
.xmapping
.request
)
9934 case MappingModifier
:
9935 x_find_modifier_meanings (dpyinfo
);
9936 /* This is meant to fall through. */
9937 case MappingKeyboard
:
9938 XRefreshKeyboardMapping (&event
.xmapping
);
9944 #ifdef USE_X_TOOLKIT
9946 XtDispatchEvent (&event
);
9948 #endif /* USE_X_TOOLKIT */
9956 /* On some systems, an X bug causes Emacs to get no more events
9957 when the window is destroyed. Detect that. (1994.) */
9960 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9961 One XNOOP in 100 loops will make Emacs terminate.
9962 B. Bretthauer, 1994 */
9964 if (x_noop_count
>= 100)
9968 if (next_noop_dpyinfo
== 0)
9969 next_noop_dpyinfo
= x_display_list
;
9971 XNoOp (next_noop_dpyinfo
->display
);
9973 /* Each time we get here, cycle through the displays now open. */
9974 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
9978 /* If the focus was just given to an auto-raising frame,
9980 /* ??? This ought to be able to handle more than one such frame. */
9981 if (pending_autoraise_frame
)
9983 x_raise_frame (pending_autoraise_frame
);
9984 pending_autoraise_frame
= 0;
9994 /***********************************************************************
9996 ***********************************************************************/
9998 /* Note if the text cursor of window W has been overwritten by a
9999 drawing operation that outputs N glyphs starting at HPOS in the
10000 line given by output_cursor.vpos. N < 0 means all the rest of the
10001 line after HPOS has been written. */
10004 note_overwritten_text_cursor (w
, hpos
, n
)
10008 if (updated_area
== TEXT_AREA
10009 && output_cursor
.vpos
== w
->phys_cursor
.vpos
10010 && hpos
<= w
->phys_cursor
.hpos
10012 || hpos
+ n
> w
->phys_cursor
.hpos
))
10013 w
->phys_cursor_on_p
= 0;
10017 /* Set clipping for output in glyph row ROW. W is the window in which
10018 we operate. GC is the graphics context to set clipping in.
10019 WHOLE_LINE_P non-zero means include the areas used for truncation
10020 mark display and alike in the clipping rectangle.
10022 ROW may be a text row or, e.g., a mode line. Text rows must be
10023 clipped to the interior of the window dedicated to text display,
10024 mode lines must be clipped to the whole window. */
10027 x_clip_to_row (w
, row
, gc
, whole_line_p
)
10029 struct glyph_row
*row
;
10033 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
10034 XRectangle clip_rect
;
10035 int window_x
, window_y
, window_width
, window_height
;
10037 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
10039 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
10040 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
10041 clip_rect
.y
= max (clip_rect
.y
, window_y
);
10042 clip_rect
.width
= window_width
;
10043 clip_rect
.height
= row
->visible_height
;
10045 /* If clipping to the whole line, including trunc marks, extend
10046 the rectangle to the left and increase its width. */
10049 clip_rect
.x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
10050 clip_rect
.width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
10053 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
10057 /* Draw a hollow box cursor on window W in glyph row ROW. */
10060 x_draw_hollow_cursor (w
, row
)
10062 struct glyph_row
*row
;
10064 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
10065 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10066 Display
*dpy
= FRAME_X_DISPLAY (f
);
10069 struct glyph
*cursor_glyph
;
10072 /* Compute frame-relative coordinates from window-relative
10074 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10075 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
10076 + row
->ascent
- w
->phys_cursor_ascent
);
10077 h
= row
->height
- 1;
10079 /* Get the glyph the cursor is on. If we can't tell because
10080 the current matrix is invalid or such, give up. */
10081 cursor_glyph
= get_phys_cursor_glyph (w
);
10082 if (cursor_glyph
== NULL
)
10085 /* Compute the width of the rectangle to draw. If on a stretch
10086 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10087 rectangle as wide as the glyph, but use a canonical character
10089 wd
= cursor_glyph
->pixel_width
- 1;
10090 if (cursor_glyph
->type
== STRETCH_GLYPH
10091 && !x_stretch_cursor_p
)
10092 wd
= min (CANON_X_UNIT (f
), wd
);
10094 /* The foreground of cursor_gc is typically the same as the normal
10095 background color, which can cause the cursor box to be invisible. */
10096 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10097 if (dpyinfo
->scratch_cursor_gc
)
10098 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
10100 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
10101 GCForeground
, &xgcv
);
10102 gc
= dpyinfo
->scratch_cursor_gc
;
10104 /* Set clipping, draw the rectangle, and reset clipping again. */
10105 x_clip_to_row (w
, row
, gc
, 0);
10106 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
10107 XSetClipMask (dpy
, gc
, None
);
10111 /* Draw a bar cursor on window W in glyph row ROW.
10113 Implementation note: One would like to draw a bar cursor with an
10114 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10115 Unfortunately, I didn't find a font yet that has this property set.
10119 x_draw_bar_cursor (w
, row
, width
)
10121 struct glyph_row
*row
;
10124 /* If cursor hpos is out of bounds, don't draw garbage. This can
10125 happen in mini-buffer windows when switching between echo area
10126 glyphs and mini-buffer. */
10127 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10129 struct frame
*f
= XFRAME (w
->frame
);
10130 struct glyph
*cursor_glyph
;
10133 unsigned long mask
;
10138 cursor_glyph
= get_phys_cursor_glyph (w
);
10139 if (cursor_glyph
== NULL
)
10142 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
10143 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10144 xgcv
.graphics_exposures
= 0;
10145 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
10146 dpy
= FRAME_X_DISPLAY (f
);
10147 window
= FRAME_X_WINDOW (f
);
10148 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
10151 XChangeGC (dpy
, gc
, mask
, &xgcv
);
10154 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
10155 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
10159 width
= f
->output_data
.x
->cursor_width
;
10161 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10162 x_clip_to_row (w
, row
, gc
, 0);
10163 XFillRectangle (dpy
, window
, gc
,
10165 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
10166 min (cursor_glyph
->pixel_width
, width
),
10168 XSetClipMask (dpy
, gc
, None
);
10173 /* Clear the cursor of window W to background color, and mark the
10174 cursor as not shown. This is used when the text where the cursor
10175 is is about to be rewritten. */
10181 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
10182 x_update_window_cursor (w
, 0);
10186 /* Draw the cursor glyph of window W in glyph row ROW. See the
10187 comment of x_draw_glyphs for the meaning of HL. */
10190 x_draw_phys_cursor_glyph (w
, row
, hl
)
10192 struct glyph_row
*row
;
10193 enum draw_glyphs_face hl
;
10195 /* If cursor hpos is out of bounds, don't draw garbage. This can
10196 happen in mini-buffer windows when switching between echo area
10197 glyphs and mini-buffer. */
10198 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10200 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
10201 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
10204 /* When we erase the cursor, and ROW is overlapped by other
10205 rows, make sure that these overlapping parts of other rows
10207 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
10209 if (row
> w
->current_matrix
->rows
10210 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
10211 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
10213 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
10214 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
10215 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
10221 /* Erase the image of a cursor of window W from the screen. */
10224 x_erase_phys_cursor (w
)
10227 struct frame
*f
= XFRAME (w
->frame
);
10228 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10229 int hpos
= w
->phys_cursor
.hpos
;
10230 int vpos
= w
->phys_cursor
.vpos
;
10231 int mouse_face_here_p
= 0;
10232 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
10233 struct glyph_row
*cursor_row
;
10234 struct glyph
*cursor_glyph
;
10235 enum draw_glyphs_face hl
;
10237 /* No cursor displayed or row invalidated => nothing to do on the
10239 if (w
->phys_cursor_type
== NO_CURSOR
)
10240 goto mark_cursor_off
;
10242 /* VPOS >= active_glyphs->nrows means that window has been resized.
10243 Don't bother to erase the cursor. */
10244 if (vpos
>= active_glyphs
->nrows
)
10245 goto mark_cursor_off
;
10247 /* If row containing cursor is marked invalid, there is nothing we
10249 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
10250 if (!cursor_row
->enabled_p
)
10251 goto mark_cursor_off
;
10253 /* This can happen when the new row is shorter than the old one.
10254 In this case, either x_draw_glyphs or clear_end_of_line
10255 should have cleared the cursor. Note that we wouldn't be
10256 able to erase the cursor in this case because we don't have a
10257 cursor glyph at hand. */
10258 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
10259 goto mark_cursor_off
;
10261 /* If the cursor is in the mouse face area, redisplay that when
10262 we clear the cursor. */
10263 if (! NILP (dpyinfo
->mouse_face_window
)
10264 && w
== XWINDOW (dpyinfo
->mouse_face_window
)
10265 && (vpos
> dpyinfo
->mouse_face_beg_row
10266 || (vpos
== dpyinfo
->mouse_face_beg_row
10267 && hpos
>= dpyinfo
->mouse_face_beg_col
))
10268 && (vpos
< dpyinfo
->mouse_face_end_row
10269 || (vpos
== dpyinfo
->mouse_face_end_row
10270 && hpos
< dpyinfo
->mouse_face_end_col
))
10271 /* Don't redraw the cursor's spot in mouse face if it is at the
10272 end of a line (on a newline). The cursor appears there, but
10273 mouse highlighting does not. */
10274 && cursor_row
->used
[TEXT_AREA
] > hpos
)
10275 mouse_face_here_p
= 1;
10277 /* Maybe clear the display under the cursor. */
10278 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
10281 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
10283 cursor_glyph
= get_phys_cursor_glyph (w
);
10284 if (cursor_glyph
== NULL
)
10285 goto mark_cursor_off
;
10287 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
10289 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10291 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
10293 cursor_glyph
->pixel_width
,
10294 cursor_row
->visible_height
,
10298 /* Erase the cursor by redrawing the character underneath it. */
10299 if (mouse_face_here_p
)
10300 hl
= DRAW_MOUSE_FACE
;
10301 else if (cursor_row
->inverse_p
)
10302 hl
= DRAW_INVERSE_VIDEO
;
10304 hl
= DRAW_NORMAL_TEXT
;
10305 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
10308 w
->phys_cursor_on_p
= 0;
10309 w
->phys_cursor_type
= NO_CURSOR
;
10313 /* Display or clear cursor of window W. If ON is zero, clear the
10314 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10315 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10318 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
10320 int on
, hpos
, vpos
, x
, y
;
10322 struct frame
*f
= XFRAME (w
->frame
);
10323 int new_cursor_type
;
10324 int new_cursor_width
;
10325 struct glyph_matrix
*current_glyphs
;
10326 struct glyph_row
*glyph_row
;
10327 struct glyph
*glyph
;
10329 /* This is pointless on invisible frames, and dangerous on garbaged
10330 windows and frames; in the latter case, the frame or window may
10331 be in the midst of changing its size, and x and y may be off the
10333 if (! FRAME_VISIBLE_P (f
)
10334 || FRAME_GARBAGED_P (f
)
10335 || vpos
>= w
->current_matrix
->nrows
10336 || hpos
>= w
->current_matrix
->matrix_w
)
10339 /* If cursor is off and we want it off, return quickly. */
10340 if (!on
&& !w
->phys_cursor_on_p
)
10343 current_glyphs
= w
->current_matrix
;
10344 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
10345 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
10347 /* If cursor row is not enabled, we don't really know where to
10348 display the cursor. */
10349 if (!glyph_row
->enabled_p
)
10351 w
->phys_cursor_on_p
= 0;
10355 xassert (interrupt_input_blocked
);
10357 /* Set new_cursor_type to the cursor we want to be displayed. In a
10358 mini-buffer window, we want the cursor only to appear if we are
10359 reading input from this window. For the selected window, we want
10360 the cursor type given by the frame parameter. If explicitly
10361 marked off, draw no cursor. In all other cases, we want a hollow
10363 new_cursor_width
= -1;
10364 if (cursor_in_echo_area
10365 && FRAME_HAS_MINIBUF_P (f
)
10366 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
10368 if (w
== XWINDOW (echo_area_window
))
10369 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10371 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10375 if (w
!= XWINDOW (selected_window
)
10376 || f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
10378 extern int cursor_in_non_selected_windows
;
10380 if (MINI_WINDOW_P (w
) || !cursor_in_non_selected_windows
)
10381 new_cursor_type
= NO_CURSOR
;
10383 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10385 else if (w
->cursor_off_p
)
10386 new_cursor_type
= NO_CURSOR
;
10389 struct buffer
*b
= XBUFFER (w
->buffer
);
10391 if (EQ (b
->cursor_type
, Qt
))
10392 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10394 new_cursor_type
= x_specified_cursor_type (b
->cursor_type
,
10395 &new_cursor_width
);
10399 /* If cursor is currently being shown and we don't want it to be or
10400 it is in the wrong place, or the cursor type is not what we want,
10402 if (w
->phys_cursor_on_p
10404 || w
->phys_cursor
.x
!= x
10405 || w
->phys_cursor
.y
!= y
10406 || new_cursor_type
!= w
->phys_cursor_type
))
10407 x_erase_phys_cursor (w
);
10409 /* If the cursor is now invisible and we want it to be visible,
10411 if (on
&& !w
->phys_cursor_on_p
)
10413 w
->phys_cursor_ascent
= glyph_row
->ascent
;
10414 w
->phys_cursor_height
= glyph_row
->height
;
10416 /* Set phys_cursor_.* before x_draw_.* is called because some
10417 of them may need the information. */
10418 w
->phys_cursor
.x
= x
;
10419 w
->phys_cursor
.y
= glyph_row
->y
;
10420 w
->phys_cursor
.hpos
= hpos
;
10421 w
->phys_cursor
.vpos
= vpos
;
10422 w
->phys_cursor_type
= new_cursor_type
;
10423 w
->phys_cursor_on_p
= 1;
10425 switch (new_cursor_type
)
10427 case HOLLOW_BOX_CURSOR
:
10428 x_draw_hollow_cursor (w
, glyph_row
);
10431 case FILLED_BOX_CURSOR
:
10432 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
10436 x_draw_bar_cursor (w
, glyph_row
, new_cursor_width
);
10447 if (w
== XWINDOW (f
->selected_window
))
10448 if (FRAME_XIC (f
) && (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
))
10449 xic_set_preeditarea (w
, x
, y
);
10454 if (updating_frame
!= f
)
10455 XFlush (FRAME_X_DISPLAY (f
));
10460 /* Display the cursor on window W, or clear it. X and Y are window
10461 relative pixel coordinates. HPOS and VPOS are glyph matrix
10462 positions. If W is not the selected window, display a hollow
10463 cursor. ON non-zero means display the cursor at X, Y which
10464 correspond to HPOS, VPOS, otherwise it is cleared. */
10467 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
10469 int on
, hpos
, vpos
, x
, y
;
10472 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
10477 /* Display the cursor on window W, or clear it, according to ON_P.
10478 Don't change the cursor's position. */
10481 x_update_cursor (f
, on_p
)
10484 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
10488 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10489 in the window tree rooted at W. */
10492 x_update_cursor_in_window_tree (w
, on_p
)
10498 if (!NILP (w
->hchild
))
10499 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
10500 else if (!NILP (w
->vchild
))
10501 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
10503 x_update_window_cursor (w
, on_p
);
10505 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
10510 /* Switch the display of W's cursor on or off, according to the value
10514 x_update_window_cursor (w
, on
)
10518 /* Don't update cursor in windows whose frame is in the process
10519 of being deleted. */
10520 if (w
->current_matrix
)
10523 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
10524 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
10534 /* Refresh bitmap kitchen sink icon for frame F
10535 when we get an expose event for it. */
10541 /* Normally, the window manager handles this function. */
10544 /* Make the x-window of frame F use the gnu icon bitmap. */
10547 x_bitmap_icon (f
, file
)
10553 if (FRAME_X_WINDOW (f
) == 0)
10556 /* Free up our existing icon bitmap if any. */
10557 if (f
->output_data
.x
->icon_bitmap
> 0)
10558 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10559 f
->output_data
.x
->icon_bitmap
= 0;
10561 if (STRINGP (file
))
10562 bitmap_id
= x_create_bitmap_from_file (f
, file
);
10565 /* Create the GNU bitmap if necessary. */
10566 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
10567 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
10568 = x_create_bitmap_from_data (f
, gnu_bits
,
10569 gnu_width
, gnu_height
);
10571 /* The first time we create the GNU bitmap,
10572 this increments the ref-count one extra time.
10573 As a result, the GNU bitmap is never freed.
10574 That way, we don't have to worry about allocating it again. */
10575 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
10577 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
10580 x_wm_set_icon_pixmap (f
, bitmap_id
);
10581 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
10587 /* Make the x-window of frame F use a rectangle with text.
10588 Use ICON_NAME as the text. */
10591 x_text_icon (f
, icon_name
)
10595 if (FRAME_X_WINDOW (f
) == 0)
10600 XTextProperty text
;
10601 text
.value
= (unsigned char *) icon_name
;
10602 text
.encoding
= XA_STRING
;
10604 text
.nitems
= strlen (icon_name
);
10605 #ifdef USE_X_TOOLKIT
10606 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10608 #else /* not USE_X_TOOLKIT */
10609 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
10610 #endif /* not USE_X_TOOLKIT */
10612 #else /* not HAVE_X11R4 */
10613 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
10614 #endif /* not HAVE_X11R4 */
10616 if (f
->output_data
.x
->icon_bitmap
> 0)
10617 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10618 f
->output_data
.x
->icon_bitmap
= 0;
10619 x_wm_set_icon_pixmap (f
, 0);
10624 #define X_ERROR_MESSAGE_SIZE 200
10626 /* If non-nil, this should be a string.
10627 It means catch X errors and store the error message in this string. */
10629 static Lisp_Object x_error_message_string
;
10631 /* An X error handler which stores the error message in
10632 x_error_message_string. This is called from x_error_handler if
10633 x_catch_errors is in effect. */
10636 x_error_catcher (display
, error
)
10638 XErrorEvent
*error
;
10640 XGetErrorText (display
, error
->error_code
,
10641 XSTRING (x_error_message_string
)->data
,
10642 X_ERROR_MESSAGE_SIZE
);
10645 /* Begin trapping X errors for display DPY. Actually we trap X errors
10646 for all displays, but DPY should be the display you are actually
10649 After calling this function, X protocol errors no longer cause
10650 Emacs to exit; instead, they are recorded in the string
10651 stored in x_error_message_string.
10653 Calling x_check_errors signals an Emacs error if an X error has
10654 occurred since the last call to x_catch_errors or x_check_errors.
10656 Calling x_uncatch_errors resumes the normal error handling. */
10658 void x_check_errors ();
10659 static Lisp_Object
x_catch_errors_unwind ();
10662 x_catch_errors (dpy
)
10665 int count
= specpdl_ptr
- specpdl
;
10667 /* Make sure any errors from previous requests have been dealt with. */
10668 XSync (dpy
, False
);
10670 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
10672 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
10673 XSTRING (x_error_message_string
)->data
[0] = 0;
10678 /* Unbind the binding that we made to check for X errors. */
10681 x_catch_errors_unwind (old_val
)
10682 Lisp_Object old_val
;
10684 x_error_message_string
= old_val
;
10688 /* If any X protocol errors have arrived since the last call to
10689 x_catch_errors or x_check_errors, signal an Emacs error using
10690 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10693 x_check_errors (dpy
, format
)
10697 /* Make sure to catch any errors incurred so far. */
10698 XSync (dpy
, False
);
10700 if (XSTRING (x_error_message_string
)->data
[0])
10701 error (format
, XSTRING (x_error_message_string
)->data
);
10704 /* Nonzero if we had any X protocol errors
10705 since we did x_catch_errors on DPY. */
10708 x_had_errors_p (dpy
)
10711 /* Make sure to catch any errors incurred so far. */
10712 XSync (dpy
, False
);
10714 return XSTRING (x_error_message_string
)->data
[0] != 0;
10717 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10720 x_clear_errors (dpy
)
10723 XSTRING (x_error_message_string
)->data
[0] = 0;
10726 /* Stop catching X protocol errors and let them make Emacs die.
10727 DPY should be the display that was passed to x_catch_errors.
10728 COUNT should be the value that was returned by
10729 the corresponding call to x_catch_errors. */
10732 x_uncatch_errors (dpy
, count
)
10736 unbind_to (count
, Qnil
);
10740 static unsigned int x_wire_count
;
10743 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
10748 /* Handle SIGPIPE, which can happen when the connection to a server
10749 simply goes away. SIGPIPE is handled by x_connection_signal.
10750 Don't need to do anything, because the write which caused the
10751 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10752 which will do the appropriate cleanup for us. */
10755 x_connection_signal (signalnum
) /* If we don't have an argument, */
10756 int signalnum
; /* some compilers complain in signal calls. */
10759 /* USG systems forget handlers when they are used;
10760 must reestablish each time */
10761 signal (signalnum
, x_connection_signal
);
10765 /* Handling X errors. */
10767 /* Handle the loss of connection to display DISPLAY. */
10770 x_connection_closed (display
, error_message
)
10772 char *error_message
;
10774 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
10775 Lisp_Object frame
, tail
;
10777 /* Indicate that this display is dead. */
10779 #if 0 /* Closing the display caused a bus error on OpenWindows. */
10780 #ifdef USE_X_TOOLKIT
10781 XtCloseDisplay (display
);
10785 dpyinfo
->display
= 0;
10787 /* First delete frames whose mini-buffers are on frames
10788 that are on the dead display. */
10789 FOR_EACH_FRAME (tail
, frame
)
10791 Lisp_Object minibuf_frame
;
10793 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
10794 if (FRAME_X_P (XFRAME (frame
))
10795 && FRAME_X_P (XFRAME (minibuf_frame
))
10796 && ! EQ (frame
, minibuf_frame
)
10797 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
10798 Fdelete_frame (frame
, Qt
);
10801 /* Now delete all remaining frames on the dead display.
10802 We are now sure none of these is used as the mini-buffer
10803 for another frame that we need to delete. */
10804 FOR_EACH_FRAME (tail
, frame
)
10805 if (FRAME_X_P (XFRAME (frame
))
10806 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
10808 /* Set this to t so that Fdelete_frame won't get confused
10809 trying to find a replacement. */
10810 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
10811 Fdelete_frame (frame
, Qt
);
10815 x_delete_display (dpyinfo
);
10817 if (x_display_list
== 0)
10819 fprintf (stderr
, "%s\n", error_message
);
10820 shut_down_emacs (0, 0, Qnil
);
10824 /* Ordinary stack unwind doesn't deal with these. */
10826 sigunblock (sigmask (SIGIO
));
10828 sigunblock (sigmask (SIGALRM
));
10829 TOTALLY_UNBLOCK_INPUT
;
10831 clear_waiting_for_input ();
10832 error ("%s", error_message
);
10835 /* This is the usual handler for X protocol errors.
10836 It kills all frames on the display that we got the error for.
10837 If that was the only one, it prints an error message and kills Emacs. */
10840 x_error_quitter (display
, error
)
10842 XErrorEvent
*error
;
10844 char buf
[256], buf1
[356];
10846 /* Note that there is no real way portable across R3/R4 to get the
10847 original error handler. */
10849 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
10850 sprintf (buf1
, "X protocol error: %s on protocol request %d",
10851 buf
, error
->request_code
);
10852 x_connection_closed (display
, buf1
);
10855 /* This is the first-level handler for X protocol errors.
10856 It calls x_error_quitter or x_error_catcher. */
10859 x_error_handler (display
, error
)
10861 XErrorEvent
*error
;
10863 if (! NILP (x_error_message_string
))
10864 x_error_catcher (display
, error
);
10866 x_error_quitter (display
, error
);
10870 /* This is the handler for X IO errors, always.
10871 It kills all frames on the display that we lost touch with.
10872 If that was the only one, it prints an error message and kills Emacs. */
10875 x_io_error_quitter (display
)
10880 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
10881 x_connection_closed (display
, buf
);
10885 /* Changing the font of the frame. */
10887 /* Give frame F the font named FONTNAME as its default font, and
10888 return the full name of that font. FONTNAME may be a wildcard
10889 pattern; in that case, we choose some font that fits the pattern.
10890 The return value shows which font we chose. */
10893 x_new_font (f
, fontname
)
10895 register char *fontname
;
10897 struct font_info
*fontp
10898 = FS_LOAD_FONT (f
, 0, fontname
, -1);
10903 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
10904 f
->output_data
.x
->baseline_offset
= fontp
->baseline_offset
;
10905 f
->output_data
.x
->fontset
= -1;
10907 /* Compute the scroll bar width in character columns. */
10908 if (f
->scroll_bar_pixel_width
> 0)
10910 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10911 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
10915 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10916 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
10919 /* Now make the frame display the given font. */
10920 if (FRAME_X_WINDOW (f
) != 0)
10922 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
10923 f
->output_data
.x
->font
->fid
);
10924 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
10925 f
->output_data
.x
->font
->fid
);
10926 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
10927 f
->output_data
.x
->font
->fid
);
10929 frame_update_line_height (f
);
10930 x_set_window_size (f
, 0, f
->width
, f
->height
);
10933 /* If we are setting a new frame's font for the first time,
10934 there are no faces yet, so this font's height is the line height. */
10935 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
10937 return build_string (fontp
->full_name
);
10940 /* Give frame F the fontset named FONTSETNAME as its default font, and
10941 return the full name of that fontset. FONTSETNAME may be a wildcard
10942 pattern; in that case, we choose some fontset that fits the pattern.
10943 The return value shows which fontset we chose. */
10946 x_new_fontset (f
, fontsetname
)
10950 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
10951 Lisp_Object result
;
10957 if (f
->output_data
.x
->fontset
== fontset
)
10958 /* This fontset is already set in frame F. There's nothing more
10960 return fontset_name (fontset
);
10962 result
= x_new_font (f
, (XSTRING (fontset_ascii (fontset
))->data
));
10964 if (!STRINGP (result
))
10965 /* Can't load ASCII font. */
10968 /* Since x_new_font doesn't update any fontset information, do it now. */
10969 f
->output_data
.x
->fontset
= fontset
;
10973 && (FRAME_XIC_STYLE (f
) & (XIMPreeditPosition
| XIMStatusArea
)))
10974 xic_set_xfontset (f
, XSTRING (fontset_ascii (fontset
))->data
);
10977 return build_string (fontsetname
);
10981 /***********************************************************************
10983 ***********************************************************************/
10989 /* XIM destroy callback function, which is called whenever the
10990 connection to input method XIM dies. CLIENT_DATA contains a
10991 pointer to the x_display_info structure corresponding to XIM. */
10994 xim_destroy_callback (xim
, client_data
, call_data
)
10996 XPointer client_data
;
10997 XPointer call_data
;
10999 struct x_display_info
*dpyinfo
= (struct x_display_info
*) client_data
;
11000 Lisp_Object frame
, tail
;
11004 /* No need to call XDestroyIC.. */
11005 FOR_EACH_FRAME (tail
, frame
)
11007 struct frame
*f
= XFRAME (frame
);
11008 if (FRAME_X_DISPLAY_INFO (f
) == dpyinfo
)
11010 FRAME_XIC (f
) = NULL
;
11011 if (FRAME_XIC_FONTSET (f
))
11013 XFreeFontSet (FRAME_X_DISPLAY (f
), FRAME_XIC_FONTSET (f
));
11014 FRAME_XIC_FONTSET (f
) = NULL
;
11019 /* No need to call XCloseIM. */
11020 dpyinfo
->xim
= NULL
;
11021 XFree (dpyinfo
->xim_styles
);
11025 #endif /* HAVE_X11R6 */
11027 /* Open the connection to the XIM server on display DPYINFO.
11028 RESOURCE_NAME is the resource name Emacs uses. */
11031 xim_open_dpy (dpyinfo
, resource_name
)
11032 struct x_display_info
*dpyinfo
;
11033 char *resource_name
;
11037 xim
= XOpenIM (dpyinfo
->display
, dpyinfo
->xrdb
, resource_name
, EMACS_CLASS
);
11038 dpyinfo
->xim
= xim
;
11043 XIMCallback destroy
;
11046 /* Get supported styles and XIM values. */
11047 XGetIMValues (xim
, XNQueryInputStyle
, &dpyinfo
->xim_styles
, NULL
);
11050 destroy
.callback
= xim_destroy_callback
;
11051 destroy
.client_data
= (XPointer
)dpyinfo
;
11052 XSetIMValues (xim
, XNDestroyCallback
, &destroy
, NULL
);
11058 #ifdef HAVE_X11R6_XIM
11062 struct x_display_info
*dpyinfo
;
11063 char *resource_name
;
11066 /* XIM instantiate callback function, which is called whenever an XIM
11067 server is available. DISPLAY is teh display of the XIM.
11068 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11069 when the callback was registered. */
11072 xim_instantiate_callback (display
, client_data
, call_data
)
11074 XPointer client_data
;
11075 XPointer call_data
;
11077 struct xim_inst_t
*xim_inst
= (struct xim_inst_t
*) client_data
;
11078 struct x_display_info
*dpyinfo
= xim_inst
->dpyinfo
;
11080 /* We don't support multiple XIM connections. */
11084 xim_open_dpy (dpyinfo
, xim_inst
->resource_name
);
11086 /* Create XIC for the existing frames on the same display, as long
11087 as they have no XIC. */
11088 if (dpyinfo
->xim
&& dpyinfo
->reference_count
> 0)
11090 Lisp_Object tail
, frame
;
11093 FOR_EACH_FRAME (tail
, frame
)
11095 struct frame
*f
= XFRAME (frame
);
11097 if (FRAME_X_DISPLAY_INFO (f
) == xim_inst
->dpyinfo
)
11098 if (FRAME_XIC (f
) == NULL
)
11100 create_frame_xic (f
);
11101 if (FRAME_XIC_STYLE (f
) & XIMStatusArea
)
11102 xic_set_statusarea (f
);
11103 if (FRAME_XIC_STYLE (f
) & XIMPreeditPosition
)
11105 struct window
*w
= XWINDOW (f
->selected_window
);
11106 xic_set_preeditarea (w
, w
->cursor
.x
, w
->cursor
.y
);
11115 #endif /* HAVE_X11R6_XIM */
11118 /* Open a connection to the XIM server on display DPYINFO.
11119 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11120 connection only at the first time. On X11R6, open the connection
11121 in the XIM instantiate callback function. */
11124 xim_initialize (dpyinfo
, resource_name
)
11125 struct x_display_info
*dpyinfo
;
11126 char *resource_name
;
11128 #ifdef HAVE_X11R6_XIM
11129 struct xim_inst_t
*xim_inst
;
11132 dpyinfo
->xim
= NULL
;
11133 xim_inst
= (struct xim_inst_t
*) xmalloc (sizeof (struct xim_inst_t
));
11134 xim_inst
->dpyinfo
= dpyinfo
;
11135 len
= strlen (resource_name
);
11136 xim_inst
->resource_name
= (char *) xmalloc (len
+ 1);
11137 bcopy (resource_name
, xim_inst
->resource_name
, len
+ 1);
11138 XRegisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
11139 resource_name
, EMACS_CLASS
,
11140 xim_instantiate_callback
,
11141 (XPointer
)xim_inst
);
11142 #else /* not HAVE_X11R6_XIM */
11143 dpyinfo
->xim
= NULL
;
11144 xim_open_dpy (dpyinfo
, resource_name
);
11145 #endif /* not HAVE_X11R6_XIM */
11149 /* Close the connection to the XIM server on display DPYINFO. */
11152 xim_close_dpy (dpyinfo
)
11153 struct x_display_info
*dpyinfo
;
11155 #ifdef HAVE_X11R6_XIM
11156 XUnregisterIMInstantiateCallback (dpyinfo
->display
, dpyinfo
->xrdb
,
11158 xim_instantiate_callback
, NULL
);
11159 #endif /* not HAVE_X11R6_XIM */
11160 XCloseIM (dpyinfo
->xim
);
11161 dpyinfo
->xim
= NULL
;
11162 XFree (dpyinfo
->xim_styles
);
11165 #endif /* not HAVE_X11R6_XIM */
11169 /* Calculate the absolute position in frame F
11170 from its current recorded position values and gravity. */
11173 x_calc_absolute_position (f
)
11177 int win_x
= 0, win_y
= 0;
11178 int flags
= f
->output_data
.x
->size_hint_flags
;
11181 /* We have nothing to do if the current position
11182 is already for the top-left corner. */
11183 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
11186 #ifdef USE_X_TOOLKIT
11187 this_window
= XtWindow (f
->output_data
.x
->widget
);
11189 this_window
= FRAME_X_WINDOW (f
);
11192 /* Find the position of the outside upper-left corner of
11193 the inner window, with respect to the outer window.
11194 But do this only if we will need the results. */
11195 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
11200 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
11203 x_clear_errors (FRAME_X_DISPLAY (f
));
11204 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
11206 /* From-window, to-window. */
11208 f
->output_data
.x
->parent_desc
,
11210 /* From-position, to-position. */
11211 0, 0, &win_x
, &win_y
,
11213 /* Child of win. */
11215 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
11217 Window newroot
, newparent
= 0xdeadbeef;
11218 Window
*newchildren
;
11221 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
11222 &newparent
, &newchildren
, &nchildren
))
11225 XFree ((char *) newchildren
);
11227 f
->output_data
.x
->parent_desc
= newparent
;
11233 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
11237 /* Treat negative positions as relative to the leftmost bottommost
11238 position that fits on the screen. */
11239 if (flags
& XNegative
)
11240 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
11241 - 2 * f
->output_data
.x
->border_width
- win_x
11243 + f
->output_data
.x
->left_pos
);
11245 if (flags
& YNegative
)
11247 int menubar_height
= 0;
11249 #ifdef USE_X_TOOLKIT
11250 if (f
->output_data
.x
->menubar_widget
)
11252 = (f
->output_data
.x
->menubar_widget
->core
.height
11253 + f
->output_data
.x
->menubar_widget
->core
.border_width
);
11256 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
11257 - 2 * f
->output_data
.x
->border_width
11261 + f
->output_data
.x
->top_pos
);
11264 /* The left_pos and top_pos
11265 are now relative to the top and left screen edges,
11266 so the flags should correspond. */
11267 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
11270 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11271 to really change the position, and 0 when calling from
11272 x_make_frame_visible (in that case, XOFF and YOFF are the current
11273 position values). It is -1 when calling from x_set_frame_parameters,
11274 which means, do adjust for borders but don't change the gravity. */
11277 x_set_offset (f
, xoff
, yoff
, change_gravity
)
11279 register int xoff
, yoff
;
11280 int change_gravity
;
11282 int modified_top
, modified_left
;
11284 if (change_gravity
> 0)
11286 f
->output_data
.x
->top_pos
= yoff
;
11287 f
->output_data
.x
->left_pos
= xoff
;
11288 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
11290 f
->output_data
.x
->size_hint_flags
|= XNegative
;
11292 f
->output_data
.x
->size_hint_flags
|= YNegative
;
11293 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11295 x_calc_absolute_position (f
);
11298 x_wm_set_size_hint (f
, (long) 0, 0);
11300 modified_left
= f
->output_data
.x
->left_pos
;
11301 modified_top
= f
->output_data
.x
->top_pos
;
11302 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11303 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11304 /* It is a mystery why we need to add the border_width here
11305 when the frame is already visible, but experiment says we do. */
11306 if (change_gravity
!= 0)
11308 modified_left
+= f
->output_data
.x
->border_width
;
11309 modified_top
+= f
->output_data
.x
->border_width
;
11313 #ifdef USE_X_TOOLKIT
11314 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
11315 modified_left
, modified_top
);
11316 #else /* not USE_X_TOOLKIT */
11317 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11318 modified_left
, modified_top
);
11319 #endif /* not USE_X_TOOLKIT */
11323 /* Call this to change the size of frame F's x-window.
11324 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11325 for this size change and subsequent size changes.
11326 Otherwise we leave the window gravity unchanged. */
11329 x_set_window_size (f
, change_gravity
, cols
, rows
)
11331 int change_gravity
;
11334 #ifndef USE_X_TOOLKIT
11335 int pixelwidth
, pixelheight
;
11340 #ifdef USE_X_TOOLKIT
11342 /* The x and y position of the widget is clobbered by the
11343 call to XtSetValues within EmacsFrameSetCharSize.
11344 This is a real kludge, but I don't understand Xt so I can't
11345 figure out a correct fix. Can anyone else tell me? -- rms. */
11346 int xpos
= f
->output_data
.x
->widget
->core
.x
;
11347 int ypos
= f
->output_data
.x
->widget
->core
.y
;
11348 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
11349 f
->output_data
.x
->widget
->core
.x
= xpos
;
11350 f
->output_data
.x
->widget
->core
.y
= ypos
;
11353 #else /* not USE_X_TOOLKIT */
11355 check_frame_size (f
, &rows
, &cols
);
11356 f
->output_data
.x
->vertical_scroll_bar_extra
11357 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
11359 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
11360 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
11361 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
11362 f
->output_data
.x
->flags_areas_extra
11363 = FRAME_FLAGS_AREA_WIDTH (f
);
11364 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
11365 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
11367 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11368 x_wm_set_size_hint (f
, (long) 0, 0);
11370 XSync (FRAME_X_DISPLAY (f
), False
);
11371 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11372 pixelwidth
, pixelheight
);
11374 /* Now, strictly speaking, we can't be sure that this is accurate,
11375 but the window manager will get around to dealing with the size
11376 change request eventually, and we'll hear how it went when the
11377 ConfigureNotify event gets here.
11379 We could just not bother storing any of this information here,
11380 and let the ConfigureNotify event set everything up, but that
11381 might be kind of confusing to the Lisp code, since size changes
11382 wouldn't be reported in the frame parameters until some random
11383 point in the future when the ConfigureNotify event arrives.
11385 We pass 1 for DELAY since we can't run Lisp code inside of
11387 change_frame_size (f
, rows
, cols
, 0, 1, 0);
11388 PIXEL_WIDTH (f
) = pixelwidth
;
11389 PIXEL_HEIGHT (f
) = pixelheight
;
11391 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11392 receive in the ConfigureNotify event; if we get what we asked
11393 for, then the event won't cause the screen to become garbaged, so
11394 we have to make sure to do it here. */
11395 SET_FRAME_GARBAGED (f
);
11397 XFlush (FRAME_X_DISPLAY (f
));
11399 #endif /* not USE_X_TOOLKIT */
11401 /* If cursor was outside the new size, mark it as off. */
11402 mark_window_cursors_off (XWINDOW (f
->root_window
));
11404 /* Clear out any recollection of where the mouse highlighting was,
11405 since it might be in a place that's outside the new frame size.
11406 Actually checking whether it is outside is a pain in the neck,
11407 so don't try--just let the highlighting be done afresh with new size. */
11408 cancel_mouse_face (f
);
11413 /* Mouse warping. */
11416 x_set_mouse_position (f
, x
, y
)
11422 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
11423 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
11425 if (pix_x
< 0) pix_x
= 0;
11426 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
11428 if (pix_y
< 0) pix_y
= 0;
11429 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
11433 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11434 0, 0, 0, 0, pix_x
, pix_y
);
11438 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11441 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
11447 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11448 0, 0, 0, 0, pix_x
, pix_y
);
11452 /* focus shifting, raising and lowering. */
11455 x_focus_on_frame (f
)
11458 #if 0 /* This proves to be unpleasant. */
11462 /* I don't think that the ICCCM allows programs to do things like this
11463 without the interaction of the window manager. Whatever you end up
11464 doing with this code, do it to x_unfocus_frame too. */
11465 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11466 RevertToPointerRoot
, CurrentTime
);
11471 x_unfocus_frame (f
)
11475 /* Look at the remarks in x_focus_on_frame. */
11476 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
11477 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
11478 RevertToPointerRoot
, CurrentTime
);
11482 /* Raise frame F. */
11488 if (f
->async_visible
)
11491 #ifdef USE_X_TOOLKIT
11492 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11493 #else /* not USE_X_TOOLKIT */
11494 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11495 #endif /* not USE_X_TOOLKIT */
11496 XFlush (FRAME_X_DISPLAY (f
));
11501 /* Lower frame F. */
11507 if (f
->async_visible
)
11510 #ifdef USE_X_TOOLKIT
11511 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11512 #else /* not USE_X_TOOLKIT */
11513 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11514 #endif /* not USE_X_TOOLKIT */
11515 XFlush (FRAME_X_DISPLAY (f
));
11521 XTframe_raise_lower (f
, raise_flag
)
11531 /* Change of visibility. */
11533 /* This tries to wait until the frame is really visible.
11534 However, if the window manager asks the user where to position
11535 the frame, this will return before the user finishes doing that.
11536 The frame will not actually be visible at that time,
11537 but it will become visible later when the window manager
11538 finishes with it. */
11541 x_make_frame_visible (f
)
11545 int original_top
, original_left
;
11549 type
= x_icon_type (f
);
11551 x_bitmap_icon (f
, type
);
11553 if (! FRAME_VISIBLE_P (f
))
11555 /* We test FRAME_GARBAGED_P here to make sure we don't
11556 call x_set_offset a second time
11557 if we get to x_make_frame_visible a second time
11558 before the window gets really visible. */
11559 if (! FRAME_ICONIFIED_P (f
)
11560 && ! f
->output_data
.x
->asked_for_visible
)
11561 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11563 f
->output_data
.x
->asked_for_visible
= 1;
11565 if (! EQ (Vx_no_window_manager
, Qt
))
11566 x_wm_set_window_state (f
, NormalState
);
11567 #ifdef USE_X_TOOLKIT
11568 /* This was XtPopup, but that did nothing for an iconified frame. */
11569 XtMapWidget (f
->output_data
.x
->widget
);
11570 #else /* not USE_X_TOOLKIT */
11571 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11572 #endif /* not USE_X_TOOLKIT */
11573 #if 0 /* This seems to bring back scroll bars in the wrong places
11574 if the window configuration has changed. They seem
11575 to come back ok without this. */
11576 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
11577 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11581 XFlush (FRAME_X_DISPLAY (f
));
11583 /* Synchronize to ensure Emacs knows the frame is visible
11584 before we do anything else. We do this loop with input not blocked
11585 so that incoming events are handled. */
11589 /* This must be before UNBLOCK_INPUT
11590 since events that arrive in response to the actions above
11591 will set it when they are handled. */
11592 int previously_visible
= f
->output_data
.x
->has_been_visible
;
11594 original_left
= f
->output_data
.x
->left_pos
;
11595 original_top
= f
->output_data
.x
->top_pos
;
11597 /* This must come after we set COUNT. */
11600 /* We unblock here so that arriving X events are processed. */
11602 /* Now move the window back to where it was "supposed to be".
11603 But don't do it if the gravity is negative.
11604 When the gravity is negative, this uses a position
11605 that is 3 pixels too low. Perhaps that's really the border width.
11607 Don't do this if the window has never been visible before,
11608 because the window manager may choose the position
11609 and we don't want to override it. */
11611 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
11612 && f
->output_data
.x
->win_gravity
== NorthWestGravity
11613 && previously_visible
)
11617 unsigned int width
, height
, border
, depth
;
11621 /* On some window managers (such as FVWM) moving an existing
11622 window, even to the same place, causes the window manager
11623 to introduce an offset. This can cause the window to move
11624 to an unexpected location. Check the geometry (a little
11625 slow here) and then verify that the window is in the right
11626 place. If the window is not in the right place, move it
11627 there, and take the potential window manager hit. */
11628 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11629 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
11631 if (original_left
!= x
|| original_top
!= y
)
11632 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11633 original_left
, original_top
);
11638 XSETFRAME (frame
, f
);
11640 /* Wait until the frame is visible. Process X events until a
11641 MapNotify event has been seen, or until we think we won't get a
11642 MapNotify at all.. */
11643 for (count
= input_signal_count
+ 10;
11644 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
11646 /* Force processing of queued events. */
11649 /* Machines that do polling rather than SIGIO have been
11650 observed to go into a busy-wait here. So we'll fake an
11651 alarm signal to let the handler know that there's something
11652 to be read. We used to raise a real alarm, but it seems
11653 that the handler isn't always enabled here. This is
11655 if (input_polling_used ())
11657 /* It could be confusing if a real alarm arrives while
11658 processing the fake one. Turn it off and let the
11659 handler reset it. */
11660 int old_poll_suppress_count
= poll_suppress_count
;
11661 poll_suppress_count
= 1;
11662 poll_for_input_1 ();
11663 poll_suppress_count
= old_poll_suppress_count
;
11666 /* See if a MapNotify event has been processed. */
11667 FRAME_SAMPLE_VISIBILITY (f
);
11672 /* Change from mapped state to withdrawn state. */
11674 /* Make the frame visible (mapped and not iconified). */
11677 x_make_frame_invisible (f
)
11682 #ifdef USE_X_TOOLKIT
11683 /* Use the frame's outermost window, not the one we normally draw on. */
11684 window
= XtWindow (f
->output_data
.x
->widget
);
11685 #else /* not USE_X_TOOLKIT */
11686 window
= FRAME_X_WINDOW (f
);
11687 #endif /* not USE_X_TOOLKIT */
11689 /* Don't keep the highlight on an invisible frame. */
11690 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11691 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11693 #if 0/* This might add unreliability; I don't trust it -- rms. */
11694 if (! f
->async_visible
&& ! f
->async_iconified
)
11700 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11701 that the current position of the window is user-specified, rather than
11702 program-specified, so that when the window is mapped again, it will be
11703 placed at the same location, without forcing the user to position it
11704 by hand again (they have already done that once for this window.) */
11705 x_wm_set_size_hint (f
, (long) 0, 1);
11709 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11710 DefaultScreen (FRAME_X_DISPLAY (f
))))
11712 UNBLOCK_INPUT_RESIGNAL
;
11713 error ("Can't notify window manager of window withdrawal");
11715 #else /* ! defined (HAVE_X11R4) */
11717 /* Tell the window manager what we're going to do. */
11718 if (! EQ (Vx_no_window_manager
, Qt
))
11722 unmap
.xunmap
.type
= UnmapNotify
;
11723 unmap
.xunmap
.window
= window
;
11724 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
11725 unmap
.xunmap
.from_configure
= False
;
11726 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11727 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11729 SubstructureRedirectMaskSubstructureNotifyMask
,
11732 UNBLOCK_INPUT_RESIGNAL
;
11733 error ("Can't notify window manager of withdrawal");
11737 /* Unmap the window ourselves. Cheeky! */
11738 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
11739 #endif /* ! defined (HAVE_X11R4) */
11741 /* We can't distinguish this from iconification
11742 just by the event that we get from the server.
11743 So we can't win using the usual strategy of letting
11744 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11745 and synchronize with the server to make sure we agree. */
11747 FRAME_ICONIFIED_P (f
) = 0;
11748 f
->async_visible
= 0;
11749 f
->async_iconified
= 0;
11756 /* Change window state from mapped to iconified. */
11759 x_iconify_frame (f
)
11765 /* Don't keep the highlight on an invisible frame. */
11766 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11767 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11769 if (f
->async_iconified
)
11774 FRAME_SAMPLE_VISIBILITY (f
);
11776 type
= x_icon_type (f
);
11778 x_bitmap_icon (f
, type
);
11780 #ifdef USE_X_TOOLKIT
11782 if (! FRAME_VISIBLE_P (f
))
11784 if (! EQ (Vx_no_window_manager
, Qt
))
11785 x_wm_set_window_state (f
, IconicState
);
11786 /* This was XtPopup, but that did nothing for an iconified frame. */
11787 XtMapWidget (f
->output_data
.x
->widget
);
11788 /* The server won't give us any event to indicate
11789 that an invisible frame was changed to an icon,
11790 so we have to record it here. */
11793 f
->async_iconified
= 1;
11794 f
->async_visible
= 0;
11799 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11800 XtWindow (f
->output_data
.x
->widget
),
11801 DefaultScreen (FRAME_X_DISPLAY (f
)));
11805 error ("Can't notify window manager of iconification");
11807 f
->async_iconified
= 1;
11808 f
->async_visible
= 0;
11812 XFlush (FRAME_X_DISPLAY (f
));
11814 #else /* not USE_X_TOOLKIT */
11816 /* Make sure the X server knows where the window should be positioned,
11817 in case the user deiconifies with the window manager. */
11818 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
11819 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11821 /* Since we don't know which revision of X we're running, we'll use both
11822 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11824 /* X11R4: send a ClientMessage to the window manager using the
11825 WM_CHANGE_STATE type. */
11829 message
.xclient
.window
= FRAME_X_WINDOW (f
);
11830 message
.xclient
.type
= ClientMessage
;
11831 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
11832 message
.xclient
.format
= 32;
11833 message
.xclient
.data
.l
[0] = IconicState
;
11835 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11836 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11838 SubstructureRedirectMask
| SubstructureNotifyMask
,
11841 UNBLOCK_INPUT_RESIGNAL
;
11842 error ("Can't notify window manager of iconification");
11846 /* X11R3: set the initial_state field of the window manager hints to
11848 x_wm_set_window_state (f
, IconicState
);
11850 if (!FRAME_VISIBLE_P (f
))
11852 /* If the frame was withdrawn, before, we must map it. */
11853 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11856 f
->async_iconified
= 1;
11857 f
->async_visible
= 0;
11859 XFlush (FRAME_X_DISPLAY (f
));
11861 #endif /* not USE_X_TOOLKIT */
11864 /* Destroy the X window of frame F. */
11867 x_destroy_window (f
)
11870 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11874 /* If a display connection is dead, don't try sending more
11875 commands to the X server. */
11876 if (dpyinfo
->display
!= 0)
11878 if (f
->output_data
.x
->icon_desc
!= 0)
11879 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
11882 free_frame_xic (f
);
11884 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
11885 #ifdef USE_X_TOOLKIT
11886 if (f
->output_data
.x
->widget
)
11887 XtDestroyWidget (f
->output_data
.x
->widget
);
11888 free_frame_menubar (f
);
11889 #endif /* USE_X_TOOLKIT */
11891 free_frame_faces (f
);
11892 XFlush (FRAME_X_DISPLAY (f
));
11895 if (f
->output_data
.x
->saved_menu_event
)
11896 xfree (f
->output_data
.x
->saved_menu_event
);
11898 xfree (f
->output_data
.x
);
11899 f
->output_data
.x
= 0;
11900 if (f
== dpyinfo
->x_focus_frame
)
11901 dpyinfo
->x_focus_frame
= 0;
11902 if (f
== dpyinfo
->x_focus_event_frame
)
11903 dpyinfo
->x_focus_event_frame
= 0;
11904 if (f
== dpyinfo
->x_highlight_frame
)
11905 dpyinfo
->x_highlight_frame
= 0;
11907 dpyinfo
->reference_count
--;
11909 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11911 dpyinfo
->mouse_face_beg_row
11912 = dpyinfo
->mouse_face_beg_col
= -1;
11913 dpyinfo
->mouse_face_end_row
11914 = dpyinfo
->mouse_face_end_col
= -1;
11915 dpyinfo
->mouse_face_window
= Qnil
;
11916 dpyinfo
->mouse_face_deferred_gc
= 0;
11917 dpyinfo
->mouse_face_mouse_frame
= 0;
11923 /* Setting window manager hints. */
11925 /* Set the normal size hints for the window manager, for frame F.
11926 FLAGS is the flags word to use--or 0 meaning preserve the flags
11927 that the window now has.
11928 If USER_POSITION is nonzero, we set the USPosition
11929 flag (this is useful when FLAGS is 0). */
11932 x_wm_set_size_hint (f
, flags
, user_position
)
11937 XSizeHints size_hints
;
11939 #ifdef USE_X_TOOLKIT
11942 Dimension widget_width
, widget_height
;
11943 Window window
= XtWindow (f
->output_data
.x
->widget
);
11944 #else /* not USE_X_TOOLKIT */
11945 Window window
= FRAME_X_WINDOW (f
);
11946 #endif /* not USE_X_TOOLKIT */
11948 /* Setting PMaxSize caused various problems. */
11949 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
11951 size_hints
.x
= f
->output_data
.x
->left_pos
;
11952 size_hints
.y
= f
->output_data
.x
->top_pos
;
11954 #ifdef USE_X_TOOLKIT
11955 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
11956 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
11957 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
11958 size_hints
.height
= widget_height
;
11959 size_hints
.width
= widget_width
;
11960 #else /* not USE_X_TOOLKIT */
11961 size_hints
.height
= PIXEL_HEIGHT (f
);
11962 size_hints
.width
= PIXEL_WIDTH (f
);
11963 #endif /* not USE_X_TOOLKIT */
11965 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
11966 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
11967 size_hints
.max_width
11968 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
11969 size_hints
.max_height
11970 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
11972 /* Calculate the base and minimum sizes.
11974 (When we use the X toolkit, we don't do it here.
11975 Instead we copy the values that the widgets are using, below.) */
11976 #ifndef USE_X_TOOLKIT
11978 int base_width
, base_height
;
11979 int min_rows
= 0, min_cols
= 0;
11981 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
11982 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
11984 check_frame_size (f
, &min_rows
, &min_cols
);
11986 /* The window manager uses the base width hints to calculate the
11987 current number of rows and columns in the frame while
11988 resizing; min_width and min_height aren't useful for this
11989 purpose, since they might not give the dimensions for a
11990 zero-row, zero-column frame.
11992 We use the base_width and base_height members if we have
11993 them; otherwise, we set the min_width and min_height members
11994 to the size for a zero x zero frame. */
11997 size_hints
.flags
|= PBaseSize
;
11998 size_hints
.base_width
= base_width
;
11999 size_hints
.base_height
= base_height
;
12000 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
12001 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
12003 size_hints
.min_width
= base_width
;
12004 size_hints
.min_height
= base_height
;
12008 /* If we don't need the old flags, we don't need the old hint at all. */
12011 size_hints
.flags
|= flags
;
12014 #endif /* not USE_X_TOOLKIT */
12017 XSizeHints hints
; /* Sometimes I hate X Windows... */
12018 long supplied_return
;
12022 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
12025 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
12028 #ifdef USE_X_TOOLKIT
12029 size_hints
.base_height
= hints
.base_height
;
12030 size_hints
.base_width
= hints
.base_width
;
12031 size_hints
.min_height
= hints
.min_height
;
12032 size_hints
.min_width
= hints
.min_width
;
12036 size_hints
.flags
|= flags
;
12041 if (hints
.flags
& PSize
)
12042 size_hints
.flags
|= PSize
;
12043 if (hints
.flags
& PPosition
)
12044 size_hints
.flags
|= PPosition
;
12045 if (hints
.flags
& USPosition
)
12046 size_hints
.flags
|= USPosition
;
12047 if (hints
.flags
& USSize
)
12048 size_hints
.flags
|= USSize
;
12052 #ifndef USE_X_TOOLKIT
12057 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
12058 size_hints
.flags
|= PWinGravity
;
12062 size_hints
.flags
&= ~ PPosition
;
12063 size_hints
.flags
|= USPosition
;
12065 #endif /* PWinGravity */
12068 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
12070 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
12074 /* Used for IconicState or NormalState */
12077 x_wm_set_window_state (f
, state
)
12081 #ifdef USE_X_TOOLKIT
12084 XtSetArg (al
[0], XtNinitialState
, state
);
12085 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
12086 #else /* not USE_X_TOOLKIT */
12087 Window window
= FRAME_X_WINDOW (f
);
12089 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
12090 f
->output_data
.x
->wm_hints
.initial_state
= state
;
12092 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
12093 #endif /* not USE_X_TOOLKIT */
12097 x_wm_set_icon_pixmap (f
, pixmap_id
)
12101 Pixmap icon_pixmap
;
12103 #ifndef USE_X_TOOLKIT
12104 Window window
= FRAME_X_WINDOW (f
);
12109 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
12110 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
12114 /* It seems there is no way to turn off use of an icon pixmap.
12115 The following line does it, only if no icon has yet been created,
12116 for some window managers. But with mwm it crashes.
12117 Some people say it should clear the IconPixmapHint bit in this case,
12118 but that doesn't work, and the X consortium said it isn't the
12119 right thing at all. Since there is no way to win,
12120 best to explicitly give up. */
12122 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
12128 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12132 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
12133 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
12136 #else /* not USE_X_TOOLKIT */
12138 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
12139 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
12141 #endif /* not USE_X_TOOLKIT */
12145 x_wm_set_icon_position (f
, icon_x
, icon_y
)
12147 int icon_x
, icon_y
;
12149 #ifdef USE_X_TOOLKIT
12150 Window window
= XtWindow (f
->output_data
.x
->widget
);
12152 Window window
= FRAME_X_WINDOW (f
);
12155 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
12156 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
12157 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
12159 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
12163 /***********************************************************************
12165 ***********************************************************************/
12167 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12170 x_get_font_info (f
, font_idx
)
12174 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
12178 /* Return a list of names of available fonts matching PATTERN on frame
12179 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12180 to be listed. Frame F NULL means we have not yet created any
12181 frame on X, and consult the first display in x_display_list.
12182 MAXNAMES sets a limit on how many fonts to match. */
12185 x_list_fonts (f
, pattern
, size
, maxnames
)
12187 Lisp_Object pattern
;
12191 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
12192 Lisp_Object tem
, second_best
;
12193 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
12194 int try_XLoadQueryFont
= 0;
12197 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
12198 if (NILP (patterns
))
12199 patterns
= Fcons (pattern
, Qnil
);
12201 if (maxnames
== 1 && !size
)
12202 /* We can return any single font matching PATTERN. */
12203 try_XLoadQueryFont
= 1;
12205 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
12210 pattern
= XCAR (patterns
);
12211 /* See if we cached the result for this particular query.
12212 The cache is an alist of the form:
12213 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12215 if (f
&& (tem
= XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
),
12216 key
= Fcons (pattern
, make_number (maxnames
)),
12217 !NILP (list
= Fassoc (key
, tem
))))
12219 list
= Fcdr_safe (list
);
12220 /* We have a cashed list. Don't have to get the list again. */
12224 /* At first, put PATTERN in the cache. */
12227 count
= x_catch_errors (dpy
);
12229 if (try_XLoadQueryFont
)
12232 unsigned long value
;
12234 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
12235 if (x_had_errors_p (dpy
))
12237 /* This error is perhaps due to insufficient memory on X
12238 server. Let's just ignore it. */
12240 x_clear_errors (dpy
);
12244 && XGetFontProperty (font
, XA_FONT
, &value
))
12246 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
12247 int len
= strlen (name
);
12250 /* If DXPC (a Differential X Protocol Compressor)
12251 Ver.3.7 is running, XGetAtomName will return null
12252 string. We must avoid such a name. */
12254 try_XLoadQueryFont
= 0;
12258 names
= (char **) alloca (sizeof (char *));
12259 /* Some systems only allow alloca assigned to a
12261 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
12262 bcopy (name
, names
[0], len
+ 1);
12267 try_XLoadQueryFont
= 0;
12270 XFreeFont (dpy
, font
);
12273 if (!try_XLoadQueryFont
)
12275 /* We try at least 10 fonts because XListFonts will return
12276 auto-scaled fonts at the head. */
12277 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
12279 if (x_had_errors_p (dpy
))
12281 /* This error is perhaps due to insufficient memory on X
12282 server. Let's just ignore it. */
12284 x_clear_errors (dpy
);
12288 x_uncatch_errors (dpy
, count
);
12295 /* Make a list of all the fonts we got back.
12296 Store that in the font cache for the display. */
12297 for (i
= 0; i
< num_fonts
; i
++)
12300 char *p
= names
[i
];
12301 int average_width
= -1, dashes
= 0;
12303 /* Count the number of dashes in NAMES[I]. If there are
12304 14 dashes, and the field value following 12th dash
12305 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12306 is usually too ugly to be used for editing. Let's
12312 if (dashes
== 7) /* PIXEL_SIZE field */
12314 else if (dashes
== 12) /* AVERAGE_WIDTH field */
12315 average_width
= atoi (p
);
12317 if (dashes
< 14 || average_width
!= 0)
12319 tem
= build_string (names
[i
]);
12320 if (NILP (Fassoc (tem
, list
)))
12322 if (STRINGP (Vx_pixel_size_width_font_regexp
)
12323 && ((fast_c_string_match_ignore_case
12324 (Vx_pixel_size_width_font_regexp
, names
[i
]))
12326 /* We can set the value of PIXEL_SIZE to the
12327 width of this font. */
12328 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
12330 /* For the moment, width is not known. */
12331 list
= Fcons (Fcons (tem
, Qnil
), list
);
12335 if (!try_XLoadQueryFont
)
12336 XFreeFontNames (names
);
12339 /* Now store the result in the cache. */
12341 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)
12342 = Fcons (Fcons (key
, list
),
12343 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
12346 if (NILP (list
)) continue; /* Try the remaining alternatives. */
12348 newlist
= second_best
= Qnil
;
12349 /* Make a list of the fonts that have the right width. */
12350 for (; CONSP (list
); list
= XCDR (list
))
12356 if (!CONSP (tem
) || NILP (XCAR (tem
)))
12360 newlist
= Fcons (XCAR (tem
), newlist
);
12364 if (!INTEGERP (XCDR (tem
)))
12366 /* Since we have not yet known the size of this font, we
12367 must try slow function call XLoadQueryFont. */
12368 XFontStruct
*thisinfo
;
12371 count
= x_catch_errors (dpy
);
12372 thisinfo
= XLoadQueryFont (dpy
,
12373 XSTRING (XCAR (tem
))->data
);
12374 if (x_had_errors_p (dpy
))
12376 /* This error is perhaps due to insufficient memory on X
12377 server. Let's just ignore it. */
12379 x_clear_errors (dpy
);
12381 x_uncatch_errors (dpy
, count
);
12387 = (thisinfo
->min_bounds
.width
== 0
12389 : make_number (thisinfo
->max_bounds
.width
));
12390 XFreeFont (dpy
, thisinfo
);
12393 /* For unknown reason, the previous call of XListFont had
12394 returned a font which can't be opened. Record the size
12395 as 0 not to try to open it again. */
12396 XCDR (tem
) = make_number (0);
12399 found_size
= XINT (XCDR (tem
));
12400 if (found_size
== size
)
12401 newlist
= Fcons (XCAR (tem
), newlist
);
12402 else if (found_size
> 0)
12404 if (NILP (second_best
))
12406 else if (found_size
< size
)
12408 if (XINT (XCDR (second_best
)) > size
12409 || XINT (XCDR (second_best
)) < found_size
)
12414 if (XINT (XCDR (second_best
)) > size
12415 && XINT (XCDR (second_best
)) > found_size
)
12420 if (!NILP (newlist
))
12422 else if (!NILP (second_best
))
12424 newlist
= Fcons (XCAR (second_best
), Qnil
);
12435 /* Check that FONT is valid on frame F. It is if it can be found in F's
12439 x_check_font (f
, font
)
12444 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12446 xassert (font
!= NULL
);
12448 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12449 if (dpyinfo
->font_table
[i
].name
12450 && font
== dpyinfo
->font_table
[i
].font
)
12453 xassert (i
< dpyinfo
->n_fonts
);
12456 #endif /* GLYPH_DEBUG != 0 */
12458 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12459 Note: There are (broken) X fonts out there with invalid XFontStruct
12460 min_bounds contents. For example, handa@etl.go.jp reports that
12461 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12462 have font->min_bounds.width == 0. */
12465 x_font_min_bounds (font
, w
, h
)
12469 *h
= FONT_HEIGHT (font
);
12470 *w
= font
->min_bounds
.width
;
12472 /* Try to handle the case where FONT->min_bounds has invalid
12473 contents. Since the only font known to have invalid min_bounds
12474 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12476 *w
= font
->max_bounds
.width
;
12480 /* Compute the smallest character width and smallest font height over
12481 all fonts available on frame F. Set the members smallest_char_width
12482 and smallest_font_height in F's x_display_info structure to
12483 the values computed. Value is non-zero if smallest_font_height or
12484 smallest_char_width become smaller than they were before. */
12487 x_compute_min_glyph_bounds (f
)
12491 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12493 int old_width
= dpyinfo
->smallest_char_width
;
12494 int old_height
= dpyinfo
->smallest_font_height
;
12496 dpyinfo
->smallest_font_height
= 100000;
12497 dpyinfo
->smallest_char_width
= 100000;
12499 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12500 if (dpyinfo
->font_table
[i
].name
)
12502 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
12505 font
= (XFontStruct
*) fontp
->font
;
12506 xassert (font
!= (XFontStruct
*) ~0);
12507 x_font_min_bounds (font
, &w
, &h
);
12509 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
12510 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
12513 xassert (dpyinfo
->smallest_char_width
> 0
12514 && dpyinfo
->smallest_font_height
> 0);
12516 return (dpyinfo
->n_fonts
== 1
12517 || dpyinfo
->smallest_char_width
< old_width
12518 || dpyinfo
->smallest_font_height
< old_height
);
12522 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12523 pointer to the structure font_info while allocating it dynamically.
12524 If SIZE is 0, load any size of font.
12525 If loading is failed, return NULL. */
12528 x_load_font (f
, fontname
, size
)
12530 register char *fontname
;
12533 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12534 Lisp_Object font_names
;
12537 /* Get a list of all the fonts that match this name. Once we
12538 have a list of matching fonts, we compare them against the fonts
12539 we already have by comparing names. */
12540 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
12542 if (!NILP (font_names
))
12547 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12548 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
12549 if (dpyinfo
->font_table
[i
].name
12550 && (!strcmp (dpyinfo
->font_table
[i
].name
,
12551 XSTRING (XCAR (tail
))->data
)
12552 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
12553 XSTRING (XCAR (tail
))->data
)))
12554 return (dpyinfo
->font_table
+ i
);
12557 /* Load the font and add it to the table. */
12561 struct font_info
*fontp
;
12562 unsigned long value
;
12565 /* If we have found fonts by x_list_font, load one of them. If
12566 not, we still try to load a font by the name given as FONTNAME
12567 because XListFonts (called in x_list_font) of some X server has
12568 a bug of not finding a font even if the font surely exists and
12569 is loadable by XLoadQueryFont. */
12570 if (size
> 0 && !NILP (font_names
))
12571 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
12574 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
12575 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
12576 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
12578 /* This error is perhaps due to insufficient memory on X
12579 server. Let's just ignore it. */
12581 x_clear_errors (FRAME_X_DISPLAY (f
));
12583 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
12588 /* Find a free slot in the font table. */
12589 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12590 if (dpyinfo
->font_table
[i
].name
== NULL
)
12593 /* If no free slot found, maybe enlarge the font table. */
12594 if (i
== dpyinfo
->n_fonts
12595 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
12598 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
12599 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
12600 dpyinfo
->font_table
12601 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
12604 fontp
= dpyinfo
->font_table
+ i
;
12605 if (i
== dpyinfo
->n_fonts
)
12606 ++dpyinfo
->n_fonts
;
12608 /* Now fill in the slots of *FONTP. */
12610 fontp
->font
= font
;
12611 fontp
->font_idx
= i
;
12612 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
12613 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
12615 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12617 if (XGetFontProperty (font
, XA_FONT
, &value
))
12619 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
12623 /* Count the number of dashes in the "full name".
12624 If it is too few, this isn't really the font's full name,
12626 In X11R4, the fonts did not come with their canonical names
12637 full_name
= (char *) xmalloc (p
- name
+ 1);
12638 bcopy (name
, full_name
, p
- name
+ 1);
12644 if (full_name
!= 0)
12645 fontp
->full_name
= full_name
;
12647 fontp
->full_name
= fontp
->name
;
12649 fontp
->size
= font
->max_bounds
.width
;
12650 fontp
->height
= FONT_HEIGHT (font
);
12652 /* For some font, ascent and descent in max_bounds field is
12653 larger than the above value. */
12654 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
12655 if (max_height
> fontp
->height
)
12656 fontp
->height
= max_height
;
12659 if (NILP (font_names
))
12661 /* We come here because of a bug of XListFonts mentioned at
12662 the head of this block. Let's store this information in
12663 the cache for x_list_fonts. */
12664 Lisp_Object lispy_name
= build_string (fontname
);
12665 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
12667 XCDR (dpyinfo
->name_list_element
)
12668 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
12669 Fcons (Fcons (lispy_full_name
,
12670 make_number (fontp
->size
)),
12672 XCDR (dpyinfo
->name_list_element
));
12674 XCDR (dpyinfo
->name_list_element
)
12675 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
12676 Fcons (Fcons (lispy_full_name
,
12677 make_number (fontp
->size
)),
12679 XCDR (dpyinfo
->name_list_element
));
12682 /* The slot `encoding' specifies how to map a character
12683 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12684 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12685 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
12686 2:0xA020..0xFF7F). For the moment, we don't know which charset
12687 uses this font. So, we set information in fontp->encoding[1]
12688 which is never used by any charset. If mapping can't be
12689 decided, set FONT_ENCODING_NOT_DECIDED. */
12691 = (font
->max_byte1
== 0
12693 ? (font
->min_char_or_byte2
< 0x80
12694 ? (font
->max_char_or_byte2
< 0x80
12695 ? 0 /* 0x20..0x7F */
12696 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
12697 : 1) /* 0xA0..0xFF */
12699 : (font
->min_byte1
< 0x80
12700 ? (font
->max_byte1
< 0x80
12701 ? (font
->min_char_or_byte2
< 0x80
12702 ? (font
->max_char_or_byte2
< 0x80
12703 ? 0 /* 0x2020..0x7F7F */
12704 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
12705 : 3) /* 0x20A0..0x7FFF */
12706 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
12707 : (font
->min_char_or_byte2
< 0x80
12708 ? (font
->max_char_or_byte2
< 0x80
12709 ? 2 /* 0xA020..0xFF7F */
12710 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
12711 : 1))); /* 0xA0A0..0xFFFF */
12713 fontp
->baseline_offset
12714 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
12715 ? (long) value
: 0);
12716 fontp
->relative_compose
12717 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
12718 ? (long) value
: 0);
12719 fontp
->default_ascent
12720 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
12721 ? (long) value
: 0);
12723 /* Set global flag fonts_changed_p to non-zero if the font loaded
12724 has a character with a smaller width than any other character
12725 before, or if the font loaded has a smalle>r height than any
12726 other font loaded before. If this happens, it will make a
12727 glyph matrix reallocation necessary. */
12728 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
12735 /* Return a pointer to struct font_info of a font named FONTNAME for
12736 frame F. If no such font is loaded, return NULL. */
12739 x_query_font (f
, fontname
)
12741 register char *fontname
;
12743 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12746 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12747 if (dpyinfo
->font_table
[i
].name
12748 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
12749 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
12750 return (dpyinfo
->font_table
+ i
);
12755 /* Find a CCL program for a font specified by FONTP, and set the member
12756 `encoder' of the structure. */
12759 x_find_ccl_program (fontp
)
12760 struct font_info
*fontp
;
12762 Lisp_Object list
, elt
;
12764 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
12768 && STRINGP (XCAR (elt
))
12769 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
12775 struct ccl_program
*ccl
12776 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
12778 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
12781 fontp
->font_encoder
= ccl
;
12787 /***********************************************************************
12789 ***********************************************************************/
12791 #ifdef USE_X_TOOLKIT
12792 static XrmOptionDescRec emacs_options
[] = {
12793 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
12794 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
12796 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12797 XrmoptionSepArg
, NULL
},
12798 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
12800 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12801 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12802 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12803 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12804 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12805 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
12806 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
12808 #endif /* USE_X_TOOLKIT */
12810 static int x_initialized
;
12812 #ifdef MULTI_KBOARD
12813 /* Test whether two display-name strings agree up to the dot that separates
12814 the screen number from the server number. */
12816 same_x_server (name1
, name2
)
12817 char *name1
, *name2
;
12819 int seen_colon
= 0;
12820 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
12821 int system_name_length
= strlen (system_name
);
12822 int length_until_period
= 0;
12824 while (system_name
[length_until_period
] != 0
12825 && system_name
[length_until_period
] != '.')
12826 length_until_period
++;
12828 /* Treat `unix' like an empty host name. */
12829 if (! strncmp (name1
, "unix:", 5))
12831 if (! strncmp (name2
, "unix:", 5))
12833 /* Treat this host's name like an empty host name. */
12834 if (! strncmp (name1
, system_name
, system_name_length
)
12835 && name1
[system_name_length
] == ':')
12836 name1
+= system_name_length
;
12837 if (! strncmp (name2
, system_name
, system_name_length
)
12838 && name2
[system_name_length
] == ':')
12839 name2
+= system_name_length
;
12840 /* Treat this host's domainless name like an empty host name. */
12841 if (! strncmp (name1
, system_name
, length_until_period
)
12842 && name1
[length_until_period
] == ':')
12843 name1
+= length_until_period
;
12844 if (! strncmp (name2
, system_name
, length_until_period
)
12845 && name2
[length_until_period
] == ':')
12846 name2
+= length_until_period
;
12848 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
12852 if (seen_colon
&& *name1
== '.')
12856 && (*name1
== '.' || *name1
== '\0')
12857 && (*name2
== '.' || *name2
== '\0'));
12861 struct x_display_info
*
12862 x_term_init (display_name
, xrm_option
, resource_name
)
12863 Lisp_Object display_name
;
12865 char *resource_name
;
12869 struct x_display_info
*dpyinfo
;
12874 if (!x_initialized
)
12880 #ifdef USE_X_TOOLKIT
12881 /* weiner@footloose.sps.mot.com reports that this causes
12883 X protocol error: BadAtom (invalid Atom parameter)
12884 on protocol request 18skiloaf.
12885 So let's not use it until R6. */
12886 #ifdef HAVE_X11XTR6
12887 XtSetLanguageProc (NULL
, NULL
, NULL
);
12898 argv
[argc
++] = "-xrm";
12899 argv
[argc
++] = xrm_option
;
12901 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
12902 resource_name
, EMACS_CLASS
,
12903 emacs_options
, XtNumber (emacs_options
),
12906 #ifdef HAVE_X11XTR6
12907 /* I think this is to compensate for XtSetLanguageProc. */
12912 #else /* not USE_X_TOOLKIT */
12914 XSetLocaleModifiers ("");
12916 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
12917 #endif /* not USE_X_TOOLKIT */
12919 /* Detect failure. */
12926 /* We have definitely succeeded. Record the new connection. */
12928 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
12930 #ifdef MULTI_KBOARD
12932 struct x_display_info
*share
;
12935 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
12936 share
= share
->next
, tail
= XCDR (tail
))
12937 if (same_x_server (XSTRING (XCAR (XCAR (tail
)))->data
,
12938 XSTRING (display_name
)->data
))
12941 dpyinfo
->kboard
= share
->kboard
;
12944 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
12945 init_kboard (dpyinfo
->kboard
);
12946 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
12948 char *vendor
= ServerVendor (dpy
);
12950 dpyinfo
->kboard
->Vsystem_key_alist
12951 = call1 (Qvendor_specific_keysyms
,
12952 build_string (vendor
? vendor
: ""));
12956 dpyinfo
->kboard
->next_kboard
= all_kboards
;
12957 all_kboards
= dpyinfo
->kboard
;
12958 /* Don't let the initial kboard remain current longer than necessary.
12959 That would cause problems if a file loaded on startup tries to
12960 prompt in the mini-buffer. */
12961 if (current_kboard
== initial_kboard
)
12962 current_kboard
= dpyinfo
->kboard
;
12964 dpyinfo
->kboard
->reference_count
++;
12968 /* Put this display on the chain. */
12969 dpyinfo
->next
= x_display_list
;
12970 x_display_list
= dpyinfo
;
12972 /* Put it on x_display_name_list as well, to keep them parallel. */
12973 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
12974 x_display_name_list
);
12975 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12977 dpyinfo
->display
= dpy
;
12980 XSetAfterFunction (x_current_display
, x_trace_wire
);
12984 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
12985 + STRING_BYTES (XSTRING (Vsystem_name
))
12987 sprintf (dpyinfo
->x_id_name
, "%s@%s",
12988 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
12990 /* Figure out which modifier bits mean what. */
12991 x_find_modifier_meanings (dpyinfo
);
12993 /* Get the scroll bar cursor. */
12994 dpyinfo
->vertical_scroll_bar_cursor
12995 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
12997 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
12998 resource_name
, EMACS_CLASS
);
12999 #ifdef HAVE_XRMSETDATABASE
13000 XrmSetDatabase (dpyinfo
->display
, xrdb
);
13002 dpyinfo
->display
->db
= xrdb
;
13004 /* Put the rdb where we can find it in a way that works on
13006 dpyinfo
->xrdb
= xrdb
;
13008 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
13009 DefaultScreen (dpyinfo
->display
));
13010 select_visual (dpyinfo
);
13011 dpyinfo
->cmap
= DefaultColormapOfScreen (dpyinfo
->screen
);
13012 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
13013 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
13014 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
13015 dpyinfo
->grabbed
= 0;
13016 dpyinfo
->reference_count
= 0;
13017 dpyinfo
->icon_bitmap_id
= -1;
13018 dpyinfo
->font_table
= NULL
;
13019 dpyinfo
->n_fonts
= 0;
13020 dpyinfo
->font_table_size
= 0;
13021 dpyinfo
->bitmaps
= 0;
13022 dpyinfo
->bitmaps_size
= 0;
13023 dpyinfo
->bitmaps_last
= 0;
13024 dpyinfo
->scratch_cursor_gc
= 0;
13025 dpyinfo
->mouse_face_mouse_frame
= 0;
13026 dpyinfo
->mouse_face_deferred_gc
= 0;
13027 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
13028 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
13029 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
13030 dpyinfo
->mouse_face_window
= Qnil
;
13031 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
13032 dpyinfo
->mouse_face_defer
= 0;
13033 dpyinfo
->x_focus_frame
= 0;
13034 dpyinfo
->x_focus_event_frame
= 0;
13035 dpyinfo
->x_highlight_frame
= 0;
13036 dpyinfo
->image_cache
= make_image_cache ();
13038 /* See if a private colormap is requested. */
13039 if (dpyinfo
->visual
== DefaultVisualOfScreen (dpyinfo
->screen
))
13041 if (dpyinfo
->visual
->class == PseudoColor
)
13044 value
= display_x_get_resource (dpyinfo
,
13045 build_string ("privateColormap"),
13046 build_string ("PrivateColormap"),
13048 if (STRINGP (value
)
13049 && (!strcmp (XSTRING (value
)->data
, "true")
13050 || !strcmp (XSTRING (value
)->data
, "on")))
13051 dpyinfo
->cmap
= XCopyColormapAndFree (dpyinfo
->display
, dpyinfo
->cmap
);
13055 dpyinfo
->cmap
= XCreateColormap (dpyinfo
->display
, dpyinfo
->root_window
,
13056 dpyinfo
->visual
, AllocNone
);
13059 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
13060 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
13061 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
13062 dpyinfo
->resy
= pixels
* 25.4 / mm
;
13063 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
13064 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
13065 dpyinfo
->resx
= pixels
* 25.4 / mm
;
13068 dpyinfo
->Xatom_wm_protocols
13069 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
13070 dpyinfo
->Xatom_wm_take_focus
13071 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
13072 dpyinfo
->Xatom_wm_save_yourself
13073 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
13074 dpyinfo
->Xatom_wm_delete_window
13075 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
13076 dpyinfo
->Xatom_wm_change_state
13077 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
13078 dpyinfo
->Xatom_wm_configure_denied
13079 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
13080 dpyinfo
->Xatom_wm_window_moved
13081 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
13082 dpyinfo
->Xatom_editres
13083 = XInternAtom (dpyinfo
->display
, "Editres", False
);
13084 dpyinfo
->Xatom_CLIPBOARD
13085 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
13086 dpyinfo
->Xatom_TIMESTAMP
13087 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
13088 dpyinfo
->Xatom_TEXT
13089 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
13090 dpyinfo
->Xatom_COMPOUND_TEXT
13091 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
13092 dpyinfo
->Xatom_DELETE
13093 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
13094 dpyinfo
->Xatom_MULTIPLE
13095 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
13096 dpyinfo
->Xatom_INCR
13097 = XInternAtom (dpyinfo
->display
, "INCR", False
);
13098 dpyinfo
->Xatom_EMACS_TMP
13099 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
13100 dpyinfo
->Xatom_TARGETS
13101 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
13102 dpyinfo
->Xatom_NULL
13103 = XInternAtom (dpyinfo
->display
, "NULL", False
);
13104 dpyinfo
->Xatom_ATOM_PAIR
13105 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
13106 /* For properties of font. */
13107 dpyinfo
->Xatom_PIXEL_SIZE
13108 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
13109 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
13110 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
13111 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
13112 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
13113 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
13114 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
13116 /* Ghostscript support. */
13117 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
13118 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
13120 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
13123 dpyinfo
->cut_buffers_initialized
= 0;
13125 connection
= ConnectionNumber (dpyinfo
->display
);
13126 dpyinfo
->connection
= connection
;
13131 null_bits
[0] = 0x00;
13133 dpyinfo
->null_pixel
13134 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
13135 null_bits
, 1, 1, (long) 0, (long) 0,
13140 extern int gray_bitmap_width
, gray_bitmap_height
;
13141 extern unsigned char *gray_bitmap_bits
;
13143 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
13145 gray_bitmap_width
, gray_bitmap_height
,
13146 (unsigned long) 1, (unsigned long) 0, 1);
13150 xim_initialize (dpyinfo
, resource_name
);
13153 #ifdef subprocesses
13154 /* This is only needed for distinguishing keyboard and process input. */
13155 if (connection
!= 0)
13156 add_keyboard_wait_descriptor (connection
);
13159 #ifndef F_SETOWN_BUG
13161 #ifdef F_SETOWN_SOCK_NEG
13162 /* stdin is a socket here */
13163 fcntl (connection
, F_SETOWN
, -getpid ());
13164 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13165 fcntl (connection
, F_SETOWN
, getpid ());
13166 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13167 #endif /* ! defined (F_SETOWN) */
13168 #endif /* F_SETOWN_BUG */
13171 if (interrupt_input
)
13172 init_sigio (connection
);
13173 #endif /* ! defined (SIGIO) */
13176 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13177 /* Make sure that we have a valid font for dialog boxes
13178 so that Xt does not crash. */
13180 Display
*dpy
= dpyinfo
->display
;
13181 XrmValue d
, fr
, to
;
13185 d
.addr
= (XPointer
)&dpy
;
13186 d
.size
= sizeof (Display
*);
13187 fr
.addr
= XtDefaultFont
;
13188 fr
.size
= sizeof (XtDefaultFont
);
13189 to
.size
= sizeof (Font
*);
13190 to
.addr
= (XPointer
)&font
;
13191 count
= x_catch_errors (dpy
);
13192 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
13194 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
13195 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
13196 x_uncatch_errors (dpy
, count
);
13201 /* See if we should run in synchronous mode. This is useful
13202 for debugging X code. */
13205 value
= display_x_get_resource (dpyinfo
,
13206 build_string ("synchronous"),
13207 build_string ("Synchronous"),
13209 if (STRINGP (value
)
13210 && (!strcmp (XSTRING (value
)->data
, "true")
13211 || !strcmp (XSTRING (value
)->data
, "on")))
13212 XSynchronize (dpyinfo
->display
, True
);
13220 /* Get rid of display DPYINFO, assuming all frames are already gone,
13221 and without sending any more commands to the X server. */
13224 x_delete_display (dpyinfo
)
13225 struct x_display_info
*dpyinfo
;
13227 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
13229 /* Discard this display from x_display_name_list and x_display_list.
13230 We can't use Fdelq because that can quit. */
13231 if (! NILP (x_display_name_list
)
13232 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
13233 x_display_name_list
= XCDR (x_display_name_list
);
13238 tail
= x_display_name_list
;
13239 while (CONSP (tail
) && CONSP (XCDR (tail
)))
13241 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
13243 XCDR (tail
) = XCDR (XCDR (tail
));
13246 tail
= XCDR (tail
);
13250 if (next_noop_dpyinfo
== dpyinfo
)
13251 next_noop_dpyinfo
= dpyinfo
->next
;
13253 if (x_display_list
== dpyinfo
)
13254 x_display_list
= dpyinfo
->next
;
13257 struct x_display_info
*tail
;
13259 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
13260 if (tail
->next
== dpyinfo
)
13261 tail
->next
= tail
->next
->next
;
13264 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13265 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13266 XrmDestroyDatabase (dpyinfo
->xrdb
);
13269 #ifdef MULTI_KBOARD
13270 if (--dpyinfo
->kboard
->reference_count
== 0)
13271 delete_kboard (dpyinfo
->kboard
);
13275 xim_close_dpy (dpyinfo
);
13278 xfree (dpyinfo
->font_table
);
13279 xfree (dpyinfo
->x_id_name
);
13283 /* Set up use of X before we make the first connection. */
13285 static struct redisplay_interface x_redisplay_interface
=
13290 x_clear_end_of_line
,
13292 x_after_update_window_line
,
13293 x_update_window_begin
,
13294 x_update_window_end
,
13297 x_get_glyph_overhangs
,
13298 x_fix_overlapping_area
13304 rif
= &x_redisplay_interface
;
13306 clear_frame_hook
= x_clear_frame
;
13307 ins_del_lines_hook
= x_ins_del_lines
;
13308 change_line_highlight_hook
= x_change_line_highlight
;
13309 delete_glyphs_hook
= x_delete_glyphs
;
13310 ring_bell_hook
= XTring_bell
;
13311 reset_terminal_modes_hook
= XTreset_terminal_modes
;
13312 set_terminal_modes_hook
= XTset_terminal_modes
;
13313 update_begin_hook
= x_update_begin
;
13314 update_end_hook
= x_update_end
;
13315 set_terminal_window_hook
= XTset_terminal_window
;
13316 read_socket_hook
= XTread_socket
;
13317 frame_up_to_date_hook
= XTframe_up_to_date
;
13318 reassert_line_highlight_hook
= XTreassert_line_highlight
;
13319 mouse_position_hook
= XTmouse_position
;
13320 frame_rehighlight_hook
= XTframe_rehighlight
;
13321 frame_raise_lower_hook
= XTframe_raise_lower
;
13322 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13323 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13324 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13325 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13326 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
13328 scroll_region_ok
= 1; /* we'll scroll partial frames */
13329 char_ins_del_ok
= 0; /* just as fast to write the line */
13330 line_ins_del_ok
= 1; /* we'll just blt 'em */
13331 fast_clear_end_of_line
= 1; /* X does this well */
13332 memory_below_frame
= 0; /* we don't remember what scrolls
13337 last_tool_bar_item
= -1;
13338 any_help_event_p
= 0;
13340 /* Try to use interrupt input; if we can't, then start polling. */
13341 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
13343 #ifdef USE_X_TOOLKIT
13344 XtToolkitInitialize ();
13345 Xt_app_con
= XtCreateApplicationContext ();
13346 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
13348 /* Install an asynchronous timer that processes Xt timeout events
13349 every 0.1s. This is necessary because some widget sets use
13350 timeouts internally, for example the LessTif menu bar, or the
13351 Xaw3d scroll bar. When Xt timouts aren't processed, these
13352 widgets don't behave normally. */
13354 EMACS_TIME interval
;
13355 EMACS_SET_SECS_USECS (interval
, 0, 100000);
13356 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
13360 #if USE_TOOLKIT_SCROLL_BARS
13361 xaw3d_arrow_scroll
= False
;
13362 xaw3d_pick_top
= True
;
13365 /* Note that there is no real way portable across R3/R4 to get the
13366 original error handler. */
13367 XSetErrorHandler (x_error_handler
);
13368 XSetIOErrorHandler (x_io_error_quitter
);
13370 /* Disable Window Change signals; they are handled by X events. */
13372 signal (SIGWINCH
, SIG_DFL
);
13373 #endif /* ! defined (SIGWINCH) */
13375 signal (SIGPIPE
, x_connection_signal
);
13382 staticpro (&x_error_message_string
);
13383 x_error_message_string
= Qnil
;
13385 staticpro (&x_display_name_list
);
13386 x_display_name_list
= Qnil
;
13388 staticpro (&last_mouse_scroll_bar
);
13389 last_mouse_scroll_bar
= Qnil
;
13391 staticpro (&Qvendor_specific_keysyms
);
13392 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
13394 staticpro (&last_mouse_press_frame
);
13395 last_mouse_press_frame
= Qnil
;
13397 staticpro (&help_echo
);
13399 staticpro (&previous_help_echo
);
13400 previous_help_echo
= Qnil
;
13402 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
13403 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13404 For example, if a block cursor is over a tab, it will be drawn as\n\
13405 wide as that tab on the display.");
13406 x_stretch_cursor_p
= 0;
13408 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p
,
13409 "If not nil, Emacs uses toolkit scroll bars.");
13410 #if USE_TOOLKIT_SCROLL_BARS
13411 x_toolkit_scroll_bars_p
= 1;
13413 x_toolkit_scroll_bars_p
= 0;
13416 staticpro (&last_mouse_motion_frame
);
13417 last_mouse_motion_frame
= Qnil
;
13420 #endif /* not HAVE_X_WINDOWS */