1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
36 #include "blockinput.h"
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
45 #include <X11/cursorfont.h>
48 /* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */
51 #include <sys/types.h>
56 #include <sys/ioctl.h>
57 #endif /* ! defined (BSD_SYSTEM) */
62 #ifndef INCLUDED_FCNTL
69 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
70 /* #include <sys/param.h> */
76 #include "dispextern.h"
77 #include "termhooks.h"
89 #include "intervals.h"
93 #include <X11/Shell.h>
96 #include <sys/types.h>
97 #ifdef HAVE_SYS_TIME_H
106 extern void free_frame_menubar ();
107 extern FRAME_PTR
x_menubar_window_to_frame ();
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
114 /* Include toolkit specific headers for the scroll bar widget. */
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #include <Xm/ScrollBarP.h>
121 #else /* !USE_MOTIF i.e. use Xaw */
124 #include <X11/Xaw3d/Simple.h>
125 #include <X11/Xaw3d/Scrollbar.h>
126 #define ARROW_SCROLLBAR
127 #include <X11/Xaw3d/ScrollbarP.h>
128 #else /* !HAVE_XAW3D */
129 #include <X11/Xaw/Simple.h>
130 #include <X11/Xaw/Scrollbar.h>
131 #endif /* !HAVE_XAW3D */
133 #define XtNpickTop "pickTop"
134 #endif /* !XtNpickTop */
135 #endif /* !USE_MOTIF */
136 #endif /* USE_TOOLKIT_SCROLL_BARS */
138 #endif /* USE_X_TOOLKIT */
140 #ifndef USE_X_TOOLKIT
141 #define x_any_window_to_frame x_window_to_frame
142 #define x_top_window_to_frame x_window_to_frame
147 #ifndef XtNinitialState
148 #define XtNinitialState "initialState"
153 /* memmove will be defined as a macro in Xfuncs.h unless
154 <string.h> is included beforehand. The declaration for memmove in
155 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
160 #define min(a,b) ((a) < (b) ? (a) : (b))
163 #define max(a,b) ((a) > (b) ? (a) : (b))
166 #define abs(x) ((x) < 0 ? -(x) : (x))
168 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
171 /* Bitmaps for truncated lines. */
176 LEFT_TRUNCATION_BITMAP
,
177 RIGHT_TRUNCATION_BITMAP
,
178 OVERLAY_ARROW_BITMAP
,
179 CONTINUED_LINE_BITMAP
,
180 CONTINUATION_LINE_BITMAP
,
184 /* Bitmap drawn to indicate lines not displaying text if
185 `indicate-empty-lines' is non-nil. */
189 static unsigned char zv_bits
[] = {
190 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
192 /* An arrow like this: `<-'. */
195 #define left_height 8
196 static unsigned char left_bits
[] = {
197 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
199 /* Right truncation arrow bitmap `->'. */
201 #define right_width 8
202 #define right_height 8
203 static unsigned char right_bits
[] = {
204 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
206 /* Marker for continued lines. */
208 #define continued_width 8
209 #define continued_height 8
210 static unsigned char continued_bits
[] = {
211 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
213 /* Marker for continuation lines. */
215 #define continuation_width 8
216 #define continuation_height 8
217 static unsigned char continuation_bits
[] = {
218 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
220 /* Overlay arrow bitmap. */
226 static unsigned char ov_bits
[] = {
227 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
229 /* A triangular arrow. */
232 static unsigned char ov_bits
[] = {
233 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
237 extern Lisp_Object Qhelp_echo
;
240 /* Non-zero means Emacs uses toolkit scroll bars. */
242 int x_toolkit_scroll_bars_p
;
244 /* If a string, XTread_socket generates an event to display that string.
245 (The display is done in read_char.) */
247 static Lisp_Object help_echo
;
249 /* Temporary variable for XTread_socket. */
251 static Lisp_Object previous_help_echo
;
253 /* Non-zero means that a HELP_EVENT has been generated since Emacs
256 static int any_help_event_p
;
258 /* Non-zero means draw block and hollow cursor as wide as the glyph
259 under it. For example, if a block cursor is over a tab, it will be
260 drawn as wide as that tab on the display. */
262 int x_stretch_cursor_p
;
264 /* This is a chain of structures for all the X displays currently in
267 struct x_display_info
*x_display_list
;
269 /* This is a list of cons cells, each of the form (NAME
270 . FONT-LIST-CACHE), one for each element of x_display_list and in
271 the same order. NAME is the name of the frame. FONT-LIST-CACHE
272 records previous values returned by x-list-fonts. */
274 Lisp_Object x_display_name_list
;
276 /* Frame being updated by update_frame. This is declared in term.c.
277 This is set by update_begin and looked at by all the XT functions.
278 It is zero while not inside an update. In that case, the XT
279 functions assume that `selected_frame' is the frame to apply to. */
281 extern struct frame
*updating_frame
;
283 extern int waiting_for_input
;
285 /* This is a frame waiting to be auto-raised, within XTread_socket. */
287 struct frame
*pending_autoraise_frame
;
290 /* The application context for Xt use. */
291 XtAppContext Xt_app_con
;
292 static String Xt_default_resources
[] = {0};
293 #endif /* USE_X_TOOLKIT */
295 /* Nominal cursor position -- where to draw output.
296 HPOS and VPOS are window relative glyph matrix coordinates.
297 X and Y are window relative pixel coordinates. */
299 struct cursor_pos output_cursor
;
304 Formerly, we used PointerMotionHintMask (in standard_event_mask)
305 so that we would have to call XQueryPointer after each MotionNotify
306 event to ask for another such event. However, this made mouse tracking
307 slow, and there was a bug that made it eventually stop.
309 Simply asking for MotionNotify all the time seems to work better.
311 In order to avoid asking for motion events and then throwing most
312 of them away or busy-polling the server for mouse positions, we ask
313 the server for pointer motion hints. This means that we get only
314 one event per group of mouse movements. "Groups" are delimited by
315 other kinds of events (focus changes and button clicks, for
316 example), or by XQueryPointer calls; when one of these happens, we
317 get another MotionNotify event the next time the mouse moves. This
318 is at least as efficient as getting motion events when mouse
319 tracking is on, and I suspect only negligibly worse when tracking
322 /* Where the mouse was last time we reported a mouse event. */
324 FRAME_PTR last_mouse_frame
;
325 static XRectangle last_mouse_glyph
;
326 static Lisp_Object last_mouse_press_frame
;
328 /* The scroll bar in which the last X motion event occurred.
330 If the last X motion event occurred in a scroll bar, we set this so
331 XTmouse_position can know whether to report a scroll bar motion or
334 If the last X motion event didn't occur in a scroll bar, we set
335 this to Qnil, to tell XTmouse_position to return an ordinary motion
338 static Lisp_Object last_mouse_scroll_bar
;
340 /* This is a hack. We would really prefer that XTmouse_position would
341 return the time associated with the position it returns, but there
342 doesn't seem to be any way to wrest the time-stamp from the server
343 along with the position query. So, we just keep track of the time
344 of the last movement we received, and return that in hopes that
345 it's somewhat accurate. */
347 static Time last_mouse_movement_time
;
349 /* Incremented by XTread_socket whenever it really tries to read
353 static int volatile input_signal_count
;
355 static int input_signal_count
;
358 /* Used locally within XTread_socket. */
360 static int x_noop_count
;
362 /* Initial values of argv and argc. */
364 extern char **initial_argv
;
365 extern int initial_argc
;
367 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
369 /* Tells if a window manager is present or not. */
371 extern Lisp_Object Vx_no_window_manager
;
373 extern Lisp_Object Qface
, Qmouse_face
;
377 /* A mask of extra modifier bits to put into every keyboard char. */
379 extern int extra_keyboard_modifiers
;
381 static Lisp_Object Qvendor_specific_keysyms
;
383 extern XrmDatabase
x_load_resources ();
384 extern Lisp_Object
x_icon_type ();
387 /* Enumeration for overriding/changing the face to use for drawing
388 glyphs in x_draw_glyphs. */
390 enum draw_glyphs_face
400 static void x_update_window_end
P_ ((struct window
*, int));
401 static void frame_to_window_pixel_xy
P_ ((struct window
*, int *, int *));
402 void x_delete_display
P_ ((struct x_display_info
*));
403 static unsigned int x_x_to_emacs_modifiers
P_ ((struct x_display_info
*,
405 static int fast_find_position
P_ ((struct window
*, int, int *, int *,
407 static void set_output_cursor
P_ ((struct cursor_pos
*));
408 static struct glyph
*x_y_to_hpos_vpos
P_ ((struct window
*, int, int,
409 int *, int *, int *));
410 static void note_mode_line_highlight
P_ ((struct window
*, int, int));
411 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
412 static void note_mouse_highlight
P_ ((struct frame
*, int, int));
413 static void note_tool_bar_highlight
P_ ((struct frame
*f
, int, int));
414 static void x_handle_tool_bar_click
P_ ((struct frame
*, XButtonEvent
*));
415 static void show_mouse_face
P_ ((struct x_display_info
*,
416 enum draw_glyphs_face
));
417 static int x_io_error_quitter
P_ ((Display
*));
418 int x_catch_errors
P_ ((Display
*));
419 void x_uncatch_errors
P_ ((Display
*, int));
420 void x_lower_frame
P_ ((struct frame
*));
421 void x_scroll_bar_clear
P_ ((struct frame
*));
422 int x_had_errors_p
P_ ((Display
*));
423 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
424 void x_raise_frame
P_ ((struct frame
*));
425 void x_set_window_size
P_ ((struct frame
*, int, int, int));
426 void x_wm_set_window_state
P_ ((struct frame
*, int));
427 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
428 void x_initialize
P_ ((void));
429 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
430 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
431 static void x_draw_phys_cursor_glyph
P_ ((struct window
*,
433 enum draw_glyphs_face
));
434 static void x_update_end
P_ ((struct frame
*));
435 static void XTframe_up_to_date
P_ ((struct frame
*));
436 static void XTreassert_line_highlight
P_ ((int, int));
437 static void x_change_line_highlight
P_ ((int, int, int, int));
438 static void XTset_terminal_modes
P_ ((void));
439 static void XTreset_terminal_modes
P_ ((void));
440 static void XTcursor_to
P_ ((int, int, int, int));
441 static void x_write_glyphs
P_ ((struct glyph
*, int));
442 static void x_clear_end_of_line
P_ ((int));
443 static void x_clear_frame
P_ ((void));
444 static void x_clear_cursor
P_ ((struct window
*));
445 static void frame_highlight
P_ ((struct frame
*));
446 static void frame_unhighlight
P_ ((struct frame
*));
447 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
448 static void XTframe_rehighlight
P_ ((struct frame
*));
449 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
450 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
451 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*));
452 static int x_intersect_rectangles
P_ ((XRectangle
*, XRectangle
*,
454 static void expose_frame
P_ ((struct frame
*, int, int, int, int));
455 static void expose_window_tree
P_ ((struct window
*, XRectangle
*));
456 static void expose_window
P_ ((struct window
*, XRectangle
*));
457 static void expose_area
P_ ((struct window
*, struct glyph_row
*,
458 XRectangle
*, enum glyph_row_area
));
459 static void expose_line
P_ ((struct window
*, struct glyph_row
*,
461 static void x_update_cursor_in_window_tree
P_ ((struct window
*, int));
462 static void x_update_window_cursor
P_ ((struct window
*, int));
463 static void x_erase_phys_cursor
P_ ((struct window
*));
464 void x_display_and_set_cursor
P_ ((struct window
*, int, int, int, int, int));
465 static void x_draw_bitmap
P_ ((struct window
*, struct glyph_row
*,
468 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*,
470 static int x_phys_cursor_in_rect_p
P_ ((struct window
*, XRectangle
*));
471 static void x_draw_row_bitmaps
P_ ((struct window
*, struct glyph_row
*));
472 static void note_overwritten_text_cursor
P_ ((struct window
*, int, int));
473 static void x_flush
P_ ((struct frame
*f
));
476 /* Flush display of frame F, or of all frames if F is null. */
485 Lisp_Object rest
, frame
;
486 FOR_EACH_FRAME (rest
, frame
)
487 x_flush (XFRAME (frame
));
489 else if (FRAME_X_P (f
))
490 XFlush (FRAME_X_DISPLAY (f
));
495 /* Remove calls to XFlush by defining XFlush to an empty replacement.
496 Calls to XFlush should be unnecessary because the X output buffer
497 is flushed automatically as needed by calls to XPending,
498 XNextEvent, or XWindowEvent according to the XFlush man page.
499 XTread_socket calls XPending. Removing XFlush improves
502 #define XFlush(DISPLAY) (void) 0
505 /***********************************************************************
507 ***********************************************************************/
511 /* This is a function useful for recording debugging information about
512 the sequence of occurrences in this file. */
520 struct record event_record
[100];
522 int event_record_index
;
524 record_event (locus
, type
)
528 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
529 event_record_index
= 0;
531 event_record
[event_record_index
].locus
= locus
;
532 event_record
[event_record_index
].type
= type
;
533 event_record_index
++;
540 /* Return the struct x_display_info corresponding to DPY. */
542 struct x_display_info
*
543 x_display_info_for_display (dpy
)
546 struct x_display_info
*dpyinfo
;
548 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
549 if (dpyinfo
->display
== dpy
)
557 /***********************************************************************
558 Starting and ending an update
559 ***********************************************************************/
561 /* Start an update of frame F. This function is installed as a hook
562 for update_begin, i.e. it is called when update_begin is called.
563 This function is called prior to calls to x_update_window_begin for
564 each window being updated. Currently, there is nothing to do here
565 because all interesting stuff is done on a window basis. */
575 /* Start update of window W. Set the global variable updated_window
576 to the window being updated and set output_cursor to the cursor
580 x_update_window_begin (w
)
583 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
584 struct x_display_info
*display_info
= FRAME_X_DISPLAY_INFO (f
);
587 set_output_cursor (&w
->cursor
);
591 if (f
== display_info
->mouse_face_mouse_frame
)
593 /* Don't do highlighting for mouse motion during the update. */
594 display_info
->mouse_face_defer
= 1;
596 /* If F needs to be redrawn, simply forget about any prior mouse
598 if (FRAME_GARBAGED_P (f
))
599 display_info
->mouse_face_window
= Qnil
;
601 /* Can we tell that this update does not affect the window
602 where the mouse highlight is? If so, no need to turn off.
603 Likewise, don't do anything if the frame is garbaged;
604 in that case, the frame's current matrix that we would use
605 is all wrong, and we will redisplay that line anyway. */
606 if (!NILP (display_info
->mouse_face_window
)
607 && w
== XWINDOW (display_info
->mouse_face_window
))
611 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
612 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
615 if (i
< w
->desired_matrix
->nrows
)
616 clear_mouse_face (display_info
);
624 /* Draw a vertical window border to the right of window W if W doesn't
625 have vertical scroll bars. */
628 x_draw_vertical_border (w
)
631 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
633 /* Redraw borders between horizontally adjacent windows. Don't
634 do it for frames with vertical scroll bars because either the
635 right scroll bar of a window, or the left scroll bar of its
636 neighbor will suffice as a border. */
637 if (!WINDOW_RIGHTMOST_P (w
)
638 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
642 window_box_edges (w
, -1, &x0
, &y0
, &x1
, &y1
);
643 x1
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
);
646 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
647 f
->output_data
.x
->normal_gc
, x1
, y0
, x1
, y1
);
652 /* End update of window W (which is equal to updated_window). Draw
653 vertical borders between horizontally adjacent windows, and display
654 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
655 pseudo-window in case we don't have X toolkit support. Such
656 windows don't have a cursor, so don't display it here. */
659 x_update_window_end (w
, cursor_on_p
)
663 if (!w
->pseudo_window_p
)
667 x_display_and_set_cursor (w
, 1, output_cursor
.hpos
,
669 output_cursor
.x
, output_cursor
.y
);
670 x_draw_vertical_border (w
);
674 updated_window
= NULL
;
678 /* End update of frame F. This function is installed as a hook in
685 /* Mouse highlight may be displayed again. */
686 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
689 XFlush (FRAME_X_DISPLAY (f
));
694 /* This function is called from various places in xdisp.c whenever a
695 complete update has been performed. The global variable
696 updated_window is not available here. */
699 XTframe_up_to_date (f
)
704 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
705 if (dpyinfo
->mouse_face_deferred_gc
706 || f
== dpyinfo
->mouse_face_mouse_frame
)
709 if (dpyinfo
->mouse_face_mouse_frame
)
710 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
711 dpyinfo
->mouse_face_mouse_x
,
712 dpyinfo
->mouse_face_mouse_y
);
713 dpyinfo
->mouse_face_deferred_gc
= 0;
720 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
721 arrow bitmaps, or clear the areas where they would be displayed
722 before DESIRED_ROW is made current. The window being updated is
723 found in updated_window. This function It is called from
724 update_window_line only if it is known that there are differences
725 between bitmaps to be drawn between current row and DESIRED_ROW. */
728 x_after_update_window_line (desired_row
)
729 struct glyph_row
*desired_row
;
731 struct window
*w
= updated_window
;
735 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
738 x_draw_row_bitmaps (w
, desired_row
);
740 /* When a window has disappeared, make sure that no rest of
741 full-width rows stays visible in the internal border. */
742 if (windows_or_buffers_changed
)
744 struct frame
*f
= XFRAME (w
->frame
);
745 int width
= FRAME_INTERNAL_BORDER_WIDTH (f
);
746 int height
= desired_row
->visible_height
;
747 int x
= (window_box_right (w
, -1)
748 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
));
749 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
751 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
752 x
, y
, width
, height
, False
);
760 /* Draw the bitmap WHICH in one of the areas to the left or right of
761 window W. ROW is the glyph row for which to display the bitmap; it
762 determines the vertical position at which the bitmap has to be
766 x_draw_bitmap (w
, row
, which
)
768 struct glyph_row
*row
;
769 enum bitmap_type which
;
771 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
772 Display
*display
= FRAME_X_DISPLAY (f
);
773 Window window
= FRAME_X_WINDOW (f
);
777 GC gc
= f
->output_data
.x
->normal_gc
;
779 int depth
= DefaultDepthOfScreen (FRAME_X_SCREEN (f
));
781 /* Must clip because of partially visible lines. */
782 x_clip_to_row (w
, row
, gc
, 1);
786 case LEFT_TRUNCATION_BITMAP
:
790 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
792 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
795 case OVERLAY_ARROW_BITMAP
:
799 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
801 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
804 case RIGHT_TRUNCATION_BITMAP
:
808 x
= window_box_right (w
, -1);
809 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
812 case CONTINUED_LINE_BITMAP
:
815 bits
= continued_bits
;
816 x
= window_box_right (w
, -1);
817 x
+= (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
) - wd
) / 2;
820 case CONTINUATION_LINE_BITMAP
:
821 wd
= continuation_width
;
822 h
= continuation_height
;
823 bits
= continuation_bits
;
824 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
826 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
833 x
= (WINDOW_TO_FRAME_PIXEL_X (w
, 0)
835 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - wd
) / 2);
842 /* Convert to frame coordinates. Set dy to the offset in the row to
843 start drawing the bitmap. */
844 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
845 dy
= (row
->height
- h
) / 2;
847 /* Draw the bitmap. I believe these small pixmaps can be cached
849 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
850 pixmap
= XCreatePixmapFromBitmapData (display
, window
, bits
, wd
, h
,
852 face
->background
, depth
);
853 XCopyArea (display
, pixmap
, window
, gc
, 0, 0, wd
, h
, x
, y
+ dy
);
854 XFreePixmap (display
, pixmap
);
855 XSetClipMask (display
, gc
, None
);
859 /* Draw flags bitmaps for glyph row ROW on window W. Call this
860 function with input blocked. */
863 x_draw_row_bitmaps (w
, row
)
865 struct glyph_row
*row
;
867 struct frame
*f
= XFRAME (w
->frame
);
868 enum bitmap_type bitmap
;
870 int header_line_height
= -1;
872 xassert (interrupt_input_blocked
);
874 /* If row is completely invisible, because of vscrolling, we
875 don't have to draw anything. */
876 if (row
->visible_height
<= 0)
879 face
= FACE_FROM_ID (f
, BITMAP_AREA_FACE_ID
);
880 PREPARE_FACE_FOR_DISPLAY (f
, face
);
882 /* Decide which bitmap to draw at the left side. */
883 if (row
->overlay_arrow_p
)
884 bitmap
= OVERLAY_ARROW_BITMAP
;
885 else if (row
->truncated_on_left_p
)
886 bitmap
= LEFT_TRUNCATION_BITMAP
;
887 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
888 bitmap
= CONTINUATION_LINE_BITMAP
;
889 else if (row
->indicate_empty_line_p
)
890 bitmap
= ZV_LINE_BITMAP
;
894 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
896 if (bitmap
== NO_BITMAP
897 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
898 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
900 /* If W has a vertical border to its left, don't draw over it. */
901 int border
= ((XFASTINT (w
->left
) > 0
902 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
904 int left
= window_box_left (w
, -1);
906 if (header_line_height
< 0)
907 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
909 /* In case the same realized face is used for bitmap areas and
910 for something displayed in the text (e.g. face `region' on
911 mono-displays, the fill style may have been changed to
912 FillSolid in x_draw_glyph_string_background. */
914 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
916 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
918 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
921 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
923 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
925 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
) - border
,
926 row
->visible_height
);
928 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
931 /* Draw the left bitmap. */
932 if (bitmap
!= NO_BITMAP
)
933 x_draw_bitmap (w
, row
, bitmap
);
935 /* Decide which bitmap to draw at the right side. */
936 if (row
->truncated_on_right_p
)
937 bitmap
= RIGHT_TRUNCATION_BITMAP
;
938 else if (row
->continued_p
)
939 bitmap
= CONTINUED_LINE_BITMAP
;
943 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
945 if (bitmap
== NO_BITMAP
946 || FRAME_FLAGS_BITMAP_WIDTH (f
) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
)
947 || row
->height
> FRAME_FLAGS_BITMAP_HEIGHT (f
))
949 int right
= window_box_right (w
, -1);
951 if (header_line_height
< 0)
952 header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
954 /* In case the same realized face is used for bitmap areas and
955 for something displayed in the text (e.g. face `region' on
956 mono-displays, the fill style may have been changed to
957 FillSolid in x_draw_glyph_string_background. */
959 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
961 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
962 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
965 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
967 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f
),
968 row
->visible_height
);
970 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
973 /* Draw the right bitmap. */
974 if (bitmap
!= NO_BITMAP
)
975 x_draw_bitmap (w
, row
, bitmap
);
979 /***********************************************************************
981 ***********************************************************************/
983 /* External interface to control of standout mode. Not used for X
984 frames. Aborts when called. */
987 XTreassert_line_highlight (new, vpos
)
994 /* Call this when about to modify line at position VPOS and change
995 whether it is highlighted. Not used for X frames. Aborts when
999 x_change_line_highlight (new_highlight
, vpos
, y
, first_unused_hpos
)
1000 int new_highlight
, vpos
, y
, first_unused_hpos
;
1006 /* This is called when starting Emacs and when restarting after
1007 suspend. When starting Emacs, no X window is mapped. And nothing
1008 must be done to Emacs's own window if it is suspended (though that
1012 XTset_terminal_modes ()
1016 /* This is called when exiting or suspending Emacs. Exiting will make
1017 the X-windows go away, and suspending requires no action. */
1020 XTreset_terminal_modes ()
1026 /***********************************************************************
1028 ***********************************************************************/
1030 /* Set the global variable output_cursor to CURSOR. All cursor
1031 positions are relative to updated_window. */
1034 set_output_cursor (cursor
)
1035 struct cursor_pos
*cursor
;
1037 output_cursor
.hpos
= cursor
->hpos
;
1038 output_cursor
.vpos
= cursor
->vpos
;
1039 output_cursor
.x
= cursor
->x
;
1040 output_cursor
.y
= cursor
->y
;
1044 /* Set a nominal cursor position.
1046 HPOS and VPOS are column/row positions in a window glyph matrix. X
1047 and Y are window text area relative pixel positions.
1049 If this is done during an update, updated_window will contain the
1050 window that is being updated and the position is the future output
1051 cursor position for that window. If updated_window is null, use
1052 selected_window and display the cursor at the given position. */
1055 XTcursor_to (vpos
, hpos
, y
, x
)
1056 int vpos
, hpos
, y
, x
;
1060 /* If updated_window is not set, work on selected_window. */
1064 w
= XWINDOW (selected_window
);
1066 /* Set the output cursor. */
1067 output_cursor
.hpos
= hpos
;
1068 output_cursor
.vpos
= vpos
;
1069 output_cursor
.x
= x
;
1070 output_cursor
.y
= y
;
1072 /* If not called as part of an update, really display the cursor.
1073 This will also set the cursor position of W. */
1074 if (updated_window
== NULL
)
1077 x_display_cursor (w
, 1, hpos
, vpos
, x
, y
);
1078 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1085 /***********************************************************************
1087 ***********************************************************************/
1089 /* Function prototypes of this page. */
1091 static struct face
*x_get_glyph_face_and_encoding
P_ ((struct frame
*,
1094 static struct face
*x_get_char_face_and_encoding
P_ ((struct frame
*, int,
1095 int, XChar2b
*, int));
1096 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1097 static void x_encode_char
P_ ((int, XChar2b
*, struct font_info
*));
1098 static void x_append_glyph
P_ ((struct it
*));
1099 static void x_append_composite_glyph
P_ ((struct it
*));
1100 static void x_append_stretch_glyph
P_ ((struct it
*it
, Lisp_Object
,
1102 static void x_produce_glyphs
P_ ((struct it
*));
1103 static void x_produce_image_glyph
P_ ((struct it
*it
));
1106 /* Return a pointer to per-char metric information in FONT of a
1107 character pointed by B which is a pointer to an XChar2b. */
1109 #define PER_CHAR_METRIC(font, b) \
1111 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1112 + (((font)->min_byte1 || (font)->max_byte1) \
1113 ? (((b)->byte1 - (font)->min_byte1) \
1114 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1116 : &((font)->max_bounds))
1119 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1120 If CHAR2B is not contained in FONT, the font's default character
1121 metric is returned. */
1123 static INLINE XCharStruct
*
1124 x_per_char_metric (font
, char2b
)
1128 /* The result metric information. */
1129 XCharStruct
*pcm
= NULL
;
1131 xassert (font
&& char2b
);
1133 if (font
->per_char
!= NULL
)
1135 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1137 /* min_char_or_byte2 specifies the linear character index
1138 corresponding to the first element of the per_char array,
1139 max_char_or_byte2 is the index of the last character. A
1140 character with non-zero CHAR2B->byte1 is not in the font.
1141 A character with byte2 less than min_char_or_byte2 or
1142 greater max_char_or_byte2 is not in the font. */
1143 if (char2b
->byte1
== 0
1144 && char2b
->byte2
>= font
->min_char_or_byte2
1145 && char2b
->byte2
<= font
->max_char_or_byte2
)
1146 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1150 /* If either min_byte1 or max_byte1 are nonzero, both
1151 min_char_or_byte2 and max_char_or_byte2 are less than
1152 256, and the 2-byte character index values corresponding
1153 to the per_char array element N (counting from 0) are:
1155 byte1 = N/D + min_byte1
1156 byte2 = N\D + min_char_or_byte2
1160 D = max_char_or_byte2 - min_char_or_byte2 + 1
1161 / = integer division
1162 \ = integer modulus */
1163 if (char2b
->byte1
>= font
->min_byte1
1164 && char2b
->byte1
<= font
->max_byte1
1165 && char2b
->byte2
>= font
->min_char_or_byte2
1166 && char2b
->byte2
<= font
->max_char_or_byte2
)
1168 pcm
= (font
->per_char
1169 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1170 * (char2b
->byte1
- font
->min_byte1
))
1171 + (char2b
->byte2
- font
->min_char_or_byte2
));
1177 /* If the per_char pointer is null, all glyphs between the first
1178 and last character indexes inclusive have the same
1179 information, as given by both min_bounds and max_bounds. */
1180 if (char2b
->byte2
>= font
->min_char_or_byte2
1181 && char2b
->byte2
<= font
->max_char_or_byte2
)
1182 pcm
= &font
->max_bounds
;
1186 if (pcm
== NULL
|| pcm
->width
== 0)
1188 /* Character not contained in the font. FONT->default_char
1189 gives the character that will be printed. FONT->default_char
1190 is a 16-bit character code with byte1 in the most significant
1191 byte and byte2 in the least significant byte. */
1192 XChar2b default_char
;
1193 default_char
.byte1
= (font
->default_char
>> BITS_PER_CHAR
) & 0xff;
1194 default_char
.byte2
= font
->default_char
& 0xff;
1196 /* Avoid an endless recursion if FONT->default_char itself
1197 hasn't per char metrics. handa@etl.go.jp reports that some
1198 fonts have this problem. */
1199 if (default_char
.byte1
!= char2b
->byte1
1200 || default_char
.byte2
!= char2b
->byte2
)
1201 pcm
= x_per_char_metric (font
, &default_char
);
1203 pcm
= &font
->max_bounds
;
1210 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1211 the two-byte form of C. Encoding is returned in *CHAR2B. */
1214 x_encode_char (c
, char2b
, font_info
)
1217 struct font_info
*font_info
;
1219 int charset
= CHAR_CHARSET (c
);
1220 XFontStruct
*font
= font_info
->font
;
1222 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1223 This may be either a program in a special encoder language or a
1225 if (font_info
->font_encoder
)
1227 /* It's a program. */
1228 struct ccl_program
*ccl
= font_info
->font_encoder
;
1230 if (CHARSET_DIMENSION (charset
) == 1)
1232 ccl
->reg
[0] = charset
;
1233 ccl
->reg
[1] = char2b
->byte2
;
1237 ccl
->reg
[0] = charset
;
1238 ccl
->reg
[1] = char2b
->byte1
;
1239 ccl
->reg
[2] = char2b
->byte2
;
1242 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1244 /* We assume that MSBs are appropriately set/reset by CCL
1246 if (font
->max_byte1
== 0) /* 1-byte font */
1247 char2b
->byte2
= ccl
->reg
[1];
1249 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1251 else if (font_info
->encoding
[charset
])
1253 /* Fixed encoding scheme. See fontset.h for the meaning of the
1254 encoding numbers. */
1255 int enc
= font_info
->encoding
[charset
];
1257 if ((enc
== 1 || enc
== 2)
1258 && CHARSET_DIMENSION (charset
) == 2)
1259 char2b
->byte1
|= 0x80;
1261 if (enc
== 1 || enc
== 3)
1262 char2b
->byte2
|= 0x80;
1267 /* Get face and two-byte form of character C in face FACE_ID on frame
1268 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1269 means we want to display multibyte text. Value is a pointer to a
1270 realized face that is ready for display. */
1272 static INLINE
struct face
*
1273 x_get_char_face_and_encoding (f
, c
, face_id
, char2b
, multibyte_p
)
1279 struct face
*face
= FACE_FROM_ID (f
, face_id
);
1283 /* Unibyte case. We don't have to encode, but we have to make
1284 sure to use a face suitable for unibyte. */
1288 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, -1))
1290 face_id
= FACE_FOR_CHARSET (f
, face_id
, -1);
1291 face
= FACE_FROM_ID (f
, face_id
);
1294 else if (c
< 128 && face_id
< BASIC_FACE_ID_SENTINEL
)
1296 /* Case of ASCII in a face known to fit ASCII. */
1302 int c1
, c2
, charset
;
1304 /* Split characters into bytes. If c2 is -1 afterwards, C is
1305 really a one-byte character so that byte1 is zero. */
1306 SPLIT_CHAR (c
, charset
, c1
, c2
);
1308 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1310 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1312 /* Get the face for displaying C. If `face' is not suitable for
1313 charset, get the one that fits. (This can happen for the
1314 translations of a composition where the glyph
1315 specifies a face for the first component, but the other
1316 components have a different charset.) */
1317 if (!FACE_SUITABLE_FOR_CHARSET_P (face
, charset
))
1319 face_id
= FACE_FOR_CHARSET (f
, face_id
, charset
);
1320 face
= FACE_FROM_ID (f
, face_id
);
1323 /* Maybe encode the character in *CHAR2B. */
1324 if (charset
!= CHARSET_ASCII
)
1326 struct font_info
*font_info
1327 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1330 x_encode_char (c
, char2b
, font_info
);
1331 if (charset
== charset_latin_iso8859_1
)
1333 xassert (((XFontStruct
*) font_info
->font
)->max_char_or_byte2
1335 char2b
->byte2
|= 0x80;
1341 /* Make sure X resources of the face are allocated. */
1342 xassert (face
!= NULL
);
1343 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1349 /* Get face and two-byte form of character glyph GLYPH on frame F.
1350 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1351 a pointer to a realized face that is ready for display. */
1353 static INLINE
struct face
*
1354 x_get_glyph_face_and_encoding (f
, glyph
, char2b
)
1356 struct glyph
*glyph
;
1361 xassert (glyph
->type
== CHAR_GLYPH
);
1362 face
= FACE_FROM_ID (f
, glyph
->u
.ch
.face_id
);
1364 if (!glyph
->multibyte_p
)
1366 /* Unibyte case. We don't have to encode, but we have to make
1367 sure to use a face suitable for unibyte. */
1369 char2b
->byte2
= glyph
->u
.ch
.code
;
1371 else if (glyph
->u
.ch
.code
< 128
1372 && glyph
->u
.ch
.face_id
< BASIC_FACE_ID_SENTINEL
)
1374 /* Case of ASCII in a face known to fit ASCII. */
1376 char2b
->byte2
= glyph
->u
.ch
.code
;
1380 int c1
, c2
, charset
;
1382 /* Split characters into bytes. If c2 is -1 afterwards, C is
1383 really a one-byte character so that byte1 is zero. */
1384 SPLIT_CHAR (glyph
->u
.ch
.code
, charset
, c1
, c2
);
1386 char2b
->byte1
= c1
, char2b
->byte2
= c2
;
1388 char2b
->byte1
= 0, char2b
->byte2
= c1
;
1390 /* Maybe encode the character in *CHAR2B. */
1391 if (charset
!= CHARSET_ASCII
)
1393 struct font_info
*font_info
1394 = FONT_INFO_FROM_ID (f
, face
->font_info_id
);
1397 x_encode_char (glyph
->u
.ch
.code
, char2b
, font_info
);
1398 if (charset
== charset_latin_iso8859_1
)
1399 char2b
->byte2
|= 0x80;
1404 /* Make sure X resources of the face are allocated. */
1405 xassert (face
!= NULL
);
1406 PREPARE_FACE_FOR_DISPLAY (f
, face
);
1411 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1412 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1418 struct glyph
*glyph
;
1419 enum glyph_row_area area
= it
->area
;
1421 xassert (it
->glyph_row
);
1422 xassert (it
->char_to_display
!= '\n' && it
->char_to_display
!= '\t');
1424 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1425 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1427 /* Play it safe. If sub-structures of the glyph are not all the
1428 same size, it otherwise be that some bits stay set. This
1429 would prevent a comparison with GLYPH_EQUAL_P. */
1432 glyph
->type
= CHAR_GLYPH
;
1433 glyph
->pixel_width
= it
->pixel_width
;
1434 glyph
->u
.ch
.code
= it
->char_to_display
;
1435 glyph
->u
.ch
.face_id
= it
->face_id
;
1436 glyph
->charpos
= CHARPOS (it
->position
);
1437 glyph
->object
= it
->object
;
1438 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1439 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1440 glyph
->voffset
= it
->voffset
;
1441 glyph
->multibyte_p
= it
->multibyte_p
;
1442 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1443 || it
->phys_descent
> it
->descent
);
1444 ++it
->glyph_row
->used
[area
];
1448 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1449 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1452 x_append_composite_glyph (it
)
1455 struct glyph
*glyph
;
1456 enum glyph_row_area area
= it
->area
;
1458 xassert (it
->glyph_row
);
1460 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1461 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1463 /* Play it safe. If sub-structures of the glyph are not all the
1464 same size, it otherwise be that some bits stay set. This
1465 would prevent a comparison with GLYPH_EQUAL_P. */
1468 glyph
->type
= COMPOSITE_GLYPH
;
1469 glyph
->pixel_width
= it
->pixel_width
;
1470 glyph
->u
.cmp
.id
= it
->cmp_id
;
1471 glyph
->u
.cmp
.face_id
= it
->face_id
;
1472 glyph
->charpos
= CHARPOS (it
->position
);
1473 glyph
->object
= it
->object
;
1474 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1475 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1476 glyph
->voffset
= it
->voffset
;
1477 glyph
->multibyte_p
= it
->multibyte_p
;
1478 glyph
->overlaps_vertically_p
= (it
->phys_ascent
> it
->ascent
1479 || it
->phys_descent
> it
->descent
);
1480 ++it
->glyph_row
->used
[area
];
1485 /* Change IT->ascent and IT->height according to the setting of
1489 take_vertical_position_into_account (it
)
1494 if (it
->voffset
< 0)
1495 /* Increase the ascent so that we can display the text higher
1497 it
->ascent
+= abs (it
->voffset
);
1499 /* Increase the descent so that we can display the text lower
1501 it
->descent
+= it
->voffset
;
1506 /* Produce glyphs/get display metrics for the image IT is loaded with.
1507 See the description of struct display_iterator in dispextern.h for
1508 an overview of struct display_iterator. */
1511 x_produce_image_glyph (it
)
1517 xassert (it
->what
== IT_IMAGE
);
1519 face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1520 img
= IMAGE_FROM_ID (it
->f
, it
->image_id
);
1523 /* Make sure X resources of the face and image are loaded. */
1524 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1525 prepare_image_for_display (it
->f
, img
);
1527 it
->ascent
= it
->phys_ascent
= IMAGE_ASCENT (img
);
1528 it
->descent
= it
->phys_descent
= img
->height
+ 2 * img
->margin
- it
->ascent
;
1529 it
->pixel_width
= img
->width
+ 2 * img
->margin
;
1533 if (face
->box
!= FACE_NO_BOX
)
1535 it
->ascent
+= face
->box_line_width
;
1536 it
->descent
+= face
->box_line_width
;
1538 if (it
->start_of_box_run_p
)
1539 it
->pixel_width
+= face
->box_line_width
;
1540 if (it
->end_of_box_run_p
)
1541 it
->pixel_width
+= face
->box_line_width
;
1544 take_vertical_position_into_account (it
);
1548 struct glyph
*glyph
;
1549 enum glyph_row_area area
= it
->area
;
1551 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1552 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1554 glyph
->type
= IMAGE_GLYPH
;
1555 glyph
->u
.img
.id
= img
->id
;
1556 glyph
->u
.img
.face_id
= it
->face_id
;
1557 glyph
->pixel_width
= it
->pixel_width
;
1558 glyph
->charpos
= CHARPOS (it
->position
);
1559 glyph
->object
= it
->object
;
1560 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1561 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1562 glyph
->voffset
= it
->voffset
;
1563 glyph
->multibyte_p
= it
->multibyte_p
;
1564 ++it
->glyph_row
->used
[area
];
1570 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1571 of the glyph, WIDTH and HEIGHT are the width and height of the
1572 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1573 ascent of the glyph (0 <= ASCENT <= 1). */
1576 x_append_stretch_glyph (it
, object
, width
, height
, ascent
)
1582 struct glyph
*glyph
;
1583 enum glyph_row_area area
= it
->area
;
1585 xassert (ascent
>= 0 && ascent
<= 1);
1587 glyph
= it
->glyph_row
->glyphs
[area
] + it
->glyph_row
->used
[area
];
1588 if (glyph
< it
->glyph_row
->glyphs
[area
+ 1])
1590 glyph
->type
= STRETCH_GLYPH
;
1591 glyph
->u
.stretch
.ascent
= height
* ascent
;
1592 glyph
->u
.stretch
.height
= height
;
1593 glyph
->u
.stretch
.face_id
= it
->face_id
;
1594 glyph
->pixel_width
= width
;
1595 glyph
->charpos
= CHARPOS (it
->position
);
1596 glyph
->object
= object
;
1597 glyph
->left_box_line_p
= it
->start_of_box_run_p
;
1598 glyph
->right_box_line_p
= it
->end_of_box_run_p
;
1599 glyph
->voffset
= it
->voffset
;
1600 glyph
->multibyte_p
= it
->multibyte_p
;
1601 ++it
->glyph_row
->used
[area
];
1606 /* Produce a stretch glyph for iterator IT. IT->object is the value
1607 of the glyph property displayed. The value must be a list
1608 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1611 1. `:width WIDTH' specifies that the space should be WIDTH *
1612 canonical char width wide. WIDTH may be an integer or floating
1615 2. `:relative-width FACTOR' specifies that the width of the stretch
1616 should be computed from the width of the first character having the
1617 `glyph' property, and should be FACTOR times that width.
1619 3. `:align-to HPOS' specifies that the space should be wide enough
1620 to reach HPOS, a value in canonical character units.
1622 Exactly one of the above pairs must be present.
1624 4. `:height HEIGHT' specifies that the height of the stretch produced
1625 should be HEIGHT, measured in canonical character units.
1627 5. `:relative-height FACTOR' specifies that the height of the the
1628 stretch should be FACTOR times the height of the characters having
1631 Either none or exactly one of 4 or 5 must be present.
1633 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1634 of the stretch should be used for the ascent of the stretch.
1635 ASCENT must be in the range 0 <= ASCENT <= 100. */
1638 ((INTEGERP (X) || FLOATP (X)) \
1644 x_produce_stretch_glyph (it
)
1647 /* (space :width WIDTH :height HEIGHT. */
1648 extern Lisp_Object QCwidth
, QCheight
, QCascent
, Qspace
;
1649 extern Lisp_Object QCrelative_width
, QCrelative_height
;
1650 extern Lisp_Object QCalign_to
;
1651 Lisp_Object prop
, plist
;
1652 double width
= 0, height
= 0, ascent
= 0;
1653 struct face
*face
= FACE_FROM_ID (it
->f
, it
->face_id
);
1654 XFontStruct
*font
= face
->font
? face
->font
: FRAME_FONT (it
->f
);
1656 PREPARE_FACE_FOR_DISPLAY (it
->f
, face
);
1658 /* List should start with `space'. */
1659 xassert (CONSP (it
->object
) && EQ (XCAR (it
->object
), Qspace
));
1660 plist
= XCDR (it
->object
);
1662 /* Compute the width of the stretch. */
1663 if (prop
= Fplist_get (plist
, QCwidth
),
1665 /* Absolute width `:width WIDTH' specified and valid. */
1666 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
);
1667 else if (prop
= Fplist_get (plist
, QCrelative_width
),
1670 /* Relative width `:relative-width FACTOR' specified and valid.
1671 Compute the width of the characters having the `glyph'
1674 unsigned char *p
= BYTE_POS_ADDR (IT_BYTEPOS (*it
));
1677 if (it
->multibyte_p
)
1679 int maxlen
= ((IT_BYTEPOS (*it
) >= GPT
? ZV
: GPT
)
1680 - IT_BYTEPOS (*it
));
1681 it2
.c
= STRING_CHAR_AND_LENGTH (p
, maxlen
, it2
.len
);
1684 it2
.c
= *p
, it2
.len
= 1;
1686 it2
.glyph_row
= NULL
;
1687 it2
.what
= IT_CHARACTER
;
1688 x_produce_glyphs (&it2
);
1689 width
= NUMVAL (prop
) * it2
.pixel_width
;
1691 else if (prop
= Fplist_get (plist
, QCalign_to
),
1693 width
= NUMVAL (prop
) * CANON_X_UNIT (it
->f
) - it
->current_x
;
1695 /* Nothing specified -> width defaults to canonical char width. */
1696 width
= CANON_X_UNIT (it
->f
);
1698 /* Compute height. */
1699 if (prop
= Fplist_get (plist
, QCheight
),
1701 height
= NUMVAL (prop
) * CANON_Y_UNIT (it
->f
);
1702 else if (prop
= Fplist_get (plist
, QCrelative_height
),
1704 height
= FONT_HEIGHT (font
) * NUMVAL (prop
);
1706 height
= FONT_HEIGHT (font
);
1708 /* Compute percentage of height used for ascent. If
1709 `:ascent ASCENT' is present and valid, use that. Otherwise,
1710 derive the ascent from the font in use. */
1711 if (prop
= Fplist_get (plist
, QCascent
),
1712 NUMVAL (prop
) > 0 && NUMVAL (prop
) <= 100)
1713 ascent
= NUMVAL (prop
) / 100.0;
1715 ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1724 Lisp_Object object
= it
->stack
[it
->sp
- 1].string
;
1725 if (!STRINGP (object
))
1726 object
= it
->w
->buffer
;
1727 x_append_stretch_glyph (it
, object
, width
, height
, ascent
);
1730 it
->pixel_width
= width
;
1731 it
->ascent
= it
->phys_ascent
= height
* ascent
;
1732 it
->descent
= it
->phys_descent
= height
- it
->ascent
;
1735 if (face
->box
!= FACE_NO_BOX
)
1737 it
->ascent
+= face
->box_line_width
;
1738 it
->descent
+= face
->box_line_width
;
1740 if (it
->start_of_box_run_p
)
1741 it
->pixel_width
+= face
->box_line_width
;
1742 if (it
->end_of_box_run_p
)
1743 it
->pixel_width
+= face
->box_line_width
;
1746 take_vertical_position_into_account (it
);
1749 /* Return proper value to be used as baseline offset of font that has
1750 ASCENT and DESCENT to draw characters by the font at the vertical
1751 center of the line of frame F.
1753 Here, out task is to find the value of BOFF in the following figure;
1755 -------------------------+-----------+-
1756 -+-+---------+-+ | |
1758 | | | | F_ASCENT F_HEIGHT
1761 | | |-|-+------+-----------|------- baseline
1763 | |---------|-+-+ | |
1765 -+-+---------+-+ F_DESCENT |
1766 -------------------------+-----------+-
1768 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1769 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1770 DESCENT = FONT->descent
1771 HEIGHT = FONT_HEIGHT (FONT)
1772 F_DESCENT = (F->output_data.x->font->descent
1773 - F->output_data.x->baseline_offset)
1774 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1777 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1779 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1780 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1782 /* Produce glyphs/get display metrics for the display element IT is
1783 loaded with. See the description of struct display_iterator in
1784 dispextern.h for an overview of struct display_iterator. */
1787 x_produce_glyphs (it
)
1790 if (it
->what
== IT_CHARACTER
)
1796 int font_not_found_p
;
1797 struct font_info
*font_info
;
1798 int boff
; /* baseline offset */
1800 /* Maybe translate single-byte characters to multibyte. */
1801 it
->char_to_display
= it
->c
;
1802 if (unibyte_display_via_language_environment
1803 && SINGLE_BYTE_CHAR_P (it
->c
)
1806 && !NILP (Vnonascii_translation_table
))))
1808 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
1809 it
->charset
= CHAR_CHARSET (it
->char_to_display
);
1812 /* Get face and font to use. Encode IT->char_to_display. */
1813 face
= x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
1814 it
->face_id
, &char2b
,
1818 /* When no suitable font found, use the default font. */
1819 font_not_found_p
= font
== NULL
;
1820 if (font_not_found_p
)
1822 font
= FRAME_FONT (it
->f
);
1823 boff
= it
->f
->output_data
.x
->baseline_offset
;
1828 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
1829 boff
= font_info
->baseline_offset
;
1830 if (font_info
->vertical_centering
)
1831 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
1834 if (it
->char_to_display
>= ' '
1835 && (!it
->multibyte_p
|| it
->char_to_display
< 128))
1837 /* Either unibyte or ASCII. */
1842 pcm
= x_per_char_metric (font
, &char2b
);
1843 it
->ascent
= font
->ascent
+ boff
;
1844 it
->descent
= font
->descent
- boff
;
1845 it
->phys_ascent
= pcm
->ascent
+ boff
;
1846 it
->phys_descent
= pcm
->descent
- boff
;
1847 it
->pixel_width
= pcm
->width
;
1849 /* If this is a space inside a region of text with
1850 `space-width' property, change its width. */
1851 stretched_p
= it
->char_to_display
== ' ' && !NILP (it
->space_width
);
1853 it
->pixel_width
*= XFLOATINT (it
->space_width
);
1855 /* If face has a box, add the box thickness to the character
1856 height. If character has a box line to the left and/or
1857 right, add the box line width to the character's width. */
1858 if (face
->box
!= FACE_NO_BOX
)
1860 int thick
= face
->box_line_width
;
1862 it
->ascent
+= thick
;
1863 it
->descent
+= thick
;
1865 if (it
->start_of_box_run_p
)
1866 it
->pixel_width
+= thick
;
1867 if (it
->end_of_box_run_p
)
1868 it
->pixel_width
+= thick
;
1871 /* If face has an overline, add the height of the overline
1872 (1 pixel) and a 1 pixel margin to the character height. */
1873 if (face
->overline_p
)
1876 take_vertical_position_into_account (it
);
1878 /* If we have to actually produce glyphs, do it. */
1883 /* Translate a space with a `space-width' property
1884 into a stretch glyph. */
1885 double ascent
= (double) font
->ascent
/ FONT_HEIGHT (font
);
1886 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1887 it
->ascent
+ it
->descent
, ascent
);
1890 x_append_glyph (it
);
1892 /* If characters with lbearing or rbearing are displayed
1893 in this line, record that fact in a flag of the
1894 glyph row. This is used to optimize X output code. */
1895 if (pcm
->lbearing
< 0
1896 || pcm
->rbearing
> pcm
->width
)
1897 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1900 else if (it
->char_to_display
== '\n')
1902 /* A newline has no width but we need the height of the line. */
1903 it
->pixel_width
= 0;
1905 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1906 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1908 if (face
->box
!= FACE_NO_BOX
)
1910 int thick
= face
->box_line_width
;
1911 it
->ascent
+= thick
;
1912 it
->descent
+= thick
;
1915 else if (it
->char_to_display
== '\t')
1917 int tab_width
= it
->tab_width
* CANON_X_UNIT (it
->f
);
1918 int x
= (it
->current_x
1920 + it
->continuation_lines_width
);
1921 int next_tab_x
= ((1 + x
+ tab_width
- 1) / tab_width
) * tab_width
;
1923 it
->pixel_width
= next_tab_x
- x
;
1925 it
->ascent
= it
->phys_ascent
= font
->ascent
+ boff
;
1926 it
->descent
= it
->phys_descent
= font
->descent
- boff
;
1930 double ascent
= (double) it
->ascent
/ (it
->ascent
+ it
->descent
);
1931 x_append_stretch_glyph (it
, it
->object
, it
->pixel_width
,
1932 it
->ascent
+ it
->descent
, ascent
);
1937 /* A multi-byte character. Assume that the display width of the
1938 character is the width of the character multiplied by the
1939 width of the font. */
1941 /* If we found a font, this font should give us the right
1942 metrics. If we didn't find a font, use the frame's
1943 default font and calculate the width of the character
1944 from the charset width; this is what old redisplay code
1946 pcm
= x_per_char_metric (font
, &char2b
);
1947 it
->pixel_width
= pcm
->width
;
1948 if (font_not_found_p
)
1949 it
->pixel_width
*= CHARSET_WIDTH (it
->charset
);
1951 it
->ascent
= font
->ascent
+ boff
;
1952 it
->descent
= font
->descent
- boff
;
1953 it
->phys_ascent
= pcm
->ascent
+ boff
;
1954 it
->phys_descent
= pcm
->descent
- boff
;
1956 && (pcm
->lbearing
< 0
1957 || pcm
->rbearing
> pcm
->width
))
1958 it
->glyph_row
->contains_overlapping_glyphs_p
= 1;
1960 if (face
->box
!= FACE_NO_BOX
)
1962 int thick
= face
->box_line_width
;
1963 it
->ascent
+= thick
;
1964 it
->descent
+= thick
;
1966 if (it
->start_of_box_run_p
)
1967 it
->pixel_width
+= thick
;
1968 if (it
->end_of_box_run_p
)
1969 it
->pixel_width
+= thick
;
1972 /* If face has an overline, add the height of the overline
1973 (1 pixel) and a 1 pixel margin to the character height. */
1974 if (face
->overline_p
)
1977 take_vertical_position_into_account (it
);
1980 x_append_glyph (it
);
1983 else if (it
->what
== IT_COMPOSITION
)
1985 /* Note: A composition is represented as one glyph in the
1986 glyph matrix. There are no padding glyphs. */
1991 int font_not_found_p
;
1992 struct font_info
*font_info
;
1993 int boff
; /* baseline offset */
1994 struct composition
*cmp
= composition_table
[it
->cmp_id
];
1996 /* Maybe translate single-byte characters to multibyte. */
1997 it
->char_to_display
= it
->c
;
1998 if (unibyte_display_via_language_environment
1999 && SINGLE_BYTE_CHAR_P (it
->c
)
2002 && !NILP (Vnonascii_translation_table
))))
2004 it
->char_to_display
= unibyte_char_to_multibyte (it
->c
);
2005 it
->charset
= CHAR_CHARSET (it
->char_to_display
);
2008 /* Get face and font to use. Encode IT->char_to_display. */
2009 face
= x_get_char_face_and_encoding (it
->f
, it
->char_to_display
,
2010 it
->face_id
, &char2b
,
2014 /* When no suitable font found, use the default font. */
2015 font_not_found_p
= font
== NULL
;
2016 if (font_not_found_p
)
2018 font
= FRAME_FONT (it
->f
);
2019 boff
= it
->f
->output_data
.x
->baseline_offset
;
2024 font_info
= FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2025 boff
= font_info
->baseline_offset
;
2026 if (font_info
->vertical_centering
)
2027 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2030 /* There are no padding glyphs, so there is only one glyph to
2031 produce for the composition. Important is that pixel_width,
2032 ascent and descent are the values of what is drawn by
2033 draw_glyphs (i.e. the values of the overall glyphs composed). */
2036 /* If we have not yet calculated pixel size data of glyphs of
2037 the composition for the current face font, calculate them
2038 now. Theoretically, we have to check all fonts for the
2039 glyphs, but that requires much time and memory space. So,
2040 here we check only the font of the first glyph. This leads
2041 to incorrect display very rarely, and C-l (recenter) can
2042 correct the display anyway. */
2043 if (cmp
->font
!= (void *) font
)
2045 /* Ascent and descent of the font of the first character of
2046 this composition (adjusted by baseline offset). Ascent
2047 and descent of overall glyphs should not be less than
2048 them respectively. */
2049 int font_ascent
= font
->ascent
+ boff
;
2050 int font_descent
= font
->descent
- boff
;
2051 /* Bounding box of the overall glyphs. */
2052 int leftmost
, rightmost
, lowest
, highest
;
2055 cmp
->font
= (void *) font
;
2057 /* Initialize the bounding box. */
2058 pcm
= x_per_char_metric (font
, &char2b
);
2060 rightmost
= pcm
->width
;
2061 lowest
= - pcm
->descent
+ boff
;
2062 highest
= pcm
->ascent
+ boff
;
2064 && font_info
->default_ascent
2065 && CHAR_TABLE_P (Vuse_default_ascent
)
2066 && !NILP (Faref (Vuse_default_ascent
,
2067 make_number (it
->char_to_display
))))
2068 highest
= font_info
->default_ascent
+ boff
;
2070 /* Draw the first glyph at the normal position. It may be
2071 shifted to right later if some other glyphs are drawn at
2073 cmp
->offsets
[0] = 0;
2074 cmp
->offsets
[1] = boff
;
2076 /* Set cmp->offsets for the remaining glyphs. */
2077 for (i
= 1; i
< cmp
->glyph_len
; i
++)
2079 int left
, right
, btm
, top
;
2080 int ch
= COMPOSITION_GLYPH (cmp
, i
);
2082 face
= x_get_char_face_and_encoding (it
->f
, ch
,
2083 it
->face_id
, &char2b
,
2088 font
= FRAME_FONT (it
->f
);
2089 boff
= it
->f
->output_data
.x
->baseline_offset
;
2095 = FONT_INFO_FROM_ID (it
->f
, face
->font_info_id
);
2096 boff
= font_info
->baseline_offset
;
2097 if (font_info
->vertical_centering
)
2098 boff
= VCENTER_BASELINE_OFFSET (font
, it
->f
) - boff
;
2101 pcm
= x_per_char_metric (font
, &char2b
);
2103 if (cmp
->method
!= COMPOSITION_WITH_RULE_ALTCHARS
)
2105 /* Relative composition with or without
2107 left
= (leftmost
+ rightmost
- pcm
->width
) / 2;
2108 btm
= - pcm
->descent
+ boff
;
2109 if (font_info
&& font_info
->relative_compose
2110 && (! CHAR_TABLE_P (Vignore_relative_composition
)
2111 || NILP (Faref (Vignore_relative_composition
,
2112 make_number (ch
)))))
2116 >= font_info
->relative_compose
)
2117 /* One extra pixel between two glyphs. */
2119 else if (pcm
->ascent
<= 0)
2120 /* One extra pixel between two glyphs. */
2121 btm
= lowest
- 1 - pcm
->ascent
- pcm
->descent
;
2126 /* A composition rule is specified by an integer
2127 value that encodes global and new reference
2128 points (GREF and NREF). GREF and NREF are
2129 specified by numbers as below:
2137 ---3---4---5--- baseline
2139 6---7---8 -- descent
2141 int rule
= COMPOSITION_RULE (cmp
, i
);
2142 int gref
, nref
, grefx
, grefy
, nrefx
, nrefy
;
2144 COMPOSITION_DECODE_RULE (rule
, gref
, nref
);
2145 grefx
= gref
% 3, nrefx
= nref
% 3;
2146 grefy
= gref
/ 3, nrefy
= nref
/ 3;
2149 + grefx
* (rightmost
- leftmost
) / 2
2150 - nrefx
* pcm
->width
/ 2);
2151 btm
= ((grefy
== 0 ? highest
2153 : grefy
== 2 ? lowest
2154 : (highest
+ lowest
) / 2)
2155 - (nrefy
== 0 ? pcm
->ascent
+ pcm
->descent
2156 : nrefy
== 1 ? pcm
->descent
- boff
2158 : (pcm
->ascent
+ pcm
->descent
) / 2));
2161 cmp
->offsets
[i
* 2] = left
;
2162 cmp
->offsets
[i
* 2 + 1] = btm
+ pcm
->descent
;
2164 /* Update the bounding box of the overall glyphs. */
2165 right
= left
+ pcm
->width
;
2166 top
= btm
+ pcm
->descent
+ pcm
->ascent
;
2167 if (left
< leftmost
)
2169 if (right
> rightmost
)
2177 /* If there are glyphs whose x-offsets are negative,
2178 shift all glyphs to the right and make all x-offsets
2182 for (i
= 0; i
< cmp
->glyph_len
; i
++)
2183 cmp
->offsets
[i
* 2] -= leftmost
;
2184 rightmost
-= leftmost
;
2187 cmp
->pixel_width
= rightmost
;
2188 cmp
->ascent
= highest
;
2189 cmp
->descent
= - lowest
;
2190 if (cmp
->ascent
< font_ascent
)
2191 cmp
->ascent
= font_ascent
;
2192 if (cmp
->descent
< font_descent
)
2193 cmp
->descent
= font_descent
;
2196 it
->pixel_width
= cmp
->pixel_width
;
2197 it
->ascent
= it
->phys_ascent
= cmp
->ascent
;
2198 it
->descent
= it
->phys_descent
= cmp
->descent
;
2200 if (face
->box
!= FACE_NO_BOX
)
2202 int thick
= face
->box_line_width
;
2203 it
->ascent
+= thick
;
2204 it
->descent
+= thick
;
2206 if (it
->start_of_box_run_p
)
2207 it
->pixel_width
+= thick
;
2208 if (it
->end_of_box_run_p
)
2209 it
->pixel_width
+= thick
;
2212 /* If face has an overline, add the height of the overline
2213 (1 pixel) and a 1 pixel margin to the character height. */
2214 if (face
->overline_p
)
2217 take_vertical_position_into_account (it
);
2220 x_append_composite_glyph (it
);
2222 else if (it
->what
== IT_IMAGE
)
2223 x_produce_image_glyph (it
);
2224 else if (it
->what
== IT_STRETCH
)
2225 x_produce_stretch_glyph (it
);
2227 /* Accumulate dimensions. */
2228 xassert (it
->ascent
>= 0 && it
->descent
> 0);
2229 if (it
->area
== TEXT_AREA
)
2230 it
->current_x
+= it
->pixel_width
;
2232 it
->max_ascent
= max (it
->max_ascent
, it
->ascent
);
2233 it
->max_descent
= max (it
->max_descent
, it
->descent
);
2234 it
->max_phys_ascent
= max (it
->max_phys_ascent
, it
->phys_ascent
);
2235 it
->max_phys_descent
= max (it
->max_phys_descent
, it
->phys_descent
);
2239 /* Estimate the pixel height of the mode or top line on frame F.
2240 FACE_ID specifies what line's height to estimate. */
2243 x_estimate_mode_line_height (f
, face_id
)
2245 enum face_id face_id
;
2249 /* This function is called so early when Emacs starts that the face
2250 cache and mode line face are not yet initialized. */
2251 if (FRAME_FACE_CACHE (f
))
2253 struct face
*face
= FACE_FROM_ID (f
, face_id
);
2255 height
= FONT_HEIGHT (face
->font
) + 2 * face
->box_line_width
;
2262 /***********************************************************************
2264 ***********************************************************************/
2266 /* A sequence of glyphs to be drawn in the same face.
2268 This data structure is not really completely X specific, so it
2269 could possibly, at least partially, be useful for other systems. It
2270 is currently not part of the external redisplay interface because
2271 it's not clear what other systems will need. */
2275 /* X-origin of the string. */
2278 /* Y-origin and y-position of the base line of this string. */
2281 /* The width of the string, not including a face extension. */
2284 /* The width of the string, including a face extension. */
2285 int background_width
;
2287 /* The height of this string. This is the height of the line this
2288 string is drawn in, and can be different from the height of the
2289 font the string is drawn in. */
2292 /* Number of pixels this string overwrites in front of its x-origin.
2293 This number is zero if the string has an lbearing >= 0; it is
2294 -lbearing, if the string has an lbearing < 0. */
2297 /* Number of pixels this string overwrites past its right-most
2298 nominal x-position, i.e. x + width. Zero if the string's
2299 rbearing is <= its nominal width, rbearing - width otherwise. */
2302 /* The frame on which the glyph string is drawn. */
2305 /* The window on which the glyph string is drawn. */
2308 /* X display and window for convenience. */
2312 /* The glyph row for which this string was built. It determines the
2313 y-origin and height of the string. */
2314 struct glyph_row
*row
;
2316 /* The area within row. */
2317 enum glyph_row_area area
;
2319 /* Characters to be drawn, and number of characters. */
2323 /* Character set of this glyph string. */
2326 /* A face-override for drawing cursors, mouse face and similar. */
2327 enum draw_glyphs_face hl
;
2329 /* Face in which this string is to be drawn. */
2332 /* Font in which this string is to be drawn. */
2335 /* Font info for this string. */
2336 struct font_info
*font_info
;
2338 /* Non-null means this string describes (part of) a composition.
2339 All characters from char2b are drawn composed. */
2340 struct composition
*cmp
;
2342 /* Index of this glyph string's first character in the glyph
2343 definition of CMP. If this is zero, this glyph string describes
2344 the first character of a composition. */
2347 /* 1 means this glyph strings face has to be drawn to the right end
2348 of the window's drawing area. */
2349 unsigned extends_to_end_of_line_p
: 1;
2351 /* 1 means the background of this string has been drawn. */
2352 unsigned background_filled_p
: 1;
2354 /* 1 means glyph string must be drawn with 16-bit functions. */
2355 unsigned two_byte_p
: 1;
2357 /* 1 means that the original font determined for drawing this glyph
2358 string could not be loaded. The member `font' has been set to
2359 the frame's default font in this case. */
2360 unsigned font_not_found_p
: 1;
2362 /* 1 means that the face in which this glyph string is drawn has a
2364 unsigned stippled_p
: 1;
2366 /* 1 means only the foreground of this glyph string must be drawn,
2367 and we should use the physical height of the line this glyph
2368 string appears in as clip rect. */
2369 unsigned for_overlaps_p
: 1;
2371 /* The GC to use for drawing this glyph string. */
2374 /* A pointer to the first glyph in the string. This glyph
2375 corresponds to char2b[0]. Needed to draw rectangles if
2376 font_not_found_p is 1. */
2377 struct glyph
*first_glyph
;
2379 /* Image, if any. */
2382 struct glyph_string
*next
, *prev
;
2389 x_dump_glyph_string (s
)
2390 struct glyph_string
*s
;
2392 fprintf (stderr
, "glyph string\n");
2393 fprintf (stderr
, " x, y, w, h = %d, %d, %d, %d\n",
2394 s
->x
, s
->y
, s
->width
, s
->height
);
2395 fprintf (stderr
, " ybase = %d\n", s
->ybase
);
2396 fprintf (stderr
, " hl = %d\n", s
->hl
);
2397 fprintf (stderr
, " left overhang = %d, right = %d\n",
2398 s
->left_overhang
, s
->right_overhang
);
2399 fprintf (stderr
, " nchars = %d\n", s
->nchars
);
2400 fprintf (stderr
, " extends to end of line = %d\n",
2401 s
->extends_to_end_of_line_p
);
2402 fprintf (stderr
, " font height = %d\n", FONT_HEIGHT (s
->font
));
2403 fprintf (stderr
, " bg width = %d\n", s
->background_width
);
2406 #endif /* GLYPH_DEBUG */
2410 static void x_append_glyph_string_lists
P_ ((struct glyph_string
**,
2411 struct glyph_string
**,
2412 struct glyph_string
*,
2413 struct glyph_string
*));
2414 static void x_prepend_glyph_string_lists
P_ ((struct glyph_string
**,
2415 struct glyph_string
**,
2416 struct glyph_string
*,
2417 struct glyph_string
*));
2418 static void x_append_glyph_string
P_ ((struct glyph_string
**,
2419 struct glyph_string
**,
2420 struct glyph_string
*));
2421 static int x_left_overwritten
P_ ((struct glyph_string
*));
2422 static int x_left_overwriting
P_ ((struct glyph_string
*));
2423 static int x_right_overwritten
P_ ((struct glyph_string
*));
2424 static int x_right_overwriting
P_ ((struct glyph_string
*));
2425 static int x_fill_glyph_string
P_ ((struct glyph_string
*, int, int, int,
2427 static void x_init_glyph_string
P_ ((struct glyph_string
*,
2428 XChar2b
*, struct window
*,
2430 enum glyph_row_area
, int,
2431 enum draw_glyphs_face
));
2432 static int x_draw_glyphs
P_ ((struct window
*, int , struct glyph_row
*,
2433 enum glyph_row_area
, int, int,
2434 enum draw_glyphs_face
, int *, int *, int));
2435 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2436 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2437 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2439 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2440 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2441 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2442 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2443 static void x_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2444 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2445 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2446 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2447 static void x_get_glyph_overhangs
P_ ((struct glyph
*, struct frame
*,
2449 static void x_compute_overhangs_and_x
P_ ((struct glyph_string
*, int, int));
2450 static int x_alloc_lighter_color
P_ ((struct frame
*, Display
*, Colormap
,
2451 unsigned long *, double, int));
2452 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2453 double, int, unsigned long));
2454 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2455 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2456 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2457 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2458 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2459 static void x_fill_image_glyph_string
P_ ((struct glyph_string
*));
2460 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2462 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2463 int, int, int, int, XRectangle
*));
2464 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2465 int, int, int, XRectangle
*));
2466 static void x_fix_overlapping_area
P_ ((struct window
*, struct glyph_row
*,
2467 enum glyph_row_area
));
2470 /* Append the list of glyph strings with head H and tail T to the list
2471 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2474 x_append_glyph_string_lists (head
, tail
, h
, t
)
2475 struct glyph_string
**head
, **tail
;
2476 struct glyph_string
*h
, *t
;
2490 /* Prepend the list of glyph strings with head H and tail T to the
2491 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2495 x_prepend_glyph_string_lists (head
, tail
, h
, t
)
2496 struct glyph_string
**head
, **tail
;
2497 struct glyph_string
*h
, *t
;
2511 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2512 Set *HEAD and *TAIL to the resulting list. */
2515 x_append_glyph_string (head
, tail
, s
)
2516 struct glyph_string
**head
, **tail
;
2517 struct glyph_string
*s
;
2519 s
->next
= s
->prev
= NULL
;
2520 x_append_glyph_string_lists (head
, tail
, s
, s
);
2524 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2529 struct glyph_string
*s
;
2531 if (s
->font
== FRAME_FONT (s
->f
)
2532 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2533 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2535 s
->gc
= s
->f
->output_data
.x
->cursor_gc
;
2538 /* Cursor on non-default face: must merge. */
2542 xgcv
.background
= s
->f
->output_data
.x
->cursor_pixel
;
2543 xgcv
.foreground
= s
->face
->background
;
2545 /* If the glyph would be invisible, try a different foreground. */
2546 if (xgcv
.foreground
== xgcv
.background
)
2547 xgcv
.foreground
= s
->face
->foreground
;
2548 if (xgcv
.foreground
== xgcv
.background
)
2549 xgcv
.foreground
= s
->f
->output_data
.x
->cursor_foreground_pixel
;
2550 if (xgcv
.foreground
== xgcv
.background
)
2551 xgcv
.foreground
= s
->face
->foreground
;
2553 /* Make sure the cursor is distinct from text in this face. */
2554 if (xgcv
.background
== s
->face
->background
2555 && xgcv
.foreground
== s
->face
->foreground
)
2557 xgcv
.background
= s
->face
->foreground
;
2558 xgcv
.foreground
= s
->face
->background
;
2561 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2562 xgcv
.font
= s
->font
->fid
;
2563 xgcv
.graphics_exposures
= False
;
2564 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2566 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2567 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2570 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2571 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2573 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2578 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2581 x_set_mouse_face_gc (s
)
2582 struct glyph_string
*s
;
2586 /* What face has to be used for the mouse face? */
2587 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2588 face_id
= FACE_FOR_CHARSET (s
->f
, face_id
, s
->charset
);
2589 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2590 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2592 /* If font in this face is same as S->font, use it. */
2593 if (s
->font
== s
->face
->font
)
2594 s
->gc
= s
->face
->gc
;
2597 /* Otherwise construct scratch_cursor_gc with values from FACE
2602 xgcv
.background
= s
->face
->background
;
2603 xgcv
.foreground
= s
->face
->foreground
;
2604 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2605 xgcv
.font
= s
->font
->fid
;
2606 xgcv
.graphics_exposures
= False
;
2607 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
2609 if (FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2610 XChangeGC (s
->display
, FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2613 FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2614 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2616 s
->gc
= FRAME_X_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2619 xassert (s
->gc
!= 0);
2623 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2624 Faces to use in the mode line have already been computed when the
2625 matrix was built, so there isn't much to do, here. */
2628 x_set_mode_line_face_gc (s
)
2629 struct glyph_string
*s
;
2631 s
->gc
= s
->face
->gc
;
2632 xassert (s
->gc
!= 0);
2636 /* Set S->gc of glyph string S for drawing that glyph string. Set
2637 S->stippled_p to a non-zero value if the face of S has a stipple
2641 x_set_glyph_string_gc (s
)
2642 struct glyph_string
*s
;
2644 if (s
->hl
== DRAW_NORMAL_TEXT
)
2646 s
->gc
= s
->face
->gc
;
2647 s
->stippled_p
= s
->face
->stipple
!= 0;
2649 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2651 x_set_mode_line_face_gc (s
);
2652 s
->stippled_p
= s
->face
->stipple
!= 0;
2654 else if (s
->hl
== DRAW_CURSOR
)
2656 x_set_cursor_gc (s
);
2659 else if (s
->hl
== DRAW_MOUSE_FACE
)
2661 x_set_mouse_face_gc (s
);
2662 s
->stippled_p
= s
->face
->stipple
!= 0;
2664 else if (s
->hl
== DRAW_IMAGE_RAISED
2665 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2667 s
->gc
= s
->face
->gc
;
2668 s
->stippled_p
= s
->face
->stipple
!= 0;
2672 s
->gc
= s
->face
->gc
;
2673 s
->stippled_p
= s
->face
->stipple
!= 0;
2676 /* GC must have been set. */
2677 xassert (s
->gc
!= 0);
2681 /* Return in *R the clipping rectangle for glyph string S. */
2684 x_get_glyph_string_clip_rect (s
, r
)
2685 struct glyph_string
*s
;
2688 if (s
->row
->full_width_p
)
2690 /* Draw full-width. X coordinates are relative to S->w->left. */
2691 int canon_x
= CANON_X_UNIT (s
->f
);
2693 r
->x
= WINDOW_LEFT_MARGIN (s
->w
) * canon_x
;
2694 r
->width
= XFASTINT (s
->w
->width
) * canon_x
;
2696 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s
->f
))
2698 int width
= FRAME_SCROLL_BAR_WIDTH (s
->f
) * canon_x
;
2699 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s
->f
))
2703 r
->x
+= FRAME_INTERNAL_BORDER_WIDTH (s
->f
);
2705 /* Unless displaying a mode or menu bar line, which are always
2706 fully visible, clip to the visible part of the row. */
2707 if (s
->w
->pseudo_window_p
)
2708 r
->height
= s
->row
->visible_height
;
2710 r
->height
= s
->height
;
2714 /* This is a text line that may be partially visible. */
2715 r
->x
= WINDOW_AREA_TO_FRAME_PIXEL_X (s
->w
, s
->area
, 0);
2716 r
->width
= window_box_width (s
->w
, s
->area
);
2717 r
->height
= s
->row
->visible_height
;
2720 /* Don't use S->y for clipping because it doesn't take partially
2721 visible lines into account. For example, it can be negative for
2722 partially visible lines at the top of a window. */
2723 if (!s
->row
->full_width_p
2724 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s
->w
, s
->row
))
2725 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2727 r
->y
= max (0, s
->row
->y
);
2729 /* If drawing a tool-bar window, draw it over the internal border
2730 at the top of the window. */
2731 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
2732 r
->y
-= s
->f
->output_data
.x
->internal_border_width
;
2734 /* If S draws overlapping rows, it's sufficient to use the top and
2735 bottom of the window for clipping because this glyph string
2736 intentionally draws over other lines. */
2737 if (s
->for_overlaps_p
)
2739 r
->y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s
->w
);
2740 r
->height
= window_text_bottom_y (s
->w
) - r
->y
;
2743 r
->y
= WINDOW_TO_FRAME_PIXEL_Y (s
->w
, r
->y
);
2747 /* Set clipping for output of glyph string S. S may be part of a mode
2748 line or menu if we don't have X toolkit support. */
2751 x_set_glyph_string_clipping (s
)
2752 struct glyph_string
*s
;
2755 x_get_glyph_string_clip_rect (s
, &r
);
2756 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, &r
, 1, Unsorted
);
2760 /* Compute left and right overhang of glyph string S. If S is a glyph
2761 string for a composition, assume overhangs don't exist. */
2764 x_compute_glyph_string_overhangs (s
)
2765 struct glyph_string
*s
;
2768 && s
->first_glyph
->type
== CHAR_GLYPH
)
2771 int direction
, font_ascent
, font_descent
;
2772 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
2773 &font_ascent
, &font_descent
, &cs
);
2774 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2775 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2780 /* Compute overhangs and x-positions for glyph string S and its
2781 predecessors, or successors. X is the starting x-position for S.
2782 BACKWARD_P non-zero means process predecessors. */
2785 x_compute_overhangs_and_x (s
, x
, backward_p
)
2786 struct glyph_string
*s
;
2794 x_compute_glyph_string_overhangs (s
);
2804 x_compute_glyph_string_overhangs (s
);
2813 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2814 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2815 assumed to be zero. */
2818 x_get_glyph_overhangs (glyph
, f
, left
, right
)
2819 struct glyph
*glyph
;
2827 if (glyph
->type
== CHAR_GLYPH
)
2831 struct font_info
*font_info
;
2834 face
= x_get_glyph_face_and_encoding (f
, glyph
, &char2b
);
2836 font_info
= FONT_INFO_FROM_ID (f
, face
->font_info_id
);
2839 XCharStruct
*pcm
= x_per_char_metric (font
, &char2b
);
2841 if (pcm
->rbearing
> pcm
->width
)
2842 *right
= pcm
->rbearing
- pcm
->width
;
2843 if (pcm
->lbearing
< 0)
2844 *left
= -pcm
->lbearing
;
2850 /* Return the index of the first glyph preceding glyph string S that
2851 is overwritten by S because of S's left overhang. Value is -1
2852 if no glyphs are overwritten. */
2855 x_left_overwritten (s
)
2856 struct glyph_string
*s
;
2860 if (s
->left_overhang
)
2863 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2864 int first
= s
->first_glyph
- glyphs
;
2866 for (i
= first
- 1; i
>= 0 && x
> -s
->left_overhang
; --i
)
2867 x
-= glyphs
[i
].pixel_width
;
2878 /* Return the index of the first glyph preceding glyph string S that
2879 is overwriting S because of its right overhang. Value is -1 if no
2880 glyph in front of S overwrites S. */
2883 x_left_overwriting (s
)
2884 struct glyph_string
*s
;
2887 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2888 int first
= s
->first_glyph
- glyphs
;
2892 for (i
= first
- 1; i
>= 0; --i
)
2895 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2898 x
-= glyphs
[i
].pixel_width
;
2905 /* Return the index of the last glyph following glyph string S that is
2906 not overwritten by S because of S's right overhang. Value is -1 if
2907 no such glyph is found. */
2910 x_right_overwritten (s
)
2911 struct glyph_string
*s
;
2915 if (s
->right_overhang
)
2918 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2919 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
2920 int end
= s
->row
->used
[s
->area
];
2922 for (i
= first
; i
< end
&& s
->right_overhang
> x
; ++i
)
2923 x
+= glyphs
[i
].pixel_width
;
2932 /* Return the index of the last glyph following glyph string S that
2933 overwrites S because of its left overhang. Value is negative
2934 if no such glyph is found. */
2937 x_right_overwriting (s
)
2938 struct glyph_string
*s
;
2941 int end
= s
->row
->used
[s
->area
];
2942 struct glyph
*glyphs
= s
->row
->glyphs
[s
->area
];
2943 int first
= (s
->first_glyph
- glyphs
) + (s
->cmp
? 1 : s
->nchars
);
2947 for (i
= first
; i
< end
; ++i
)
2950 x_get_glyph_overhangs (glyphs
+ i
, s
->f
, &left
, &right
);
2953 x
+= glyphs
[i
].pixel_width
;
2960 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2963 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2964 struct glyph_string
*s
;
2968 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
, &xgcv
);
2969 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2970 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2971 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2975 /* Draw the background of glyph_string S. If S->background_filled_p
2976 is non-zero don't draw it. FORCE_P non-zero means draw the
2977 background even if it wouldn't be drawn normally. This is used
2978 when a string preceding S draws into the background of S, or S
2979 contains the first component of a composition. */
2982 x_draw_glyph_string_background (s
, force_p
)
2983 struct glyph_string
*s
;
2986 /* Nothing to do if background has already been drawn or if it
2987 shouldn't be drawn in the first place. */
2988 if (!s
->background_filled_p
)
2992 /* Fill background with a stipple pattern. */
2993 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2994 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2995 s
->y
+ s
->face
->box_line_width
,
2996 s
->background_width
,
2997 s
->height
- 2 * s
->face
->box_line_width
);
2998 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2999 s
->background_filled_p
= 1;
3001 else if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * s
->face
->box_line_width
3002 || s
->font_not_found_p
3003 || s
->extends_to_end_of_line_p
3006 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ s
->face
->box_line_width
,
3007 s
->background_width
,
3008 s
->height
- 2 * s
->face
->box_line_width
);
3009 s
->background_filled_p
= 1;
3015 /* Draw the foreground of glyph string S. */
3018 x_draw_glyph_string_foreground (s
)
3019 struct glyph_string
*s
;
3023 /* If first glyph of S has a left box line, start drawing the text
3024 of S to the right of that box line. */
3025 if (s
->face
->box
!= FACE_NO_BOX
3026 && s
->first_glyph
->left_box_line_p
)
3027 x
= s
->x
+ s
->face
->box_line_width
;
3031 /* Draw characters of S as rectangles if S's font could not be
3033 if (s
->font_not_found_p
)
3035 for (i
= 0; i
< s
->nchars
; ++i
)
3037 struct glyph
*g
= s
->first_glyph
+ i
;
3038 XDrawRectangle (s
->display
, s
->window
,
3039 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
3041 x
+= g
->pixel_width
;
3046 char *char1b
= (char *) s
->char2b
;
3047 int boff
= s
->font_info
->baseline_offset
;
3049 if (s
->font_info
->vertical_centering
)
3050 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
3052 /* If we can use 8-bit functions, condense S->char2b. */
3054 for (i
= 0; i
< s
->nchars
; ++i
)
3055 char1b
[i
] = s
->char2b
[i
].byte2
;
3057 /* Draw text with XDrawString if background has already been
3058 filled. Otherwise, use XDrawImageString. (Note that
3059 XDrawImageString is usually faster than XDrawString.) Always
3060 use XDrawImageString when drawing the cursor so that there is
3061 no chance that characters under a box cursor are invisible. */
3062 if (s
->for_overlaps_p
3063 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
3065 /* Draw characters with 16-bit or 8-bit functions. */
3067 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
3068 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3070 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
3071 s
->ybase
- boff
, char1b
, s
->nchars
);
3076 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
3077 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
3079 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
3080 s
->ybase
- boff
, char1b
, s
->nchars
);
3085 /* Draw the foreground of composite glyph string S. */
3088 x_draw_composite_glyph_string_foreground (s
)
3089 struct glyph_string
*s
;
3093 /* If first glyph of S has a left box line, start drawing the text
3094 of S to the right of that box line. */
3095 if (s
->face
->box
!= FACE_NO_BOX
3096 && s
->first_glyph
->left_box_line_p
)
3097 x
= s
->x
+ s
->face
->box_line_width
;
3101 /* S is a glyph string for a composition. S->gidx is the index of
3102 the first character drawn for glyphs of this composition.
3103 S->gidx == 0 means we are drawing the very first character of
3104 this composition. */
3106 /* Draw a rectangle for the composition if the font for the very
3107 first character of the composition could not be loaded. */
3108 if (s
->font_not_found_p
)
3111 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
3112 s
->width
- 1, s
->height
- 1);
3116 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
3117 XDrawString16 (s
->display
, s
->window
, s
->gc
,
3118 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
3119 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
3125 #ifdef USE_X_TOOLKIT
3127 /* Allocate the color COLOR->pixel on the screen and display of
3128 widget WIDGET in colormap CMAP. If an exact match cannot be
3129 allocated, try the nearest color available. Value is non-zero
3130 if successful. This is called from lwlib. */
3133 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
3139 struct x_display_info
*dpyinfo
;
3142 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
3144 /* Find the top-level shell of the widget. Note that this function
3145 can be called when the widget is not yet realized, so XtWindow
3146 (widget) == 0. That's the reason we can't simply use
3147 x_any_window_to_frame. */
3148 while (!XtIsTopLevelShell (widget
))
3149 widget
= XtParent (widget
);
3151 /* Look for a frame with that top-level widget. Allocate the color
3152 on that frame to get the right gamma correction value. */
3153 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
3154 if (GC_FRAMEP (XCAR (tail
))
3155 && (f
= XFRAME (XCAR (tail
)),
3156 (f
->output_data
.nothing
!= 1
3157 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
3158 && f
->output_data
.x
->widget
== widget
)
3159 return x_alloc_nearest_color (f
, cmap
, color
);
3164 #endif /* USE_X_TOOLKIT */
3167 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3168 CMAP. If an exact match can't be allocated, try the nearest color
3169 available. Value is non-zero if successful. Set *COLOR to the
3173 x_alloc_nearest_color (f
, cmap
, color
)
3178 Display
*display
= FRAME_X_DISPLAY (f
);
3179 Screen
*screen
= FRAME_X_SCREEN (f
);
3182 gamma_correct (f
, color
);
3183 rc
= XAllocColor (display
, cmap
, color
);
3186 /* If we got to this point, the colormap is full, so we're going
3187 to try to get the next closest color. The algorithm used is
3188 a least-squares matching, which is what X uses for closest
3189 color matching with StaticColor visuals. */
3191 unsigned long nearest_delta
= ~0;
3192 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
3193 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
3195 for (i
= 0; i
< ncells
; ++i
)
3197 XQueryColors (display
, cmap
, cells
, ncells
);
3199 for (nearest
= i
= 0; i
< ncells
; ++i
)
3201 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
3202 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
3203 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
3204 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
3206 if (delta
< nearest_delta
)
3209 nearest_delta
= delta
;
3213 color
->red
= cells
[nearest
].red
;
3214 color
->green
= cells
[nearest
].green
;
3215 color
->blue
= cells
[nearest
].blue
;
3216 rc
= XAllocColor (display
, cmap
, color
);
3223 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3224 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3225 If this produces the same color as PIXEL, try a color where all RGB
3226 values have DELTA added. Return the allocated color in *PIXEL.
3227 DISPLAY is the X display, CMAP is the colormap to operate on.
3228 Value is non-zero if successful. */
3231 x_alloc_lighter_color (f
, display
, cmap
, pixel
, factor
, delta
)
3235 unsigned long *pixel
;
3242 /* Get RGB color values. */
3243 color
.pixel
= *pixel
;
3244 XQueryColor (display
, cmap
, &color
);
3246 /* Change RGB values by specified FACTOR. Avoid overflow! */
3247 xassert (factor
>= 0);
3248 new.red
= min (0xffff, factor
* color
.red
);
3249 new.green
= min (0xffff, factor
* color
.green
);
3250 new.blue
= min (0xffff, factor
* color
.blue
);
3252 /* Try to allocate the color. */
3253 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3256 if (new.pixel
== *pixel
)
3258 /* If we end up with the same color as before, try adding
3259 delta to the RGB values. */
3260 int class = FRAME_X_DISPLAY_INFO (f
)->visual
->class;
3262 /* If display has an immutable color map, freeing colors is
3263 not necessary and some servers don't allow it. So don't
3265 if (class != StaticColor
3266 && class != StaticGray
3267 && class != TrueColor
)
3268 XFreeColors (display
, cmap
, &new.pixel
, 1, 0);
3270 new.red
= min (0xffff, delta
+ color
.red
);
3271 new.green
= min (0xffff, delta
+ color
.green
);
3272 new.blue
= min (0xffff, delta
+ color
.blue
);
3273 success_p
= x_alloc_nearest_color (f
, cmap
, &new);
3284 /* Set up the foreground color for drawing relief lines of glyph
3285 string S. RELIEF is a pointer to a struct relief containing the GC
3286 with which lines will be drawn. Use a color that is FACTOR or
3287 DELTA lighter or darker than the relief's background which is found
3288 in S->f->output_data.x->relief_background. If such a color cannot
3289 be allocated, use DEFAULT_PIXEL, instead. */
3292 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
3294 struct relief
*relief
;
3297 unsigned long default_pixel
;
3300 struct x_output
*di
= f
->output_data
.x
;
3301 unsigned long mask
= GCForeground
| GCLineWidth
| GCGraphicsExposures
;
3302 unsigned long pixel
;
3303 unsigned long background
= di
->relief_background
;
3304 Colormap cmap
= DefaultColormapOfScreen (FRAME_X_SCREEN (f
));
3305 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
3306 Display
*dpy
= FRAME_X_DISPLAY (f
);
3308 xgcv
.graphics_exposures
= False
;
3309 xgcv
.line_width
= 1;
3311 /* Free previously allocated color. The color cell will be reused
3312 when it has been freed as many times as it was allocated, so this
3313 doesn't affect faces using the same colors. */
3315 && relief
->allocated_p
)
3317 /* If display has an immutable color map, freeing colors is not
3318 necessary and some servers don't allow it. So don't do it. */
3319 int class = dpyinfo
->visual
->class;
3320 if (class != StaticColor
3321 && class != StaticGray
3322 && class != TrueColor
)
3323 XFreeColors (dpy
, cmap
, &relief
->pixel
, 1, 0);
3324 relief
->allocated_p
= 0;
3327 /* Allocate new color. */
3328 xgcv
.foreground
= default_pixel
;
3330 if (dpyinfo
->n_planes
!= 1
3331 && x_alloc_lighter_color (f
, dpy
, cmap
, &pixel
, factor
, delta
))
3333 relief
->allocated_p
= 1;
3334 xgcv
.foreground
= relief
->pixel
= pixel
;
3337 if (relief
->gc
== 0)
3339 xgcv
.stipple
= dpyinfo
->gray
;
3341 relief
->gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
), mask
, &xgcv
);
3344 XChangeGC (dpy
, relief
->gc
, mask
, &xgcv
);
3348 /* Set up colors for the relief lines around glyph string S. */
3351 x_setup_relief_colors (s
)
3352 struct glyph_string
*s
;
3354 struct x_output
*di
= s
->f
->output_data
.x
;
3355 unsigned long color
;
3357 if (s
->face
->use_box_color_for_shadows_p
)
3358 color
= s
->face
->box_color
;
3363 /* Get the background color of the face. */
3364 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
3365 color
= xgcv
.background
;
3368 if (di
->white_relief
.gc
== 0
3369 || color
!= di
->relief_background
)
3371 di
->relief_background
= color
;
3372 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
3373 WHITE_PIX_DEFAULT (s
->f
));
3374 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
3375 BLACK_PIX_DEFAULT (s
->f
));
3380 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3381 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3382 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3383 relief. LEFT_P non-zero means draw a relief on the left side of
3384 the rectangle. RIGHT_P non-zero means draw a relief on the right
3385 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3389 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
3390 raised_p
, left_p
, right_p
, clip_rect
)
3392 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
, raised_p
;
3393 XRectangle
*clip_rect
;
3399 gc
= f
->output_data
.x
->white_relief
.gc
;
3401 gc
= f
->output_data
.x
->black_relief
.gc
;
3402 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3405 for (i
= 0; i
< width
; ++i
)
3406 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3407 left_x
+ i
* left_p
, top_y
+ i
,
3408 right_x
+ 1 - i
* right_p
, top_y
+ i
);
3412 for (i
= 0; i
< width
; ++i
)
3413 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3414 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
3416 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3418 gc
= f
->output_data
.x
->black_relief
.gc
;
3420 gc
= f
->output_data
.x
->white_relief
.gc
;
3421 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, clip_rect
, 1, Unsorted
);
3424 for (i
= 0; i
< width
; ++i
)
3425 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3426 left_x
+ i
* left_p
, bottom_y
- i
,
3427 right_x
+ 1 - i
* right_p
, bottom_y
- i
);
3431 for (i
= 0; i
< width
; ++i
)
3432 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
3433 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
);
3435 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
3439 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3440 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3441 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3442 left side of the rectangle. RIGHT_P non-zero means draw a line
3443 on the right side of the rectangle. CLIP_RECT is the clipping
3444 rectangle to use when drawing. */
3447 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3448 left_p
, right_p
, clip_rect
)
3449 struct glyph_string
*s
;
3450 int left_x
, top_y
, right_x
, bottom_y
, left_p
, right_p
;
3451 XRectangle
*clip_rect
;
3455 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3456 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
3457 XSetClipRectangles (s
->display
, s
->gc
, 0, 0, clip_rect
, 1, Unsorted
);
3460 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3461 left_x
, top_y
, right_x
- left_x
, width
);
3465 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3466 left_x
, top_y
, width
, bottom_y
- top_y
);
3469 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3470 left_x
, bottom_y
- width
, right_x
- left_x
, width
);
3474 XFillRectangle (s
->display
, s
->window
, s
->gc
,
3475 right_x
- width
, top_y
, width
, bottom_y
- top_y
);
3477 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3478 XSetClipMask (s
->display
, s
->gc
, None
);
3482 /* Draw a box around glyph string S. */
3485 x_draw_glyph_string_box (s
)
3486 struct glyph_string
*s
;
3488 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
3489 int left_p
, right_p
;
3490 struct glyph
*last_glyph
;
3491 XRectangle clip_rect
;
3493 last_x
= window_box_right (s
->w
, s
->area
);
3494 if (s
->row
->full_width_p
3495 && !s
->w
->pseudo_window_p
)
3497 last_x
+= FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s
->f
);
3498 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s
->f
))
3499 last_x
+= FRAME_SCROLL_BAR_WIDTH (s
->f
) * CANON_X_UNIT (s
->f
);
3502 /* The glyph that may have a right box line. */
3503 last_glyph
= (s
->cmp
|| s
->img
3505 : s
->first_glyph
+ s
->nchars
- 1);
3507 width
= s
->face
->box_line_width
;
3508 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3510 right_x
= ((s
->row
->full_width_p
3512 : min (last_x
, s
->x
+ s
->background_width
) - 1));
3514 bottom_y
= top_y
+ s
->height
- 1;
3516 left_p
= (s
->first_glyph
->left_box_line_p
3517 || (s
->hl
== DRAW_MOUSE_FACE
3519 || s
->prev
->hl
!= s
->hl
)));
3520 right_p
= (last_glyph
->right_box_line_p
3521 || (s
->hl
== DRAW_MOUSE_FACE
3523 || s
->next
->hl
!= s
->hl
)));
3525 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3527 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3528 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3529 left_p
, right_p
, &clip_rect
);
3532 x_setup_relief_colors (s
);
3533 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3534 width
, raised_p
, left_p
, right_p
, &clip_rect
);
3539 /* Draw foreground of image glyph string S. */
3542 x_draw_image_foreground (s
)
3543 struct glyph_string
*s
;
3546 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3548 /* If first glyph of S has a left box line, start drawing it to the
3549 right of that line. */
3550 if (s
->face
->box
!= FACE_NO_BOX
3551 && s
->first_glyph
->left_box_line_p
)
3552 x
= s
->x
+ s
->face
->box_line_width
;
3556 /* If there is a margin around the image, adjust x- and y-position
3560 x
+= s
->img
->margin
;
3561 y
+= s
->img
->margin
;
3568 /* We can't set both a clip mask and use XSetClipRectangles
3569 because the latter also sets a clip mask. We also can't
3570 trust on the shape extension to be available
3571 (XShapeCombineRegion). So, compute the rectangle to draw
3573 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3576 XRectangle clip_rect
, image_rect
, r
;
3578 xgcv
.clip_mask
= s
->img
->mask
;
3579 xgcv
.clip_x_origin
= x
;
3580 xgcv
.clip_y_origin
= y
;
3581 xgcv
.function
= GXcopy
;
3582 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3584 x_get_glyph_string_clip_rect (s
, &clip_rect
);
3587 image_rect
.width
= s
->img
->width
;
3588 image_rect
.height
= s
->img
->height
;
3589 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
3590 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3591 r
.x
- x
, r
.y
- y
, r
.width
, r
.height
, r
.x
, r
.y
);
3595 XCopyArea (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
3596 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3598 /* When the image has a mask, we can expect that at
3599 least part of a mouse highlight or a block cursor will
3600 be visible. If the image doesn't have a mask, make
3601 a block cursor visible by drawing a rectangle around
3602 the image. I believe it's looking better if we do
3603 nothing here for mouse-face. */
3604 if (s
->hl
== DRAW_CURSOR
)
3605 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3606 s
->img
->width
- 1, s
->img
->height
- 1);
3610 /* Draw a rectangle if image could not be loaded. */
3611 XDrawRectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
3612 s
->img
->width
- 1, s
->img
->height
- 1);
3616 /* Draw a relief around the image glyph string S. */
3619 x_draw_image_relief (s
)
3620 struct glyph_string
*s
;
3622 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3625 int y
= s
->ybase
- IMAGE_ASCENT (s
->img
);
3627 /* If first glyph of S has a left box line, start drawing it to the
3628 right of that line. */
3629 if (s
->face
->box
!= FACE_NO_BOX
3630 && s
->first_glyph
->left_box_line_p
)
3631 x
= s
->x
+ s
->face
->box_line_width
;
3635 /* If there is a margin around the image, adjust x- and y-position
3639 x
+= s
->img
->margin
;
3640 y
+= s
->img
->margin
;
3643 if (s
->hl
== DRAW_IMAGE_SUNKEN
3644 || s
->hl
== DRAW_IMAGE_RAISED
)
3646 thick
= tool_bar_button_relief
> 0 ? tool_bar_button_relief
: 3;
3647 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3651 thick
= abs (s
->img
->relief
);
3652 raised_p
= s
->img
->relief
> 0;
3657 x1
= x
+ s
->img
->width
+ thick
- 1;
3658 y1
= y
+ s
->img
->height
+ thick
- 1;
3660 x_setup_relief_colors (s
);
3661 x_get_glyph_string_clip_rect (s
, &r
);
3662 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
, 1, 1, &r
);
3666 /* Draw the foreground of image glyph string S to PIXMAP. */
3669 x_draw_image_foreground_1 (s
, pixmap
)
3670 struct glyph_string
*s
;
3674 int y
= s
->ybase
- s
->y
- IMAGE_ASCENT (s
->img
);
3676 /* If first glyph of S has a left box line, start drawing it to the
3677 right of that line. */
3678 if (s
->face
->box
!= FACE_NO_BOX
3679 && s
->first_glyph
->left_box_line_p
)
3680 x
= s
->face
->box_line_width
;
3684 /* If there is a margin around the image, adjust x- and y-position
3688 x
+= s
->img
->margin
;
3689 y
+= s
->img
->margin
;
3696 /* We can't set both a clip mask and use XSetClipRectangles
3697 because the latter also sets a clip mask. We also can't
3698 trust on the shape extension to be available
3699 (XShapeCombineRegion). So, compute the rectangle to draw
3701 unsigned long mask
= (GCClipMask
| GCClipXOrigin
| GCClipYOrigin
3705 xgcv
.clip_mask
= s
->img
->mask
;
3706 xgcv
.clip_x_origin
= x
;
3707 xgcv
.clip_y_origin
= y
;
3708 xgcv
.function
= GXcopy
;
3709 XChangeGC (s
->display
, s
->gc
, mask
, &xgcv
);
3711 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3712 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3713 XSetClipMask (s
->display
, s
->gc
, None
);
3717 XCopyArea (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3718 0, 0, s
->img
->width
, s
->img
->height
, x
, y
);
3720 /* When the image has a mask, we can expect that at
3721 least part of a mouse highlight or a block cursor will
3722 be visible. If the image doesn't have a mask, make
3723 a block cursor visible by drawing a rectangle around
3724 the image. I believe it's looking better if we do
3725 nothing here for mouse-face. */
3726 if (s
->hl
== DRAW_CURSOR
)
3727 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3728 s
->img
->width
- 1, s
->img
->height
- 1);
3732 /* Draw a rectangle if image could not be loaded. */
3733 XDrawRectangle (s
->display
, pixmap
, s
->gc
, x
, y
,
3734 s
->img
->width
- 1, s
->img
->height
- 1);
3738 /* Draw part of the background of glyph string S. X, Y, W, and H
3739 give the rectangle to draw. */
3742 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3743 struct glyph_string
*s
;
3748 /* Fill background with a stipple pattern. */
3749 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3750 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3751 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3754 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3758 /* Draw image glyph string S.
3761 s->x +-------------------------
3764 | +-------------------------
3767 | | +-------------------
3773 x_draw_image_glyph_string (s
)
3774 struct glyph_string
*s
;
3777 int box_line_width
= s
->face
->box_line_width
;
3778 int margin
= s
->img
->margin
;
3780 Pixmap pixmap
= None
;
3782 height
= s
->height
- 2 * box_line_width
;
3784 /* Fill background with face under the image. Do it only if row is
3785 taller than image or if image has a clip mask to reduce
3787 s
->stippled_p
= s
->face
->stipple
!= 0;
3788 if (height
> s
->img
->height
3791 || s
->img
->pixmap
== 0
3792 || s
->width
!= s
->background_width
)
3794 if (box_line_width
&& s
->first_glyph
->left_box_line_p
)
3795 x
= s
->x
+ box_line_width
;
3799 y
= s
->y
+ box_line_width
;
3803 /* Create a pixmap as large as the glyph string Fill it with
3804 the background color. Copy the image to it, using its
3805 mask. Copy the temporary pixmap to the display. */
3806 Screen
*screen
= FRAME_X_SCREEN (s
->f
);
3807 int depth
= DefaultDepthOfScreen (screen
);
3809 /* Create a pixmap as large as the glyph string. */
3810 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3811 s
->background_width
,
3814 /* Don't clip in the following because we're working on the
3816 XSetClipMask (s
->display
, s
->gc
, None
);
3818 /* Fill the pixmap with the background color/stipple. */
3821 /* Fill background with a stipple pattern. */
3822 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3823 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3824 0, 0, s
->background_width
, s
->height
);
3825 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3830 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3832 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3833 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3834 0, 0, s
->background_width
, s
->height
);
3835 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3839 /* Implementation idea: Is it possible to construct a mask?
3840 We could look at the color at the margins of the image, and
3841 say that this color is probably the background color of the
3843 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3845 s
->background_filled_p
= 1;
3848 /* Draw the foreground. */
3851 x_draw_image_foreground_1 (s
, pixmap
);
3852 x_set_glyph_string_clipping (s
);
3853 XCopyArea (s
->display
, pixmap
, s
->window
, s
->gc
,
3854 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3855 XFreePixmap (s
->display
, pixmap
);
3858 x_draw_image_foreground (s
);
3860 /* If we must draw a relief around the image, do it. */
3862 || s
->hl
== DRAW_IMAGE_RAISED
3863 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3864 x_draw_image_relief (s
);
3868 /* Draw stretch glyph string S. */
3871 x_draw_stretch_glyph_string (s
)
3872 struct glyph_string
*s
;
3874 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3875 s
->stippled_p
= s
->face
->stipple
!= 0;
3877 if (s
->hl
== DRAW_CURSOR
3878 && !x_stretch_cursor_p
)
3880 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3881 as wide as the stretch glyph. */
3882 int width
= min (CANON_X_UNIT (s
->f
), s
->background_width
);
3885 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3887 /* Clear rest using the GC of the original non-cursor face. */
3888 if (width
< s
->background_width
)
3890 GC gc
= s
->face
->gc
;
3891 int x
= s
->x
+ width
, y
= s
->y
;
3892 int w
= s
->background_width
- width
, h
= s
->height
;
3895 x_get_glyph_string_clip_rect (s
, &r
);
3896 XSetClipRectangles (s
->display
, gc
, 0, 0, &r
, 1, Unsorted
);
3898 if (s
->face
->stipple
)
3900 /* Fill background with a stipple pattern. */
3901 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3902 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3903 XSetFillStyle (s
->display
, gc
, FillSolid
);
3908 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
3909 XSetForeground (s
->display
, gc
, xgcv
.background
);
3910 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3911 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
3916 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3919 s
->background_filled_p
= 1;
3923 /* Draw glyph string S. */
3926 x_draw_glyph_string (s
)
3927 struct glyph_string
*s
;
3929 /* If S draws into the background of its successor, draw the
3930 background of the successor first so that S can draw into it.
3931 This makes S->next use XDrawString instead of XDrawImageString. */
3932 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3934 xassert (s
->next
->img
== NULL
);
3935 x_set_glyph_string_gc (s
->next
);
3936 x_set_glyph_string_clipping (s
->next
);
3937 x_draw_glyph_string_background (s
->next
, 1);
3940 /* Set up S->gc, set clipping and draw S. */
3941 x_set_glyph_string_gc (s
);
3942 x_set_glyph_string_clipping (s
);
3944 switch (s
->first_glyph
->type
)
3947 x_draw_image_glyph_string (s
);
3951 x_draw_stretch_glyph_string (s
);
3955 if (s
->for_overlaps_p
)
3956 s
->background_filled_p
= 1;
3958 x_draw_glyph_string_background (s
, 0);
3959 x_draw_glyph_string_foreground (s
);
3962 case COMPOSITE_GLYPH
:
3963 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3964 s
->background_filled_p
= 1;
3966 x_draw_glyph_string_background (s
, 1);
3967 x_draw_composite_glyph_string_foreground (s
);
3974 if (!s
->for_overlaps_p
)
3976 /* Draw underline. */
3977 if (s
->face
->underline_p
)
3979 unsigned long dy
, h
;
3981 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_THICKNESS
, &h
))
3983 if (!XGetFontProperty (s
->font
, XA_UNDERLINE_POSITION
, &dy
))
3986 if (s
->face
->underline_defaulted_p
)
3987 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3992 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3993 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3994 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3996 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4000 /* Draw overline. */
4001 if (s
->face
->overline_p
)
4003 unsigned long dy
= 0, h
= 1;
4005 if (s
->face
->overline_color_defaulted_p
)
4006 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4011 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4012 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
4013 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4015 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4019 /* Draw strike-through. */
4020 if (s
->face
->strike_through_p
)
4022 unsigned long h
= 1;
4023 unsigned long dy
= (s
->height
- h
) / 2;
4025 if (s
->face
->strike_through_color_defaulted_p
)
4026 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4031 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
4032 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
4033 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
4035 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
4040 if (s
->face
->box
!= FACE_NO_BOX
)
4041 x_draw_glyph_string_box (s
);
4044 /* Reset clipping. */
4045 XSetClipMask (s
->display
, s
->gc
, None
);
4049 static int x_fill_composite_glyph_string
P_ ((struct glyph_string
*,
4050 struct face
**, int));
4053 /* Load glyph string S with a composition components specified by S->cmp.
4054 FACES is an array of faces for all components of this composition.
4055 S->gidx is the index of the first component for S.
4056 OVERLAPS_P non-zero means S should draw the foreground only, and
4057 use its lines physical height for clipping.
4059 Value is the index of a component not in S. */
4062 x_fill_composite_glyph_string (s
, faces
, overlaps_p
)
4063 struct glyph_string
*s
;
4064 struct face
**faces
;
4071 s
->for_overlaps_p
= overlaps_p
;
4073 s
->face
= faces
[s
->gidx
];
4074 s
->font
= s
->face
->font
;
4075 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4077 /* For all glyphs of this composition, starting at the offset
4078 S->gidx, until we reach the end of the definition or encounter a
4079 glyph that requires the different face, add it to S. */
4081 for (i
= s
->gidx
+ 1; i
< s
->cmp
->glyph_len
&& faces
[i
] == s
->face
; ++i
)
4084 /* All glyph strings for the same composition has the same width,
4085 i.e. the width set for the first component of the composition. */
4087 s
->width
= s
->first_glyph
->pixel_width
;
4089 /* If the specified font could not be loaded, use the frame's
4090 default font, but record the fact that we couldn't load it in
4091 the glyph string so that we can draw rectangles for the
4092 characters of the glyph string. */
4093 if (s
->font
== NULL
)
4095 s
->font_not_found_p
= 1;
4096 s
->font
= FRAME_FONT (s
->f
);
4099 /* Adjust base line for subscript/superscript text. */
4100 s
->ybase
+= s
->first_glyph
->voffset
;
4102 xassert (s
->face
&& s
->face
->gc
);
4104 /* This glyph string must always be drawn with 16-bit functions. */
4107 return s
->gidx
+ s
->nchars
;
4111 /* Load glyph string S with a sequence characters.
4112 FACE_ID is the face id of the string. START is the index of the
4113 first glyph to consider, END is the index of the last + 1.
4114 OVERLAPS_P non-zero means S should draw the foreground only, and
4115 use its lines physical height for clipping.
4117 Value is the index of the first glyph not in S. */
4120 x_fill_glyph_string (s
, face_id
, start
, end
, overlaps_p
)
4121 struct glyph_string
*s
;
4123 int start
, end
, overlaps_p
;
4125 struct glyph
*glyph
, *last
;
4128 xassert (s
->f
== XFRAME (s
->w
->frame
));
4129 xassert (s
->nchars
== 0);
4130 xassert (start
>= 0 && end
> start
);
4132 s
->for_overlaps_p
= overlaps_p
,
4133 glyph
= s
->row
->glyphs
[s
->area
] + start
;
4134 last
= s
->row
->glyphs
[s
->area
] + end
;
4135 voffset
= glyph
->voffset
;
4138 && glyph
->type
== CHAR_GLYPH
4139 && glyph
->voffset
== voffset
4140 /* Same face id implies same charset, nowadays. */
4141 && glyph
->u
.ch
.face_id
== face_id
)
4143 s
->face
= x_get_glyph_face_and_encoding (s
->f
, glyph
,
4144 s
->char2b
+ s
->nchars
);
4145 if (s
->char2b
[s
->nchars
].byte2
!= 0)
4149 xassert (s
->nchars
<= end
- start
);
4150 s
->width
+= glyph
->pixel_width
;
4154 s
->font
= s
->face
->font
;
4155 s
->font_info
= FONT_INFO_FROM_ID (s
->f
, s
->face
->font_info_id
);
4157 /* If the specified font could not be loaded, use the frame's font,
4158 but record the fact that we couldn't load it in
4159 S->font_not_found_p so that we can draw rectangles for the
4160 characters of the glyph string. */
4161 if (s
->font
== NULL
)
4163 s
->font_not_found_p
= 1;
4164 s
->font
= FRAME_FONT (s
->f
);
4167 /* Adjust base line for subscript/superscript text. */
4168 s
->ybase
+= voffset
;
4170 xassert (s
->face
&& s
->face
->gc
);
4171 return glyph
- s
->row
->glyphs
[s
->area
];
4175 /* Fill glyph string S from image glyph S->first_glyph. */
4178 x_fill_image_glyph_string (s
)
4179 struct glyph_string
*s
;
4181 xassert (s
->first_glyph
->type
== IMAGE_GLYPH
);
4182 s
->img
= IMAGE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.id
);
4184 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.img
.face_id
);
4185 s
->font
= s
->face
->font
;
4186 s
->width
= s
->first_glyph
->pixel_width
;
4188 /* Adjust base line for subscript/superscript text. */
4189 s
->ybase
+= s
->first_glyph
->voffset
;
4193 /* Fill glyph string S from stretch glyph S->first_glyph. */
4196 x_fill_stretch_glyph_string (s
)
4197 struct glyph_string
*s
;
4199 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
4200 s
->face
= FACE_FROM_ID (s
->f
, s
->first_glyph
->u
.stretch
.face_id
);
4201 s
->font
= s
->face
->font
;
4202 s
->width
= s
->first_glyph
->pixel_width
;
4204 /* Adjust base line for subscript/superscript text. */
4205 s
->ybase
+= s
->first_glyph
->voffset
;
4209 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4210 of XChar2b structures for S; it can't be allocated in
4211 x_init_glyph_string because it must be allocated via `alloca'. W
4212 is the window on which S is drawn. ROW and AREA are the glyph row
4213 and area within the row from which S is constructed. START is the
4214 index of the first glyph structure covered by S. HL is a
4215 face-override for drawing S. */
4218 x_init_glyph_string (s
, char2b
, w
, row
, area
, start
, hl
)
4219 struct glyph_string
*s
;
4222 struct glyph_row
*row
;
4223 enum glyph_row_area area
;
4225 enum draw_glyphs_face hl
;
4227 bzero (s
, sizeof *s
);
4229 s
->f
= XFRAME (w
->frame
);
4230 s
->display
= FRAME_X_DISPLAY (s
->f
);
4231 s
->window
= FRAME_X_WINDOW (s
->f
);
4236 s
->first_glyph
= row
->glyphs
[area
] + start
;
4237 s
->height
= row
->height
;
4238 s
->y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4240 /* Display the internal border below the tool-bar window. */
4241 if (s
->w
== XWINDOW (s
->f
->tool_bar_window
))
4242 s
->y
-= s
->f
->output_data
.x
->internal_border_width
;
4244 s
->ybase
= s
->y
+ row
->ascent
;
4248 /* Set background width of glyph string S. START is the index of the
4249 first glyph following S. LAST_X is the right-most x-position + 1
4250 in the drawing area. */
4253 x_set_glyph_string_background_width (s
, start
, last_x
)
4254 struct glyph_string
*s
;
4258 /* If the face of this glyph string has to be drawn to the end of
4259 the drawing area, set S->extends_to_end_of_line_p. */
4260 struct face
*default_face
= FACE_FROM_ID (s
->f
, DEFAULT_FACE_ID
);
4262 if (start
== s
->row
->used
[s
->area
]
4263 && s
->hl
== DRAW_NORMAL_TEXT
4264 && ((s
->area
== TEXT_AREA
&& s
->row
->fill_line_p
)
4265 || s
->face
->background
!= default_face
->background
4266 || s
->face
->stipple
!= default_face
->stipple
))
4267 s
->extends_to_end_of_line_p
= 1;
4269 /* If S extends its face to the end of the line, set its
4270 background_width to the distance to the right edge of the drawing
4272 if (s
->extends_to_end_of_line_p
)
4273 s
->background_width
= last_x
- s
->x
+ 1;
4275 s
->background_width
= s
->width
;
4279 /* Add a glyph string for a stretch glyph to the list of strings
4280 between HEAD and TAIL. START is the index of the stretch glyph in
4281 row area AREA of glyph row ROW. END is the index of the last glyph
4282 in that glyph row area. X is the current output position assigned
4283 to the new glyph string constructed. HL overrides that face of the
4284 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4285 is the right-most x-position of the drawing area. */
4287 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4288 and below -- keep them on one line. */
4289 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4292 s = (struct glyph_string *) alloca (sizeof *s); \
4293 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4294 x_fill_stretch_glyph_string (s); \
4295 x_append_glyph_string (&HEAD, &TAIL, s); \
4302 /* Add a glyph string for an image glyph to the list of strings
4303 between HEAD and TAIL. START is the index of the image glyph in
4304 row area AREA of glyph row ROW. END is the index of the last glyph
4305 in that glyph row area. X is the current output position assigned
4306 to the new glyph string constructed. HL overrides that face of the
4307 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4308 is the right-most x-position of the drawing area. */
4310 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4313 s = (struct glyph_string *) alloca (sizeof *s); \
4314 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4315 x_fill_image_glyph_string (s); \
4316 x_append_glyph_string (&HEAD, &TAIL, s); \
4323 /* Add a glyph string for a sequence of character glyphs to the list
4324 of strings between HEAD and TAIL. START is the index of the first
4325 glyph in row area AREA of glyph row ROW that is part of the new
4326 glyph string. END is the index of the last glyph in that glyph row
4327 area. X is the current output position assigned to the new glyph
4328 string constructed. HL overrides that face of the glyph; e.g. it
4329 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4330 right-most x-position of the drawing area. */
4332 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4335 int c, charset, face_id; \
4338 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4339 charset = CHAR_CHARSET (c); \
4340 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4342 s = (struct glyph_string *) alloca (sizeof *s); \
4343 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4344 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4345 x_append_glyph_string (&HEAD, &TAIL, s); \
4346 s->charset = charset; \
4348 START = x_fill_glyph_string (s, face_id, START, END, \
4354 /* Add a glyph string for a composite sequence to the list of strings
4355 between HEAD and TAIL. START is the index of the first glyph in
4356 row area AREA of glyph row ROW that is part of the new glyph
4357 string. END is the index of the last glyph in that glyph row area.
4358 X is the current output position assigned to the new glyph string
4359 constructed. HL overrides that face of the glyph; e.g. it is
4360 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4361 x-position of the drawing area. */
4363 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4365 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp.id; \
4366 int face_id = (ROW)->glyphs[AREA][START].u.cmp.face_id; \
4367 struct composition *cmp = composition_table[cmp_id]; \
4368 int glyph_len = cmp->glyph_len; \
4370 struct face **faces; \
4371 struct glyph_string *first_s = NULL; \
4374 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4375 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4376 /* At first, fill in `char2b' and `faces'. */ \
4377 for (n = 0; n < glyph_len; n++) \
4379 int c = FAST_GLYPH_CHAR (COMPOSITION_GLYPH (cmp, n)); \
4380 faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4381 face_id, char2b + n, 1); \
4384 /* Make glyph_strings for each glyph sequence that is drawable by \
4385 the same face, and append them to HEAD/TAIL. */ \
4386 for (n = 0; n < cmp->glyph_len;) \
4388 s = (struct glyph_string *) alloca (sizeof *s); \
4389 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4390 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4399 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4407 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4408 of AREA of glyph row ROW on window W between indices START and END.
4409 HL overrides the face for drawing glyph strings, e.g. it is
4410 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4411 x-positions of the drawing area.
4413 This is an ugly monster macro construct because we must use alloca
4414 to allocate glyph strings (because x_draw_glyphs can be called
4417 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4420 HEAD = TAIL = NULL; \
4421 while (START < END) \
4423 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4424 switch (first_glyph->type) \
4427 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4428 TAIL, HL, X, LAST_X, \
4432 case COMPOSITE_GLYPH: \
4433 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4434 HEAD, TAIL, HL, X, LAST_X,\
4438 case STRETCH_GLYPH: \
4439 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4440 HEAD, TAIL, HL, X, LAST_X); \
4444 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4445 TAIL, HL, X, LAST_X); \
4452 x_set_glyph_string_background_width (s, START, LAST_X); \
4459 /* Draw glyphs between START and END in AREA of ROW on window W,
4460 starting at x-position X. X is relative to AREA in W. HL is a
4461 face-override with the following meaning:
4463 DRAW_NORMAL_TEXT draw normally
4464 DRAW_CURSOR draw in cursor face
4465 DRAW_MOUSE_FACE draw in mouse face.
4466 DRAW_INVERSE_VIDEO draw in mode line face
4467 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4468 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4470 If REAL_START is non-null, return in *REAL_START the real starting
4471 position for display. This can be different from START in case
4472 overlapping glyphs must be displayed. If REAL_END is non-null,
4473 return in *REAL_END the real end position for display. This can be
4474 different from END in case overlapping glyphs must be displayed.
4476 If OVERLAPS_P is non-zero, draw only the foreground of characters
4477 and clip to the physical height of ROW.
4479 Value is the x-position reached, relative to AREA of W. */
4482 x_draw_glyphs (w
, x
, row
, area
, start
, end
, hl
, real_start
, real_end
,
4486 struct glyph_row
*row
;
4487 enum glyph_row_area area
;
4489 enum draw_glyphs_face hl
;
4490 int *real_start
, *real_end
;
4493 struct glyph_string
*head
, *tail
;
4494 struct glyph_string
*s
;
4495 int last_x
, area_width
;
4499 /* Let's rather be paranoid than getting a SEGV. */
4500 start
= max (0, start
);
4501 end
= min (end
, row
->used
[area
]);
4503 *real_start
= start
;
4507 /* Translate X to frame coordinates. Set last_x to the right
4508 end of the drawing area. */
4509 if (row
->full_width_p
)
4511 /* X is relative to the left edge of W, without scroll bars
4513 struct frame
*f
= XFRAME (w
->frame
);
4514 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4515 int window_left_x
= WINDOW_LEFT_MARGIN (w
) * CANON_X_UNIT (f
);
4518 area_width
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4519 last_x
= window_left_x
+ area_width
;
4521 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4523 int width
= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4524 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4530 x
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
4531 last_x
-= FRAME_INTERNAL_BORDER_WIDTH (f
);
4535 x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, x
);
4536 area_width
= window_box_width (w
, area
);
4537 last_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, area
, area_width
);
4540 /* Build a doubly-linked list of glyph_string structures between
4541 head and tail from what we have to draw. Note that the macro
4542 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4543 the reason we use a separate variable `i'. */
4545 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, end
, head
, tail
, hl
, x
, last_x
,
4548 x_reached
= tail
->x
+ tail
->background_width
;
4552 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4553 the row, redraw some glyphs in front or following the glyph
4554 strings built above. */
4555 if (!overlaps_p
&& row
->contains_overlapping_glyphs_p
)
4558 struct glyph_string
*h
, *t
;
4560 /* Compute overhangs for all glyph strings. */
4561 for (s
= head
; s
; s
= s
->next
)
4562 x_compute_glyph_string_overhangs (s
);
4564 /* Prepend glyph strings for glyphs in front of the first glyph
4565 string that are overwritten because of the first glyph
4566 string's left overhang. The background of all strings
4567 prepended must be drawn because the first glyph string
4569 i
= x_left_overwritten (head
);
4573 BUILD_GLYPH_STRINGS (w
, row
, area
, j
, start
, h
, t
,
4574 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4578 *real_start
= start
;
4579 x_compute_overhangs_and_x (t
, head
->x
, 1);
4580 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4583 /* Prepend glyph strings for glyphs in front of the first glyph
4584 string that overwrite that glyph string because of their
4585 right overhang. For these strings, only the foreground must
4586 be drawn, because it draws over the glyph string at `head'.
4587 The background must not be drawn because this would overwrite
4588 right overhangs of preceding glyphs for which no glyph
4590 i
= x_left_overwriting (head
);
4593 BUILD_GLYPH_STRINGS (w
, row
, area
, i
, start
, h
, t
,
4594 DRAW_NORMAL_TEXT
, dummy_x
, last_x
,
4596 for (s
= h
; s
; s
= s
->next
)
4597 s
->background_filled_p
= 1;
4600 x_compute_overhangs_and_x (t
, head
->x
, 1);
4601 x_prepend_glyph_string_lists (&head
, &tail
, h
, t
);
4604 /* Append glyphs strings for glyphs following the last glyph
4605 string tail that are overwritten by tail. The background of
4606 these strings has to be drawn because tail's foreground draws
4608 i
= x_right_overwritten (tail
);
4611 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4612 DRAW_NORMAL_TEXT
, x
, last_x
,
4614 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4615 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4620 /* Append glyph strings for glyphs following the last glyph
4621 string tail that overwrite tail. The foreground of such
4622 glyphs has to be drawn because it writes into the background
4623 of tail. The background must not be drawn because it could
4624 paint over the foreground of following glyphs. */
4625 i
= x_right_overwriting (tail
);
4628 BUILD_GLYPH_STRINGS (w
, row
, area
, end
, i
, h
, t
,
4629 DRAW_NORMAL_TEXT
, x
, last_x
,
4631 for (s
= h
; s
; s
= s
->next
)
4632 s
->background_filled_p
= 1;
4633 x_compute_overhangs_and_x (h
, tail
->x
+ tail
->width
, 0);
4634 x_append_glyph_string_lists (&head
, &tail
, h
, t
);
4640 /* Draw all strings. */
4641 for (s
= head
; s
; s
= s
->next
)
4642 x_draw_glyph_string (s
);
4644 /* Value is the x-position up to which drawn, relative to AREA of W.
4645 This doesn't include parts drawn because of overhangs. */
4646 x_reached
= FRAME_TO_WINDOW_PIXEL_X (w
, x_reached
);
4647 if (!row
->full_width_p
)
4649 if (area
> LEFT_MARGIN_AREA
)
4650 x_reached
-= window_box_width (w
, LEFT_MARGIN_AREA
);
4651 if (area
> TEXT_AREA
)
4652 x_reached
-= window_box_width (w
, TEXT_AREA
);
4658 /* Fix the display of area AREA of overlapping row ROW in window W. */
4661 x_fix_overlapping_area (w
, row
, area
)
4663 struct glyph_row
*row
;
4664 enum glyph_row_area area
;
4670 if (area
== LEFT_MARGIN_AREA
)
4672 else if (area
== TEXT_AREA
)
4673 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
4675 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
4676 + window_box_width (w
, TEXT_AREA
));
4678 for (i
= 0; i
< row
->used
[area
];)
4680 if (row
->glyphs
[area
][i
].overlaps_vertically_p
)
4682 int start
= i
, start_x
= x
;
4686 x
+= row
->glyphs
[area
][i
].pixel_width
;
4689 while (i
< row
->used
[area
]
4690 && row
->glyphs
[area
][i
].overlaps_vertically_p
);
4692 x_draw_glyphs (w
, start_x
, row
, area
, start
, i
,
4694 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4699 x
+= row
->glyphs
[area
][i
].pixel_width
;
4708 /* Output LEN glyphs starting at START at the nominal cursor position.
4709 Advance the nominal cursor over the text. The global variable
4710 updated_window contains the window being updated, updated_row is
4711 the glyph row being updated, and updated_area is the area of that
4712 row being updated. */
4715 x_write_glyphs (start
, len
)
4716 struct glyph
*start
;
4719 int x
, hpos
, real_start
, real_end
;
4721 xassert (updated_window
&& updated_row
);
4726 hpos
= start
- updated_row
->glyphs
[updated_area
];
4727 x
= x_draw_glyphs (updated_window
, output_cursor
.x
,
4728 updated_row
, updated_area
,
4730 (updated_row
->inverse_p
4731 ? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
),
4732 &real_start
, &real_end
, 0);
4734 /* If we drew over the cursor, note that it is not visible any more. */
4735 note_overwritten_text_cursor (updated_window
, real_start
,
4736 real_end
- real_start
);
4740 /* Advance the output cursor. */
4741 output_cursor
.hpos
+= len
;
4742 output_cursor
.x
= x
;
4746 /* Insert LEN glyphs from START at the nominal cursor position. */
4749 x_insert_glyphs (start
, len
)
4750 struct glyph
*start
;
4755 int line_height
, shift_by_width
, shifted_region_width
;
4756 struct glyph_row
*row
;
4757 struct glyph
*glyph
;
4758 int frame_x
, frame_y
, hpos
, real_start
, real_end
;
4760 xassert (updated_window
&& updated_row
);
4763 f
= XFRAME (WINDOW_FRAME (w
));
4765 /* Get the height of the line we are in. */
4767 line_height
= row
->height
;
4769 /* Get the width of the glyphs to insert. */
4771 for (glyph
= start
; glyph
< start
+ len
; ++glyph
)
4772 shift_by_width
+= glyph
->pixel_width
;
4774 /* Get the width of the region to shift right. */
4775 shifted_region_width
= (window_box_width (w
, updated_area
)
4780 frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, output_cursor
.x
);
4781 frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, output_cursor
.y
);
4782 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
4783 f
->output_data
.x
->normal_gc
,
4785 shifted_region_width
, line_height
,
4786 frame_x
+ shift_by_width
, frame_y
);
4788 /* Write the glyphs. */
4789 hpos
= start
- row
->glyphs
[updated_area
];
4790 x_draw_glyphs (w
, output_cursor
.x
, row
, updated_area
, hpos
, hpos
+ len
,
4791 DRAW_NORMAL_TEXT
, &real_start
, &real_end
, 0);
4792 note_overwritten_text_cursor (w
, real_start
, real_end
- real_start
);
4794 /* Advance the output cursor. */
4795 output_cursor
.hpos
+= len
;
4796 output_cursor
.x
+= shift_by_width
;
4801 /* Delete N glyphs at the nominal cursor position. Not implemented
4812 /* Erase the current text line from the nominal cursor position
4813 (inclusive) to pixel column TO_X (exclusive). The idea is that
4814 everything from TO_X onward is already erased.
4816 TO_X is a pixel position relative to updated_area of
4817 updated_window. TO_X == -1 means clear to the end of this area. */
4820 x_clear_end_of_line (to_x
)
4824 struct window
*w
= updated_window
;
4825 int max_x
, min_y
, max_y
;
4826 int from_x
, from_y
, to_y
;
4828 xassert (updated_window
&& updated_row
);
4829 f
= XFRAME (w
->frame
);
4831 if (updated_row
->full_width_p
)
4833 max_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
);
4834 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
4835 && !w
->pseudo_window_p
)
4836 max_x
+= FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
);
4839 max_x
= window_box_width (w
, updated_area
);
4840 max_y
= window_text_bottom_y (w
);
4842 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4843 of window. For TO_X > 0, truncate to end of drawing area. */
4849 to_x
= min (to_x
, max_x
);
4851 to_y
= min (max_y
, output_cursor
.y
+ updated_row
->height
);
4853 /* Notice if the cursor will be cleared by this operation. */
4854 if (!updated_row
->full_width_p
)
4855 note_overwritten_text_cursor (w
, output_cursor
.hpos
, -1);
4857 from_x
= output_cursor
.x
;
4859 /* Translate to frame coordinates. */
4860 if (updated_row
->full_width_p
)
4862 from_x
= WINDOW_TO_FRAME_PIXEL_X (w
, from_x
);
4863 to_x
= WINDOW_TO_FRAME_PIXEL_X (w
, to_x
);
4867 from_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, from_x
);
4868 to_x
= WINDOW_AREA_TO_FRAME_PIXEL_X (w
, updated_area
, to_x
);
4871 min_y
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
4872 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (min_y
, output_cursor
.y
));
4873 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, to_y
);
4875 /* Prevent inadvertently clearing to end of the X window. */
4876 if (to_x
> from_x
&& to_y
> from_y
)
4879 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4880 from_x
, from_y
, to_x
- from_x
, to_y
- from_y
,
4887 /* Clear entire frame. If updating_frame is non-null, clear that
4888 frame. Otherwise clear the selected frame. */
4898 f
= SELECTED_FRAME ();
4900 /* Clearing the frame will erase any cursor, so mark them all as no
4902 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4903 output_cursor
.hpos
= output_cursor
.vpos
= 0;
4904 output_cursor
.x
= -1;
4906 /* We don't set the output cursor here because there will always
4907 follow an explicit cursor_to. */
4909 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
4911 /* We have to clear the scroll bars, too. If we have changed
4912 colors or something like that, then they should be notified. */
4913 x_scroll_bar_clear (f
);
4915 XFlush (FRAME_X_DISPLAY (f
));
4921 /* Invert the middle quarter of the frame for .15 sec. */
4923 /* We use the select system call to do the waiting, so we have to make
4924 sure it's available. If it isn't, we just won't do visual bells. */
4926 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4929 /* Subtract the `struct timeval' values X and Y, storing the result in
4930 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4933 timeval_subtract (result
, x
, y
)
4934 struct timeval
*result
, x
, y
;
4936 /* Perform the carry for the later subtraction by updating y. This
4937 is safer because on some systems the tv_sec member is unsigned. */
4938 if (x
.tv_usec
< y
.tv_usec
)
4940 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
4941 y
.tv_usec
-= 1000000 * nsec
;
4945 if (x
.tv_usec
- y
.tv_usec
> 1000000)
4947 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
4948 y
.tv_usec
+= 1000000 * nsec
;
4952 /* Compute the time remaining to wait. tv_usec is certainly
4954 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
4955 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
4957 /* Return indication of whether the result should be considered
4959 return x
.tv_sec
< y
.tv_sec
;
4971 /* Create a GC that will use the GXxor function to flip foreground
4972 pixels into background pixels. */
4976 values
.function
= GXxor
;
4977 values
.foreground
= (f
->output_data
.x
->foreground_pixel
4978 ^ f
->output_data
.x
->background_pixel
);
4980 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4981 GCFunction
| GCForeground
, &values
);
4985 /* Get the height not including a menu bar widget. */
4986 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
4987 /* Height of each line to flash. */
4988 int flash_height
= FRAME_LINE_HEIGHT (f
);
4989 /* These will be the left and right margins of the rectangles. */
4990 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
4991 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
4995 /* Don't flash the area between a scroll bar and the frame
4996 edge it is next to. */
4997 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
4999 case vertical_scroll_bar_left
:
5000 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5003 case vertical_scroll_bar_right
:
5004 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
5011 width
= flash_right
- flash_left
;
5013 /* If window is tall, flash top and bottom line. */
5014 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5016 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5018 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5019 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5020 width
, flash_height
);
5021 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5023 (height
- flash_height
5024 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5025 width
, flash_height
);
5028 /* If it is short, flash it all. */
5029 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5030 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5031 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5036 struct timeval wakeup
;
5038 EMACS_GET_TIME (wakeup
);
5040 /* Compute time to wait until, propagating carry from usecs. */
5041 wakeup
.tv_usec
+= 150000;
5042 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
5043 wakeup
.tv_usec
%= 1000000;
5045 /* Keep waiting until past the time wakeup. */
5048 struct timeval timeout
;
5050 EMACS_GET_TIME (timeout
);
5052 /* In effect, timeout = wakeup - timeout.
5053 Break if result would be negative. */
5054 if (timeval_subtract (&timeout
, wakeup
, timeout
))
5057 /* Try to wait that long--but we might wake up sooner. */
5058 select (0, NULL
, NULL
, NULL
, &timeout
);
5062 /* If window is tall, flash top and bottom line. */
5063 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
5065 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5067 (FRAME_INTERNAL_BORDER_WIDTH (f
)
5068 + FRAME_TOOL_BAR_LINES (f
) * CANON_Y_UNIT (f
)),
5069 width
, flash_height
);
5070 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5072 (height
- flash_height
5073 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
5074 width
, flash_height
);
5077 /* If it is short, flash it all. */
5078 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
5079 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
5080 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
5082 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
5090 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5093 /* Make audible bell. */
5098 struct frame
*f
= SELECTED_FRAME ();
5100 if (FRAME_X_DISPLAY (f
))
5102 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5109 XBell (FRAME_X_DISPLAY (f
), 0);
5110 XFlush (FRAME_X_DISPLAY (f
));
5117 /* Specify how many text lines, from the top of the window,
5118 should be affected by insert-lines and delete-lines operations.
5119 This, and those operations, are used only within an update
5120 that is bounded by calls to x_update_begin and x_update_end. */
5123 XTset_terminal_window (n
)
5126 /* This function intentionally left blank. */
5131 /***********************************************************************
5133 ***********************************************************************/
5135 /* Perform an insert-lines or delete-lines operation, inserting N
5136 lines or deleting -N lines at vertical position VPOS. */
5139 x_ins_del_lines (vpos
, n
)
5146 /* Scroll part of the display as described by RUN. */
5149 x_scroll_run (w
, run
)
5153 struct frame
*f
= XFRAME (w
->frame
);
5154 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
5156 /* Get frame-relative bounding box of the text display area of W,
5157 without mode lines. Include in this box the flags areas to the
5158 left and right of W. */
5159 window_box (w
, -1, &x
, &y
, &width
, &height
);
5160 width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
5161 x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
5163 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
5164 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
5165 bottom_y
= y
+ height
;
5169 /* Scrolling up. Make sure we don't copy part of the mode
5170 line at the bottom. */
5171 if (from_y
+ run
->height
> bottom_y
)
5172 height
= bottom_y
- from_y
;
5174 height
= run
->height
;
5178 /* Scolling down. Make sure we don't copy over the mode line.
5180 if (to_y
+ run
->height
> bottom_y
)
5181 height
= bottom_y
- to_y
;
5183 height
= run
->height
;
5188 /* Cursor off. Will be switched on again in x_update_window_end. */
5192 XCopyArea (FRAME_X_DISPLAY (f
),
5193 FRAME_X_WINDOW (f
), FRAME_X_WINDOW (f
),
5194 f
->output_data
.x
->normal_gc
,
5204 /***********************************************************************
5206 ***********************************************************************/
5208 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5209 corner of the exposed rectangle. W and H are width and height of
5210 the exposed area. All are pixel values. W or H zero means redraw
5211 the entire frame. */
5214 expose_frame (f
, x
, y
, w
, h
)
5220 TRACE ((stderr
, "expose_frame "));
5222 /* No need to redraw if frame will be redrawn soon. */
5223 if (FRAME_GARBAGED_P (f
))
5225 TRACE ((stderr
, " garbaged\n"));
5229 /* If basic faces haven't been realized yet, there is no point in
5230 trying to redraw anything. This can happen when we get an expose
5231 event while Emacs is starting, e.g. by moving another window. */
5232 if (FRAME_FACE_CACHE (f
) == NULL
5233 || FRAME_FACE_CACHE (f
)->used
< BASIC_FACE_ID_SENTINEL
)
5235 TRACE ((stderr
, " no faces\n"));
5239 if (w
== 0 || h
== 0)
5242 r
.width
= CANON_X_UNIT (f
) * f
->width
;
5243 r
.height
= CANON_Y_UNIT (f
) * f
->height
;
5253 TRACE ((stderr
, "(%d, %d, %d, %d)\n", r
.x
, r
.y
, r
.width
, r
.height
));
5254 expose_window_tree (XWINDOW (f
->root_window
), &r
);
5256 if (WINDOWP (f
->tool_bar_window
))
5258 struct window
*w
= XWINDOW (f
->tool_bar_window
);
5259 XRectangle window_rect
;
5260 XRectangle intersection_rect
;
5261 int window_x
, window_y
, window_width
, window_height
;
5264 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5265 window_rect
.x
= window_x
;
5266 window_rect
.y
= window_y
;
5267 window_rect
.width
= window_width
;
5268 window_rect
.height
= window_height
;
5270 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5271 expose_window (w
, &intersection_rect
);
5274 #ifndef USE_X_TOOLKIT
5275 if (WINDOWP (f
->menu_bar_window
))
5277 struct window
*w
= XWINDOW (f
->menu_bar_window
);
5278 XRectangle window_rect
;
5279 XRectangle intersection_rect
;
5280 int window_x
, window_y
, window_width
, window_height
;
5283 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
5284 window_rect
.x
= window_x
;
5285 window_rect
.y
= window_y
;
5286 window_rect
.width
= window_width
;
5287 window_rect
.height
= window_height
;
5289 if (x_intersect_rectangles (&r
, &window_rect
, &intersection_rect
))
5290 expose_window (w
, &intersection_rect
);
5292 #endif /* not USE_X_TOOLKIT */
5296 /* Redraw (parts) of all windows in the window tree rooted at W that
5297 intersect R. R contains frame pixel coordinates. */
5300 expose_window_tree (w
, r
)
5306 if (!NILP (w
->hchild
))
5307 expose_window_tree (XWINDOW (w
->hchild
), r
);
5308 else if (!NILP (w
->vchild
))
5309 expose_window_tree (XWINDOW (w
->vchild
), r
);
5312 XRectangle window_rect
;
5313 XRectangle intersection_rect
;
5314 struct frame
*f
= XFRAME (w
->frame
);
5315 int window_x
, window_y
, window_width
, window_height
;
5317 /* Frame-relative pixel rectangle of W. */
5318 window_box (w
, -1, &window_x
, &window_y
, &window_width
,
5322 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
)
5323 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5324 window_rect
.y
= window_y
;
5327 + FRAME_X_FLAGS_AREA_WIDTH (f
)
5328 + FRAME_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
));
5330 = window_height
+ CURRENT_MODE_LINE_HEIGHT (w
);
5332 if (x_intersect_rectangles (r
, &window_rect
, &intersection_rect
))
5333 expose_window (w
, &intersection_rect
);
5336 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5341 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5342 which intersects rectangle R. R is in window-relative coordinates. */
5345 expose_area (w
, row
, r
, area
)
5347 struct glyph_row
*row
;
5349 enum glyph_row_area area
;
5352 struct glyph
*first
= row
->glyphs
[area
];
5353 struct glyph
*end
= row
->glyphs
[area
] + row
->used
[area
];
5357 /* Set x to the window-relative start position for drawing glyphs of
5358 AREA. The first glyph of the text area can be partially visible.
5359 The first glyphs of other areas cannot. */
5360 if (area
== LEFT_MARGIN_AREA
)
5362 else if (area
== TEXT_AREA
)
5363 x
= row
->x
+ window_box_width (w
, LEFT_MARGIN_AREA
);
5365 x
= (window_box_width (w
, LEFT_MARGIN_AREA
)
5366 + window_box_width (w
, TEXT_AREA
));
5368 if (area
== TEXT_AREA
&& row
->fill_line_p
)
5369 /* If row extends face to end of line write the whole line. */
5370 x_draw_glyphs (w
, x
, row
, area
,
5372 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5376 /* Find the first glyph that must be redrawn. */
5378 && x
+ first
->pixel_width
< r
->x
)
5380 x
+= first
->pixel_width
;
5384 /* Find the last one. */
5388 && x
< r
->x
+ r
->width
)
5390 x
+= last
->pixel_width
;
5396 x_draw_glyphs (w
, first_x
, row
, area
,
5397 first
- row
->glyphs
[area
],
5398 last
- row
->glyphs
[area
],
5399 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5405 /* Redraw the parts of the glyph row ROW on window W intersecting
5406 rectangle R. R is in window-relative coordinates. */
5409 expose_line (w
, row
, r
)
5411 struct glyph_row
*row
;
5414 xassert (row
->enabled_p
);
5416 if (row
->mode_line_p
|| w
->pseudo_window_p
)
5417 x_draw_glyphs (w
, 0, row
, TEXT_AREA
, 0, row
->used
[TEXT_AREA
],
5418 row
->inverse_p
? DRAW_INVERSE_VIDEO
: DRAW_NORMAL_TEXT
,
5422 if (row
->used
[LEFT_MARGIN_AREA
])
5423 expose_area (w
, row
, r
, LEFT_MARGIN_AREA
);
5424 if (row
->used
[TEXT_AREA
])
5425 expose_area (w
, row
, r
, TEXT_AREA
);
5426 if (row
->used
[RIGHT_MARGIN_AREA
])
5427 expose_area (w
, row
, r
, RIGHT_MARGIN_AREA
);
5428 x_draw_row_bitmaps (w
, row
);
5433 /* Return non-zero if W's cursor intersects rectangle R. */
5436 x_phys_cursor_in_rect_p (w
, r
)
5440 XRectangle cr
, result
;
5441 struct glyph
*cursor_glyph
;
5443 cursor_glyph
= get_phys_cursor_glyph (w
);
5446 cr
.x
= w
->phys_cursor
.x
;
5447 cr
.y
= w
->phys_cursor
.y
;
5448 cr
.width
= cursor_glyph
->pixel_width
;
5449 cr
.height
= w
->phys_cursor_height
;
5450 return x_intersect_rectangles (&cr
, r
, &result
);
5457 /* Redraw a rectangle of window W. R is a rectangle in window
5458 relative coordinates. Call this function with input blocked. */
5461 expose_window (w
, r
)
5465 struct glyph_row
*row
;
5467 int yb
= window_text_bottom_y (w
);
5468 int cursor_cleared_p
;
5470 /* If window is not yet fully initialized, do nothing. This can
5471 happen when toolkit scroll bars are used and a window is split.
5472 Reconfiguring the scroll bar will generate an expose for a newly
5474 if (w
->current_matrix
== NULL
)
5477 TRACE ((stderr
, "expose_window (%d, %d, %d, %d)\n",
5478 r
->x
, r
->y
, r
->width
, r
->height
));
5480 /* Convert to window coordinates. */
5481 r
->x
= FRAME_TO_WINDOW_PIXEL_X (w
, r
->x
);
5482 r
->y
= FRAME_TO_WINDOW_PIXEL_Y (w
, r
->y
);
5484 /* Turn off the cursor. */
5485 if (!w
->pseudo_window_p
5486 && x_phys_cursor_in_rect_p (w
, r
))
5489 cursor_cleared_p
= 1;
5492 cursor_cleared_p
= 0;
5494 /* Find the first row intersecting the rectangle R. */
5495 row
= w
->current_matrix
->rows
;
5497 while (row
->enabled_p
5499 && y
+ row
->height
< r
->y
)
5505 /* Display the text in the rectangle, one text line at a time. */
5506 while (row
->enabled_p
5508 && y
< r
->y
+ r
->height
)
5510 expose_line (w
, row
, r
);
5515 /* Display the mode line if there is one. */
5516 if (WINDOW_WANTS_MODELINE_P (w
)
5517 && (row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
),
5519 && row
->y
< r
->y
+ r
->height
)
5520 expose_line (w
, row
, r
);
5522 if (!w
->pseudo_window_p
)
5524 /* Draw border between windows. */
5525 x_draw_vertical_border (w
);
5527 /* Turn the cursor on again. */
5528 if (cursor_cleared_p
)
5529 x_update_window_cursor (w
, 1);
5534 /* Determine the intersection of two rectangles R1 and R2. Return
5535 the intersection in *RESULT. Value is non-zero if RESULT is not
5539 x_intersect_rectangles (r1
, r2
, result
)
5540 XRectangle
*r1
, *r2
, *result
;
5542 XRectangle
*left
, *right
;
5543 XRectangle
*upper
, *lower
;
5544 int intersection_p
= 0;
5546 /* Rearrange so that R1 is the left-most rectangle. */
5548 left
= r1
, right
= r2
;
5550 left
= r2
, right
= r1
;
5552 /* X0 of the intersection is right.x0, if this is inside R1,
5553 otherwise there is no intersection. */
5554 if (right
->x
<= left
->x
+ left
->width
)
5556 result
->x
= right
->x
;
5558 /* The right end of the intersection is the minimum of the
5559 the right ends of left and right. */
5560 result
->width
= (min (left
->x
+ left
->width
, right
->x
+ right
->width
)
5563 /* Same game for Y. */
5565 upper
= r1
, lower
= r2
;
5567 upper
= r2
, lower
= r1
;
5569 /* The upper end of the intersection is lower.y0, if this is inside
5570 of upper. Otherwise, there is no intersection. */
5571 if (lower
->y
<= upper
->y
+ upper
->height
)
5573 result
->y
= lower
->y
;
5575 /* The lower end of the intersection is the minimum of the lower
5576 ends of upper and lower. */
5577 result
->height
= (min (lower
->y
+ lower
->height
,
5578 upper
->y
+ upper
->height
)
5584 return intersection_p
;
5595 /* We used to only do this if Vx_no_window_manager was non-nil, but
5596 the ICCCM (section 4.1.6) says that the window's border pixmap
5597 and border pixel are window attributes which are "private to the
5598 client", so we can always change it to whatever we want. */
5600 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5601 f
->output_data
.x
->border_pixel
);
5603 x_update_cursor (f
, 1);
5607 frame_unhighlight (f
)
5610 /* We used to only do this if Vx_no_window_manager was non-nil, but
5611 the ICCCM (section 4.1.6) says that the window's border pixmap
5612 and border pixel are window attributes which are "private to the
5613 client", so we can always change it to whatever we want. */
5615 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5616 f
->output_data
.x
->border_tile
);
5618 x_update_cursor (f
, 1);
5621 /* The focus has changed. Update the frames as necessary to reflect
5622 the new situation. Note that we can't change the selected frame
5623 here, because the Lisp code we are interrupting might become confused.
5624 Each event gets marked with the frame in which it occurred, so the
5625 Lisp code can tell when the switch took place by examining the events. */
5628 x_new_focus_frame (dpyinfo
, frame
)
5629 struct x_display_info
*dpyinfo
;
5630 struct frame
*frame
;
5632 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5634 if (frame
!= dpyinfo
->x_focus_frame
)
5636 /* Set this before calling other routines, so that they see
5637 the correct value of x_focus_frame. */
5638 dpyinfo
->x_focus_frame
= frame
;
5640 if (old_focus
&& old_focus
->auto_lower
)
5641 x_lower_frame (old_focus
);
5644 selected_frame
= frame
;
5645 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
5647 Fselect_window (selected_frame
->selected_window
);
5648 choose_minibuf_frame ();
5651 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
5652 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
5654 pending_autoraise_frame
= 0;
5657 x_frame_rehighlight (dpyinfo
);
5660 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5663 x_mouse_leave (dpyinfo
)
5664 struct x_display_info
*dpyinfo
;
5666 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
5669 /* The focus has changed, or we have redirected a frame's focus to
5670 another frame (this happens when a frame uses a surrogate
5671 mini-buffer frame). Shift the highlight as appropriate.
5673 The FRAME argument doesn't necessarily have anything to do with which
5674 frame is being highlighted or un-highlighted; we only use it to find
5675 the appropriate X display info. */
5678 XTframe_rehighlight (frame
)
5679 struct frame
*frame
;
5681 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
5685 x_frame_rehighlight (dpyinfo
)
5686 struct x_display_info
*dpyinfo
;
5688 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
5690 if (dpyinfo
->x_focus_frame
)
5692 dpyinfo
->x_highlight_frame
5693 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
5694 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
5695 : dpyinfo
->x_focus_frame
);
5696 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
5698 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
5699 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
5703 dpyinfo
->x_highlight_frame
= 0;
5705 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
5708 frame_unhighlight (old_highlight
);
5709 if (dpyinfo
->x_highlight_frame
)
5710 frame_highlight (dpyinfo
->x_highlight_frame
);
5716 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5718 /* Initialize mode_switch_bit and modifier_meaning. */
5720 x_find_modifier_meanings (dpyinfo
)
5721 struct x_display_info
*dpyinfo
;
5723 int min_code
, max_code
;
5726 XModifierKeymap
*mods
;
5728 dpyinfo
->meta_mod_mask
= 0;
5729 dpyinfo
->shift_lock_mask
= 0;
5730 dpyinfo
->alt_mod_mask
= 0;
5731 dpyinfo
->super_mod_mask
= 0;
5732 dpyinfo
->hyper_mod_mask
= 0;
5735 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
5737 min_code
= dpyinfo
->display
->min_keycode
;
5738 max_code
= dpyinfo
->display
->max_keycode
;
5741 syms
= XGetKeyboardMapping (dpyinfo
->display
,
5742 min_code
, max_code
- min_code
+ 1,
5744 mods
= XGetModifierMapping (dpyinfo
->display
);
5746 /* Scan the modifier table to see which modifier bits the Meta and
5747 Alt keysyms are on. */
5749 int row
, col
; /* The row and column in the modifier table. */
5751 for (row
= 3; row
< 8; row
++)
5752 for (col
= 0; col
< mods
->max_keypermod
; col
++)
5755 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
5757 /* Zeroes are used for filler. Skip them. */
5761 /* Are any of this keycode's keysyms a meta key? */
5765 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
5767 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
5773 dpyinfo
->meta_mod_mask
|= (1 << row
);
5778 dpyinfo
->alt_mod_mask
|= (1 << row
);
5783 dpyinfo
->hyper_mod_mask
|= (1 << row
);
5788 dpyinfo
->super_mod_mask
|= (1 << row
);
5792 /* Ignore this if it's not on the lock modifier. */
5793 if ((1 << row
) == LockMask
)
5794 dpyinfo
->shift_lock_mask
= LockMask
;
5802 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5803 if (! dpyinfo
->meta_mod_mask
)
5805 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
5806 dpyinfo
->alt_mod_mask
= 0;
5809 /* If some keys are both alt and meta,
5810 make them just meta, not alt. */
5811 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
5813 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
5816 XFree ((char *) syms
);
5817 XFreeModifiermap (mods
);
5820 /* Convert between the modifier bits X uses and the modifier bits
5824 x_x_to_emacs_modifiers (dpyinfo
, state
)
5825 struct x_display_info
*dpyinfo
;
5828 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
5829 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
5830 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
5831 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
5832 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
5833 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
5837 x_emacs_to_x_modifiers (dpyinfo
, state
)
5838 struct x_display_info
*dpyinfo
;
5841 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
5842 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
5843 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
5844 | ((state
& shift_modifier
) ? ShiftMask
: 0)
5845 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
5846 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
5849 /* Convert a keysym to its name. */
5852 x_get_keysym_name (keysym
)
5858 value
= XKeysymToString (keysym
);
5866 /* Mouse clicks and mouse movement. Rah. */
5868 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5869 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5870 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5871 not force the value into range. */
5874 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
5876 register int pix_x
, pix_y
;
5877 register int *x
, *y
;
5881 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5882 even for negative values. */
5884 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
5886 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
5888 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
5889 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
5893 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
5894 bounds
->height
= f
->output_data
.x
->line_height
;
5895 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
5896 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
5903 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
5904 pix_x
= FRAME_WINDOW_WIDTH (f
);
5908 else if (pix_y
> f
->height
)
5917 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5918 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5919 can't tell the positions because W's display is not up to date,
5923 glyph_to_pixel_coords (w
, hpos
, vpos
, frame_x
, frame_y
)
5926 int *frame_x
, *frame_y
;
5930 xassert (hpos
>= 0 && hpos
< w
->current_matrix
->matrix_w
);
5931 xassert (vpos
>= 0 && vpos
< w
->current_matrix
->matrix_h
);
5933 if (display_completed
)
5935 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, vpos
);
5936 struct glyph
*glyph
= row
->glyphs
[TEXT_AREA
];
5937 struct glyph
*end
= glyph
+ min (hpos
, row
->used
[TEXT_AREA
]);
5943 *frame_x
+= glyph
->pixel_width
;
5951 *frame_y
= *frame_x
= 0;
5955 *frame_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, *frame_y
);
5956 *frame_x
= WINDOW_TO_FRAME_PIXEL_X (w
, *frame_x
);
5961 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5963 If the event is a button press, then note that we have grabbed
5967 construct_mouse_click (result
, event
, f
)
5968 struct input_event
*result
;
5969 XButtonEvent
*event
;
5972 /* Make the event type no_event; we'll change that when we decide
5974 result
->kind
= mouse_click
;
5975 result
->code
= event
->button
- Button1
;
5976 result
->timestamp
= event
->time
;
5977 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
5979 | (event
->type
== ButtonRelease
5983 XSETINT (result
->x
, event
->x
);
5984 XSETINT (result
->y
, event
->y
);
5985 XSETFRAME (result
->frame_or_window
, f
);
5989 #if 0 /* This function isn't called. --gerd */
5991 /* Prepare a menu-event in *RESULT for placement in the input queue. */
5994 construct_menu_click (result
, event
, f
)
5995 struct input_event
*result
;
5996 XButtonEvent
*event
;
5999 /* Make the event type no_event; we'll change that when we decide
6001 result
->kind
= mouse_click
;
6002 result
->code
= event
->button
- Button1
;
6003 result
->timestamp
= event
->time
;
6004 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6006 | (event
->type
== ButtonRelease
6010 XSETINT (result
->x
, event
->x
);
6011 XSETINT (result
->y
, -1);
6012 XSETFRAME (result
->frame_or_window
, f
);
6018 /* Function to report a mouse movement to the mainstream Emacs code.
6019 The input handler calls this.
6021 We have received a mouse movement event, which is given in *event.
6022 If the mouse is over a different glyph than it was last time, tell
6023 the mainstream emacs code by setting mouse_moved. If not, ask for
6024 another motion event, so we can check again the next time it moves. */
6026 static XMotionEvent last_mouse_motion_event
;
6027 static Lisp_Object last_mouse_motion_frame
;
6030 note_mouse_movement (frame
, event
)
6032 XMotionEvent
*event
;
6034 last_mouse_movement_time
= event
->time
;
6035 last_mouse_motion_event
= *event
;
6036 XSETFRAME (last_mouse_motion_frame
, frame
);
6038 if (event
->window
!= FRAME_X_WINDOW (frame
))
6040 frame
->mouse_moved
= 1;
6041 last_mouse_scroll_bar
= Qnil
;
6042 note_mouse_highlight (frame
, -1, -1);
6045 /* Has the mouse moved off the glyph it was on at the last sighting? */
6046 else if (event
->x
< last_mouse_glyph
.x
6047 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
6048 || event
->y
< last_mouse_glyph
.y
6049 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
6051 frame
->mouse_moved
= 1;
6052 last_mouse_scroll_bar
= Qnil
;
6053 note_mouse_highlight (frame
, event
->x
, event
->y
);
6057 /* This is used for debugging, to turn off note_mouse_highlight. */
6059 int disable_mouse_highlight
;
6063 /************************************************************************
6065 ************************************************************************/
6067 /* Find the glyph under window-relative coordinates X/Y in window W.
6068 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6069 strings. Return in *HPOS and *VPOS the row and column number of
6070 the glyph found. Return in *AREA the glyph area containing X.
6071 Value is a pointer to the glyph found or null if X/Y is not on
6072 text, or we can't tell because W's current matrix is not up to
6075 static struct glyph
*
6076 x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, area
)
6079 int *hpos
, *vpos
, *area
;
6081 struct glyph
*glyph
, *end
;
6082 struct glyph_row
*row
;
6083 int x0
, i
, left_area_width
;
6085 /* Find row containing Y. Give up if some row is not enabled. */
6086 for (i
= 0; i
< w
->current_matrix
->nrows
; ++i
)
6088 row
= MATRIX_ROW (w
->current_matrix
, i
);
6089 if (!row
->enabled_p
)
6091 if (y
>= row
->y
&& y
< MATRIX_ROW_BOTTOM_Y (row
))
6098 /* Give up if Y is not in the window. */
6099 if (i
== w
->current_matrix
->nrows
)
6102 /* Get the glyph area containing X. */
6103 if (w
->pseudo_window_p
)
6110 left_area_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
6111 if (x
< left_area_width
)
6113 *area
= LEFT_MARGIN_AREA
;
6116 else if (x
< left_area_width
+ window_box_width (w
, TEXT_AREA
))
6119 x0
= row
->x
+ left_area_width
;
6123 *area
= RIGHT_MARGIN_AREA
;
6124 x0
= left_area_width
+ window_box_width (w
, TEXT_AREA
);
6128 /* Find glyph containing X. */
6129 glyph
= row
->glyphs
[*area
];
6130 end
= glyph
+ row
->used
[*area
];
6133 if (x
< x0
+ glyph
->pixel_width
)
6135 if (w
->pseudo_window_p
)
6137 else if (BUFFERP (glyph
->object
))
6141 x0
+= glyph
->pixel_width
;
6148 *hpos
= glyph
- row
->glyphs
[*area
];
6153 /* Convert frame-relative x/y to coordinates relative to window W.
6154 Takes pseudo-windows into account. */
6157 frame_to_window_pixel_xy (w
, x
, y
)
6161 if (w
->pseudo_window_p
)
6163 /* A pseudo-window is always full-width, and starts at the
6164 left edge of the frame, plus a frame border. */
6165 struct frame
*f
= XFRAME (w
->frame
);
6166 *x
-= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
);
6167 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6171 *x
= FRAME_TO_WINDOW_PIXEL_X (w
, *x
);
6172 *y
= FRAME_TO_WINDOW_PIXEL_Y (w
, *y
);
6177 /* Take proper action when mouse has moved to the mode or top line of
6178 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6179 mode line. X is relative to the start of the text display area of
6180 W, so the width of bitmap areas and scroll bars must be subtracted
6181 to get a position relative to the start of the mode line. */
6184 note_mode_line_highlight (w
, x
, mode_line_p
)
6188 struct frame
*f
= XFRAME (w
->frame
);
6189 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6190 Cursor cursor
= dpyinfo
->vertical_scroll_bar_cursor
;
6191 struct glyph_row
*row
;
6194 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
6196 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
6200 struct glyph
*glyph
, *end
;
6201 Lisp_Object help
, map
;
6204 /* Find the glyph under X. */
6205 glyph
= row
->glyphs
[TEXT_AREA
];
6206 end
= glyph
+ row
->used
[TEXT_AREA
];
6207 x0
= - (FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * CANON_X_UNIT (f
)
6208 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
));
6210 && x
>= x0
+ glyph
->pixel_width
)
6212 x0
+= glyph
->pixel_width
;
6217 && STRINGP (glyph
->object
)
6218 && XSTRING (glyph
->object
)->intervals
6219 && glyph
->charpos
>= 0
6220 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6222 /* If we're on a string with `help-echo' text property,
6223 arrange for the help to be displayed. This is done by
6224 setting the global variable help_echo to the help string. */
6225 help
= Fget_text_property (make_number (glyph
->charpos
),
6226 Qhelp_echo
, glyph
->object
);
6230 /* Change the mouse pointer according to what is under X/Y. */
6231 map
= Fget_text_property (make_number (glyph
->charpos
),
6232 Qlocal_map
, glyph
->object
);
6233 if (!NILP (Fkeymapp (map
)))
6234 cursor
= f
->output_data
.x
->nontext_cursor
;
6238 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), cursor
);
6242 /* Take proper action when the mouse has moved to position X, Y on
6243 frame F as regards highlighting characters that have mouse-face
6244 properties. Also de-highlighting chars where the mouse was before.
6245 X and Y can be negative or out of range. */
6248 note_mouse_highlight (f
, x
, y
)
6252 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6257 /* When a menu is active, don't highlight because this looks odd. */
6258 #ifdef USE_X_TOOLKIT
6259 if (popup_activated ())
6263 if (disable_mouse_highlight
)
6266 dpyinfo
->mouse_face_mouse_x
= x
;
6267 dpyinfo
->mouse_face_mouse_y
= y
;
6268 dpyinfo
->mouse_face_mouse_frame
= f
;
6270 if (dpyinfo
->mouse_face_defer
)
6275 dpyinfo
->mouse_face_deferred_gc
= 1;
6279 /* Which window is that in? */
6280 window
= window_from_coordinates (f
, x
, y
, &portion
, 1);
6282 /* If we were displaying active text in another window, clear that. */
6283 if (! EQ (window
, dpyinfo
->mouse_face_window
))
6284 clear_mouse_face (dpyinfo
);
6286 /* Not on a window -> return. */
6287 if (!WINDOWP (window
))
6290 /* Convert to window-relative pixel coordinates. */
6291 w
= XWINDOW (window
);
6292 frame_to_window_pixel_xy (w
, &x
, &y
);
6294 /* Handle tool-bar window differently since it doesn't display a
6296 if (EQ (window
, f
->tool_bar_window
))
6298 note_tool_bar_highlight (f
, x
, y
);
6302 if (portion
== 1 || portion
== 3)
6304 /* Mouse is on the mode or top line. */
6305 note_mode_line_highlight (w
, x
, portion
== 1);
6309 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6310 f
->output_data
.x
->text_cursor
);
6312 /* Are we in a window whose display is up to date?
6313 And verify the buffer's text has not changed. */
6314 if (/* Within text portion of the window. */
6316 && EQ (w
->window_end_valid
, w
->buffer
)
6317 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
6318 && (XFASTINT (w
->last_overlay_modified
)
6319 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
6321 int hpos
, vpos
, pos
, i
, area
;
6322 struct glyph
*glyph
;
6324 /* Find the glyph under X/Y. */
6325 glyph
= x_y_to_hpos_vpos (w
, x
, y
, &hpos
, &vpos
, &area
);
6327 /* Clear mouse face if X/Y not over text. */
6329 || area
!= TEXT_AREA
6330 || !MATRIX_ROW (w
->current_matrix
, vpos
)->displays_text_p
)
6332 clear_mouse_face (dpyinfo
);
6336 pos
= glyph
->charpos
;
6337 xassert (w
->pseudo_window_p
|| BUFFERP (glyph
->object
));
6339 /* Check for mouse-face and help-echo. */
6341 Lisp_Object mouse_face
, overlay
, position
;
6342 Lisp_Object
*overlay_vec
;
6344 struct buffer
*obuf
;
6347 /* If we get an out-of-range value, return now; avoid an error. */
6348 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
6351 /* Make the window's buffer temporarily current for
6352 overlays_at and compute_char_face. */
6353 obuf
= current_buffer
;
6354 current_buffer
= XBUFFER (w
->buffer
);
6360 /* Is this char mouse-active or does it have help-echo? */
6361 XSETINT (position
, pos
);
6363 /* Put all the overlays we want in a vector in overlay_vec.
6364 Store the length in len. If there are more than 10, make
6365 enough space for all, and try again. */
6367 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6368 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6369 if (noverlays
> len
)
6372 overlay_vec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
6373 noverlays
= overlays_at (pos
, 0, &overlay_vec
, &len
, NULL
, NULL
);
6376 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
6378 /* Check mouse-face highlighting. */
6379 if (! (EQ (window
, dpyinfo
->mouse_face_window
)
6380 && vpos
>= dpyinfo
->mouse_face_beg_row
6381 && vpos
<= dpyinfo
->mouse_face_end_row
6382 && (vpos
> dpyinfo
->mouse_face_beg_row
6383 || hpos
>= dpyinfo
->mouse_face_beg_col
)
6384 && (vpos
< dpyinfo
->mouse_face_end_row
6385 || hpos
< dpyinfo
->mouse_face_end_col
6386 || dpyinfo
->mouse_face_past_end
)))
6388 /* Clear the display of the old active region, if any. */
6389 clear_mouse_face (dpyinfo
);
6391 /* Find the highest priority overlay that has a mouse-face prop. */
6393 for (i
= 0; i
< noverlays
; i
++)
6395 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
6396 if (!NILP (mouse_face
))
6398 overlay
= overlay_vec
[i
];
6403 /* If no overlay applies, get a text property. */
6405 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
6407 /* Handle the overlay case. */
6408 if (! NILP (overlay
))
6410 /* Find the range of text around this char that
6411 should be active. */
6412 Lisp_Object before
, after
;
6415 before
= Foverlay_start (overlay
);
6416 after
= Foverlay_end (overlay
);
6417 /* Record this as the current active region. */
6418 fast_find_position (w
, XFASTINT (before
),
6419 &dpyinfo
->mouse_face_beg_col
,
6420 &dpyinfo
->mouse_face_beg_row
,
6421 &dpyinfo
->mouse_face_beg_x
,
6422 &dpyinfo
->mouse_face_beg_y
);
6423 dpyinfo
->mouse_face_past_end
6424 = !fast_find_position (w
, XFASTINT (after
),
6425 &dpyinfo
->mouse_face_end_col
,
6426 &dpyinfo
->mouse_face_end_row
,
6427 &dpyinfo
->mouse_face_end_x
,
6428 &dpyinfo
->mouse_face_end_y
);
6429 dpyinfo
->mouse_face_window
= window
;
6430 dpyinfo
->mouse_face_face_id
6431 = face_at_buffer_position (w
, pos
, 0, 0,
6432 &ignore
, pos
+ 1, 1);
6434 /* Display it as active. */
6435 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6437 /* Handle the text property case. */
6438 else if (! NILP (mouse_face
))
6440 /* Find the range of text around this char that
6441 should be active. */
6442 Lisp_Object before
, after
, beginning
, end
;
6445 beginning
= Fmarker_position (w
->start
);
6446 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
6447 - XFASTINT (w
->window_end_pos
)));
6449 = Fprevious_single_property_change (make_number (pos
+ 1),
6451 w
->buffer
, beginning
);
6453 = Fnext_single_property_change (position
, Qmouse_face
,
6455 /* Record this as the current active region. */
6456 fast_find_position (w
, XFASTINT (before
),
6457 &dpyinfo
->mouse_face_beg_col
,
6458 &dpyinfo
->mouse_face_beg_row
,
6459 &dpyinfo
->mouse_face_beg_x
,
6460 &dpyinfo
->mouse_face_beg_y
);
6461 dpyinfo
->mouse_face_past_end
6462 = !fast_find_position (w
, XFASTINT (after
),
6463 &dpyinfo
->mouse_face_end_col
,
6464 &dpyinfo
->mouse_face_end_row
,
6465 &dpyinfo
->mouse_face_end_x
,
6466 &dpyinfo
->mouse_face_end_y
);
6467 dpyinfo
->mouse_face_window
= window
;
6468 dpyinfo
->mouse_face_face_id
6469 = face_at_buffer_position (w
, pos
, 0, 0,
6470 &ignore
, pos
+ 1, 1);
6472 /* Display it as active. */
6473 show_mouse_face (dpyinfo
, DRAW_MOUSE_FACE
);
6477 /* Look for a `help-echo' property. */
6481 /* Check overlays first. */
6483 for (i
= 0; i
< noverlays
&& !STRINGP (help
); ++i
)
6484 help
= Foverlay_get (overlay_vec
[i
], Qhelp_echo
);
6486 /* Try text properties. */
6488 && ((STRINGP (glyph
->object
)
6489 && glyph
->charpos
>= 0
6490 && glyph
->charpos
< XSTRING (glyph
->object
)->size
)
6491 || (BUFFERP (glyph
->object
)
6492 && glyph
->charpos
>= BEGV
6493 && glyph
->charpos
< ZV
)))
6494 help
= Fget_text_property (make_number (glyph
->charpos
),
6495 Qhelp_echo
, glyph
->object
);
6503 current_buffer
= obuf
;
6509 redo_mouse_highlight ()
6511 if (!NILP (last_mouse_motion_frame
)
6512 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
6513 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
6514 last_mouse_motion_event
.x
,
6515 last_mouse_motion_event
.y
);
6520 /***********************************************************************
6522 ***********************************************************************/
6524 static int x_tool_bar_item
P_ ((struct frame
*, int, int,
6525 struct glyph
**, int *, int *, int *));
6527 /* Tool-bar item index of the item on which a mouse button was pressed
6530 static int last_tool_bar_item
;
6533 /* Get information about the tool-bar item at position X/Y on frame F.
6534 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6535 the current matrix of the tool-bar window of F, or NULL if not
6536 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6537 item in F->current_tool_bar_items. Value is
6539 -1 if X/Y is not on a tool-bar item
6540 0 if X/Y is on the same item that was highlighted before.
6544 x_tool_bar_item (f
, x
, y
, glyph
, hpos
, vpos
, prop_idx
)
6547 struct glyph
**glyph
;
6548 int *hpos
, *vpos
, *prop_idx
;
6550 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6551 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6554 /* Find the glyph under X/Y. */
6555 *glyph
= x_y_to_hpos_vpos (w
, x
, y
, hpos
, vpos
, &area
);
6559 /* Get the start of this tool-bar item's properties in
6560 f->current_tool_bar_items. */
6561 if (!tool_bar_item_info (f
, *glyph
, prop_idx
))
6564 /* Is mouse on the highlighted item? */
6565 if (EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
)
6566 && *vpos
>= dpyinfo
->mouse_face_beg_row
6567 && *vpos
<= dpyinfo
->mouse_face_end_row
6568 && (*vpos
> dpyinfo
->mouse_face_beg_row
6569 || *hpos
>= dpyinfo
->mouse_face_beg_col
)
6570 && (*vpos
< dpyinfo
->mouse_face_end_row
6571 || *hpos
< dpyinfo
->mouse_face_end_col
6572 || dpyinfo
->mouse_face_past_end
))
6579 /* Handle mouse button event on the tool-bar of frame F, at
6580 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6584 x_handle_tool_bar_click (f
, button_event
)
6586 XButtonEvent
*button_event
;
6588 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6589 struct window
*w
= XWINDOW (f
->tool_bar_window
);
6590 int hpos
, vpos
, prop_idx
;
6591 struct glyph
*glyph
;
6592 Lisp_Object enabled_p
;
6593 int x
= button_event
->x
;
6594 int y
= button_event
->y
;
6596 /* If not on the highlighted tool-bar item, return. */
6597 frame_to_window_pixel_xy (w
, &x
, &y
);
6598 if (x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
) != 0)
6601 /* If item is disabled, do nothing. */
6602 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6603 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6604 if (NILP (enabled_p
))
6607 if (button_event
->type
== ButtonPress
)
6609 /* Show item in pressed state. */
6610 show_mouse_face (dpyinfo
, DRAW_IMAGE_SUNKEN
);
6611 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_SUNKEN
;
6612 last_tool_bar_item
= prop_idx
;
6616 Lisp_Object key
, frame
;
6617 struct input_event event
;
6619 /* Show item in released state. */
6620 show_mouse_face (dpyinfo
, DRAW_IMAGE_RAISED
);
6621 dpyinfo
->mouse_face_image_state
= DRAW_IMAGE_RAISED
;
6623 key
= (XVECTOR (f
->current_tool_bar_items
)
6624 ->contents
[prop_idx
+ TOOL_BAR_ITEM_KEY
]);
6626 XSETFRAME (frame
, f
);
6627 event
.kind
= TOOL_BAR_EVENT
;
6628 event
.frame_or_window
= Fcons (frame
, Fcons (Qtool_bar
, Qnil
));
6629 kbd_buffer_store_event (&event
);
6631 event
.kind
= TOOL_BAR_EVENT
;
6632 event
.frame_or_window
= Fcons (frame
, key
);
6633 event
.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
6634 button_event
->state
);
6635 kbd_buffer_store_event (&event
);
6636 last_tool_bar_item
= -1;
6641 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6642 tool-bar window-relative coordinates X/Y. Called from
6643 note_mouse_highlight. */
6646 note_tool_bar_highlight (f
, x
, y
)
6650 Lisp_Object window
= f
->tool_bar_window
;
6651 struct window
*w
= XWINDOW (window
);
6652 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6654 struct glyph
*glyph
;
6655 struct glyph_row
*row
;
6657 Lisp_Object enabled_p
;
6659 enum draw_glyphs_face draw
= DRAW_IMAGE_RAISED
;
6660 int mouse_down_p
, rc
;
6662 /* Function note_mouse_highlight is called with negative x(y
6663 values when mouse moves outside of the frame. */
6664 if (x
<= 0 || y
<= 0)
6666 clear_mouse_face (dpyinfo
);
6670 rc
= x_tool_bar_item (f
, x
, y
, &glyph
, &hpos
, &vpos
, &prop_idx
);
6673 /* Not on tool-bar item. */
6674 clear_mouse_face (dpyinfo
);
6678 /* On same tool-bar item as before. */
6681 clear_mouse_face (dpyinfo
);
6683 /* Mouse is down, but on different tool-bar item? */
6684 mouse_down_p
= (dpyinfo
->grabbed
6685 && f
== last_mouse_frame
6686 && FRAME_LIVE_P (f
));
6688 && last_tool_bar_item
!= prop_idx
)
6691 dpyinfo
->mouse_face_image_state
= DRAW_NORMAL_TEXT
;
6692 draw
= mouse_down_p
? DRAW_IMAGE_SUNKEN
: DRAW_IMAGE_RAISED
;
6694 /* If tool-bar item is not enabled, don't highlight it. */
6695 enabled_p
= (XVECTOR (f
->current_tool_bar_items
)
6696 ->contents
[prop_idx
+ TOOL_BAR_ITEM_ENABLED_P
]);
6697 if (!NILP (enabled_p
))
6699 /* Compute the x-position of the glyph. In front and past the
6700 image is a space. We include this is the highlighted area. */
6701 row
= MATRIX_ROW (w
->current_matrix
, vpos
);
6702 for (i
= x
= 0; i
< hpos
; ++i
)
6703 x
+= row
->glyphs
[TEXT_AREA
][i
].pixel_width
;
6705 /* Record this as the current active region. */
6706 dpyinfo
->mouse_face_beg_col
= hpos
;
6707 dpyinfo
->mouse_face_beg_row
= vpos
;
6708 dpyinfo
->mouse_face_beg_x
= x
;
6709 dpyinfo
->mouse_face_beg_y
= row
->y
;
6710 dpyinfo
->mouse_face_past_end
= 0;
6712 dpyinfo
->mouse_face_end_col
= hpos
+ 1;
6713 dpyinfo
->mouse_face_end_row
= vpos
;
6714 dpyinfo
->mouse_face_end_x
= x
+ glyph
->pixel_width
;
6715 dpyinfo
->mouse_face_end_y
= row
->y
;
6716 dpyinfo
->mouse_face_window
= window
;
6717 dpyinfo
->mouse_face_face_id
= TOOL_BAR_FACE_ID
;
6719 /* Display it as active. */
6720 show_mouse_face (dpyinfo
, draw
);
6721 dpyinfo
->mouse_face_image_state
= draw
;
6726 /* Set help_echo to a help string.to display for this tool-bar item.
6727 XTread_socket does the rest. */
6728 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6729 ->contents
[prop_idx
+ TOOL_BAR_ITEM_HELP
]);
6730 if (!STRINGP (help_echo
))
6731 help_echo
= (XVECTOR (f
->current_tool_bar_items
)
6732 ->contents
[prop_idx
+ TOOL_BAR_ITEM_CAPTION
]);
6737 /* Find the glyph matrix position of buffer position POS in window W.
6738 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6739 current glyphs must be up to date. If POS is above window start
6740 return (0, 0, 0, 0). If POS is after end of W, return end of
6744 fast_find_position (w
, pos
, hpos
, vpos
, x
, y
)
6747 int *hpos
, *vpos
, *x
, *y
;
6751 int maybe_next_line_p
= 0;
6752 int line_start_position
;
6753 int yb
= window_text_bottom_y (w
);
6754 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, 0);
6755 struct glyph_row
*best_row
= row
;
6756 int row_vpos
= 0, best_row_vpos
= 0;
6761 if (row
->used
[TEXT_AREA
])
6762 line_start_position
= row
->glyphs
[TEXT_AREA
]->charpos
;
6764 line_start_position
= 0;
6766 if (line_start_position
> pos
)
6768 /* If the position sought is the end of the buffer,
6769 don't include the blank lines at the bottom of the window. */
6770 else if (line_start_position
== pos
6771 && pos
== BUF_ZV (XBUFFER (w
->buffer
)))
6773 maybe_next_line_p
= 1;
6776 else if (line_start_position
> 0)
6779 best_row_vpos
= row_vpos
;
6786 /* Find the right column within BEST_ROW. */
6788 current_x
= best_row
->x
;
6789 for (i
= 0; i
< best_row
->used
[TEXT_AREA
]; i
++)
6791 struct glyph
*glyph
= best_row
->glyphs
[TEXT_AREA
] + i
;
6794 charpos
= glyph
->charpos
;
6798 *vpos
= best_row_vpos
;
6803 else if (charpos
> pos
)
6805 else if (charpos
> 0)
6808 current_x
+= glyph
->pixel_width
;
6811 /* If we're looking for the end of the buffer,
6812 and we didn't find it in the line we scanned,
6813 use the start of the following line. */
6814 if (maybe_next_line_p
)
6819 current_x
= best_row
->x
;
6822 *vpos
= best_row_vpos
;
6823 *hpos
= lastcol
+ 1;
6830 /* Display the active region described by mouse_face_*
6831 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6834 show_mouse_face (dpyinfo
, draw
)
6835 struct x_display_info
*dpyinfo
;
6836 enum draw_glyphs_face draw
;
6838 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
6839 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
6841 int cursor_off_p
= 0;
6842 struct cursor_pos saved_cursor
;
6844 saved_cursor
= output_cursor
;
6846 /* If window is in the process of being destroyed, don't bother
6848 if (w
->current_matrix
== NULL
)
6851 /* Recognize when we are called to operate on rows that don't exist
6852 anymore. This can happen when a window is split. */
6853 if (dpyinfo
->mouse_face_end_row
>= w
->current_matrix
->nrows
)
6856 set_output_cursor (&w
->phys_cursor
);
6858 /* Note that mouse_face_beg_row etc. are window relative. */
6859 for (i
= dpyinfo
->mouse_face_beg_row
;
6860 i
<= dpyinfo
->mouse_face_end_row
;
6863 int start_hpos
, end_hpos
, start_x
;
6864 struct glyph_row
*row
= MATRIX_ROW (w
->current_matrix
, i
);
6866 /* Don't do anything if row doesn't have valid contents. */
6867 if (!row
->enabled_p
)
6870 /* For all but the first row, the highlight starts at column 0. */
6871 if (i
== dpyinfo
->mouse_face_beg_row
)
6873 start_hpos
= dpyinfo
->mouse_face_beg_col
;
6874 start_x
= dpyinfo
->mouse_face_beg_x
;
6882 if (i
== dpyinfo
->mouse_face_end_row
)
6883 end_hpos
= dpyinfo
->mouse_face_end_col
;
6885 end_hpos
= row
->used
[TEXT_AREA
];
6887 /* If the cursor's in the text we are about to rewrite, turn the
6889 if (!w
->pseudo_window_p
6890 && i
== output_cursor
.vpos
6891 && output_cursor
.hpos
>= start_hpos
- 1
6892 && output_cursor
.hpos
<= end_hpos
)
6894 x_update_window_cursor (w
, 0);
6898 if (end_hpos
> start_hpos
)
6899 x_draw_glyphs (w
, start_x
, row
, TEXT_AREA
,
6900 start_hpos
, end_hpos
, draw
, NULL
, NULL
, 0);
6903 /* If we turned the cursor off, turn it back on. */
6905 x_display_cursor (w
, 1,
6906 output_cursor
.hpos
, output_cursor
.vpos
,
6907 output_cursor
.x
, output_cursor
.y
);
6909 output_cursor
= saved_cursor
;
6913 /* Change the mouse cursor. */
6914 if (draw
== DRAW_NORMAL_TEXT
)
6915 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6916 f
->output_data
.x
->text_cursor
);
6917 else if (draw
== DRAW_MOUSE_FACE
)
6918 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6919 f
->output_data
.x
->cross_cursor
);
6921 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
6922 f
->output_data
.x
->nontext_cursor
);
6925 /* Clear out the mouse-highlighted active region.
6926 Redraw it un-highlighted first. */
6929 clear_mouse_face (dpyinfo
)
6930 struct x_display_info
*dpyinfo
;
6935 if (! NILP (dpyinfo
->mouse_face_window
))
6936 show_mouse_face (dpyinfo
, DRAW_NORMAL_TEXT
);
6938 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6939 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6940 dpyinfo
->mouse_face_window
= Qnil
;
6943 /* Just discard the mouse face information for frame F, if any.
6944 This is used when the size of F is changed. */
6947 cancel_mouse_face (f
)
6951 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6953 window
= dpyinfo
->mouse_face_window
;
6954 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
6956 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6957 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6958 dpyinfo
->mouse_face_window
= Qnil
;
6962 static struct scroll_bar
*x_window_to_scroll_bar ();
6963 static void x_scroll_bar_report_motion ();
6965 /* Return the current position of the mouse.
6966 *fp should be a frame which indicates which display to ask about.
6968 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6969 and *part to the frame, window, and scroll bar part that the mouse
6970 is over. Set *x and *y to the portion and whole of the mouse's
6971 position on the scroll bar.
6973 If the mouse movement started elsewhere, set *fp to the frame the
6974 mouse is on, *bar_window to nil, and *x and *y to the character cell
6977 Set *time to the server time-stamp for the time at which the mouse
6978 was at this position.
6980 Don't store anything if we don't have a valid set of values to report.
6982 This clears the mouse_moved flag, so we can wait for the next mouse
6986 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
6989 Lisp_Object
*bar_window
;
6990 enum scroll_bar_part
*part
;
6992 unsigned long *time
;
6998 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
6999 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
7005 Window dummy_window
;
7008 Lisp_Object frame
, tail
;
7010 /* Clear the mouse-moved flag for every frame on this display. */
7011 FOR_EACH_FRAME (tail
, frame
)
7012 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
7013 XFRAME (frame
)->mouse_moved
= 0;
7015 last_mouse_scroll_bar
= Qnil
;
7017 /* Figure out which root window we're on. */
7018 XQueryPointer (FRAME_X_DISPLAY (*fp
),
7019 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
7021 /* The root window which contains the pointer. */
7024 /* Trash which we can't trust if the pointer is on
7025 a different screen. */
7028 /* The position on that root window. */
7031 /* More trash we can't trust. */
7034 /* Modifier keys and pointer buttons, about which
7036 (unsigned int *) &dummy
);
7038 /* Now we have a position on the root; find the innermost window
7039 containing the pointer. */
7043 int parent_x
= 0, parent_y
= 0;
7048 /* XTranslateCoordinates can get errors if the window
7049 structure is changing at the same time this function
7050 is running. So at least we must not crash from them. */
7052 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
7054 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
7055 && FRAME_LIVE_P (last_mouse_frame
))
7057 /* If mouse was grabbed on a frame, give coords for that frame
7058 even if the mouse is now outside it. */
7059 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7061 /* From-window, to-window. */
7062 root
, FRAME_X_WINDOW (last_mouse_frame
),
7064 /* From-position, to-position. */
7065 root_x
, root_y
, &win_x
, &win_y
,
7069 f1
= last_mouse_frame
;
7075 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
7077 /* From-window, to-window. */
7080 /* From-position, to-position. */
7081 root_x
, root_y
, &win_x
, &win_y
,
7086 if (child
== None
|| child
== win
)
7094 /* Now we know that:
7095 win is the innermost window containing the pointer
7096 (XTC says it has no child containing the pointer),
7097 win_x and win_y are the pointer's position in it
7098 (XTC did this the last time through), and
7099 parent_x and parent_y are the pointer's position in win's parent.
7100 (They are what win_x and win_y were when win was child.
7101 If win is the root window, it has no parent, and
7102 parent_{x,y} are invalid, but that's okay, because we'll
7103 never use them in that case.) */
7105 /* Is win one of our frames? */
7106 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
7109 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
7112 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
7114 /* If not, is it one of our scroll bars? */
7117 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
7121 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7127 if (f1
== 0 && insist
> 0)
7128 f1
= SELECTED_FRAME ();
7132 /* Ok, we found a frame. Store all the values.
7133 last_mouse_glyph is a rectangle used to reduce the
7134 generation of mouse events. To not miss any motion
7135 events, we must divide the frame into rectangles of the
7136 size of the smallest character that could be displayed
7137 on it, i.e. into the same rectangles that matrices on
7138 the frame are divided into. */
7140 #if OLD_REDISPLAY_CODE
7141 int ignore1
, ignore2
;
7142 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
7144 FRAME_X_DISPLAY_INFO (f1
)->grabbed
7148 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
7149 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
7153 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7154 round down even for negative values. */
7160 last_mouse_glyph
.width
= width
;
7161 last_mouse_glyph
.height
= height
;
7162 last_mouse_glyph
.x
= (x
+ width
- 1) / width
* width
;
7163 last_mouse_glyph
.y
= (y
+ height
- 1) / height
* height
;
7170 XSETINT (*x
, win_x
);
7171 XSETINT (*y
, win_y
);
7172 *time
= last_mouse_movement_time
;
7181 DEFUN ("xt-process-timeouts", Fxt_process_timeouts
, Sxt_process_timeouts
,
7183 "Arrange for Xt timeout callbacks to be called.")
7186 #ifdef USE_X_TOOLKIT
7188 while (XtAppPending (Xt_app_con
) & XtIMTimer
)
7189 XtAppProcessEvent (Xt_app_con
, XtIMTimer
);
7191 #endif /* USE_X_TOOLKIT */
7198 /* Scroll bar support. */
7200 /* Given an X window ID, find the struct scroll_bar which manages it.
7201 This can be called in GC, so we have to make sure to strip off mark
7203 static struct scroll_bar
*
7204 x_window_to_scroll_bar (window_id
)
7209 for (tail
= Vframe_list
;
7210 XGCTYPE (tail
) == Lisp_Cons
;
7213 Lisp_Object frame
, bar
, condemned
;
7215 frame
= XCAR (tail
);
7216 /* All elements of Vframe_list should be frames. */
7217 if (! GC_FRAMEP (frame
))
7220 /* Scan this frame's scroll bar list for a scroll bar with the
7222 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
7223 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
7224 /* This trick allows us to search both the ordinary and
7225 condemned scroll bar lists with one loop. */
7226 ! GC_NILP (bar
) || (bar
= condemned
,
7229 bar
= XSCROLL_BAR (bar
)->next
)
7230 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
7231 return XSCROLL_BAR (bar
);
7239 /************************************************************************
7241 ************************************************************************/
7243 #if USE_TOOLKIT_SCROLL_BARS
7245 static void x_scroll_bar_to_input_event
P_ ((XEvent
*, struct input_event
*));
7246 static void x_send_scroll_bar_event
P_ ((Lisp_Object
, int, int, int));
7247 static void x_create_toolkit_scroll_bar
P_ ((struct frame
*,
7248 struct scroll_bar
*));
7249 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
7253 /* Id of action hook installed for scroll bars. */
7255 static XtActionHookId action_hook_id
;
7257 /* Lisp window being scrolled. Set when starting to interact with
7258 a toolkit scroll bar, reset to nil when ending the interaction. */
7260 static Lisp_Object window_being_scrolled
;
7262 /* Last scroll bar part sent in xm_scroll_callback. */
7264 static int last_scroll_bar_part
;
7266 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7267 that movements of 1/20 of the screen size are mapped to up/down. */
7269 static Boolean xaw3d_arrow_scroll
;
7271 /* Whether the drag scrolling maintains the mouse at the top of the
7272 thumb. If not, resizing the thumb needs to be done more carefully
7273 to avoid jerkyness. */
7275 static Boolean xaw3d_pick_top
;
7278 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7279 bars are used.. The hook is responsible for detecting when
7280 the user ends an interaction with the scroll bar, and generates
7281 a `end-scroll' scroll_bar_click' event if so. */
7284 xt_action_hook (widget
, client_data
, action_name
, event
, params
,
7287 XtPointer client_data
;
7291 Cardinal
*num_params
;
7297 scroll_bar_p
= XmIsScrollBar (widget
);
7298 end_action
= "Release";
7299 #else /* !USE_MOTIF i.e. use Xaw */
7300 scroll_bar_p
= XtIsSubclass (widget
, scrollbarWidgetClass
);
7301 end_action
= "EndScroll";
7302 #endif /* USE_MOTIF */
7304 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
7305 let Xt timeouts be processed doesn't work. */
7307 && strcmp (action_name
, end_action
) == 0
7308 && WINDOWP (window_being_scrolled
))
7312 x_send_scroll_bar_event (window_being_scrolled
,
7313 scroll_bar_end_scroll
, 0, 0);
7314 w
= XWINDOW (window_being_scrolled
);
7315 XSCROLL_BAR (w
->vertical_scroll_bar
)->dragging
= Qnil
;
7316 window_being_scrolled
= Qnil
;
7317 last_scroll_bar_part
= -1;
7322 /* Send a client message with message type Xatom_Scrollbar for a
7323 scroll action to the frame of WINDOW. PART is a value identifying
7324 the part of the scroll bar that was clicked on. PORTION is the
7325 amount to scroll of a whole of WHOLE. */
7328 x_send_scroll_bar_event (window
, part
, portion
, whole
)
7330 int part
, portion
, whole
;
7333 XClientMessageEvent
*ev
= (XClientMessageEvent
*) &event
;
7334 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7336 /* Construct a ClientMessage event to send to the frame. */
7337 ev
->type
= ClientMessage
;
7338 ev
->message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_Scrollbar
;
7339 ev
->display
= FRAME_X_DISPLAY (f
);
7340 ev
->window
= FRAME_X_WINDOW (f
);
7342 ev
->data
.l
[0] = (long) window
;
7343 ev
->data
.l
[1] = (long) part
;
7344 ev
->data
.l
[2] = (long) 0;
7345 ev
->data
.l
[3] = (long) portion
;
7346 ev
->data
.l
[4] = (long) whole
;
7348 /* Setting the event mask to zero means that the message will
7349 be sent to the client that created the window, and if that
7350 window no longer exists, no event will be sent. */
7352 XSendEvent (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), False
, 0, &event
);
7357 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7361 x_scroll_bar_to_input_event (event
, ievent
)
7363 struct input_event
*ievent
;
7365 XClientMessageEvent
*ev
= (XClientMessageEvent
*) event
;
7366 Lisp_Object window
= (Lisp_Object
) ev
->data
.l
[0];
7367 struct frame
*f
= XFRAME (XWINDOW (window
)->frame
);
7369 ievent
->kind
= scroll_bar_click
;
7370 ievent
->frame_or_window
= window
;
7371 ievent
->timestamp
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
7372 ievent
->part
= ev
->data
.l
[1];
7373 ievent
->code
= ev
->data
.l
[2];
7374 ievent
->x
= make_number ((int) ev
->data
.l
[3]);
7375 ievent
->y
= make_number ((int) ev
->data
.l
[4]);
7376 ievent
->modifiers
= 0;
7382 /* Minimum and maximum values used for Motif scroll bars. */
7385 #define XM_SB_MAX 10000000
7386 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7389 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7390 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7391 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7394 xm_scroll_callback (widget
, client_data
, call_data
)
7396 XtPointer client_data
, call_data
;
7398 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7399 XmScrollBarCallbackStruct
*cs
= (XmScrollBarCallbackStruct
*) call_data
;
7401 int part
= -1, whole
= 0, portion
= 0;
7405 case XmCR_DECREMENT
:
7406 bar
->dragging
= Qnil
;
7407 part
= scroll_bar_up_arrow
;
7410 case XmCR_INCREMENT
:
7411 bar
->dragging
= Qnil
;
7412 part
= scroll_bar_down_arrow
;
7415 case XmCR_PAGE_DECREMENT
:
7416 bar
->dragging
= Qnil
;
7417 part
= scroll_bar_above_handle
;
7420 case XmCR_PAGE_INCREMENT
:
7421 bar
->dragging
= Qnil
;
7422 part
= scroll_bar_below_handle
;
7426 bar
->dragging
= Qnil
;
7427 part
= scroll_bar_to_top
;
7430 case XmCR_TO_BOTTOM
:
7431 bar
->dragging
= Qnil
;
7432 part
= scroll_bar_to_bottom
;
7438 int dragging_down_p
= (INTEGERP (bar
->dragging
)
7439 && XINT (bar
->dragging
) <= cs
->value
);
7441 /* Get the slider size. */
7443 XtVaGetValues (widget
, XmNsliderSize
, &slider_size
, NULL
);
7446 /* At the max position of the scroll bar, do a line-wise
7447 movement. Without doing anything, the LessTif scroll bar
7448 calls us with the same cs->value again and again. If we
7449 want to make sure that we can reach the end of the buffer,
7450 we have to do something.
7452 Implementation note: setting bar->dragging always to
7453 cs->value gives a smoother movement at the max position.
7454 Setting it to nil when doing line-wise movement gives
7455 a better slider behavior. */
7457 if (cs
->value
+ slider_size
== XM_SB_MAX
7459 && last_scroll_bar_part
== scroll_bar_down_arrow
))
7461 part
= scroll_bar_down_arrow
;
7462 bar
->dragging
= Qnil
;
7466 whole
= XM_SB_RANGE
;
7467 portion
= min (cs
->value
- XM_SB_MIN
, XM_SB_MAX
- slider_size
);
7468 part
= scroll_bar_handle
;
7469 bar
->dragging
= make_number (cs
->value
);
7474 case XmCR_VALUE_CHANGED
:
7480 window_being_scrolled
= bar
->window
;
7481 last_scroll_bar_part
= part
;
7482 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7487 #else /* !USE_MOTIF, i.e. Xaw. */
7490 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7491 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7492 scroll bar struct. CALL_DATA is a pointer to a float saying where
7496 xaw_jump_callback (widget
, client_data
, call_data
)
7498 XtPointer client_data
, call_data
;
7500 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7501 float top
= *(float *) call_data
;
7503 int whole
, portion
, height
;
7506 /* Get the size of the thumb, a value between 0 and 1. */
7508 XtVaGetValues (widget
, XtNshown
, &shown
, XtNheight
, &height
, NULL
);
7512 portion
= shown
< 1 ? top
* whole
: 0;
7514 if (shown
< 1 && (abs (top
+ shown
- 1) < 1.0/height
))
7515 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7516 the bottom, so we force the scrolling whenever we see that we're
7517 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7518 we try to ensure that we always stay two pixels away from the
7520 part
= scroll_bar_down_arrow
;
7522 part
= scroll_bar_handle
;
7524 window_being_scrolled
= bar
->window
;
7525 bar
->dragging
= make_number (portion
);
7526 last_scroll_bar_part
= part
;
7527 x_send_scroll_bar_event (bar
->window
, part
, portion
, whole
);
7531 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7532 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7533 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7534 the scroll bar. CALL_DATA is an integer specifying the action that
7535 has taken place. It's magnitude is in the range 0..height of the
7536 scroll bar. Negative values mean scroll towards buffer start.
7537 Values < height of scroll bar mean line-wise movement. */
7540 xaw_scroll_callback (widget
, client_data
, call_data
)
7542 XtPointer client_data
, call_data
;
7544 struct scroll_bar
*bar
= (struct scroll_bar
*) client_data
;
7545 int position
= (int) call_data
;
7549 /* Get the height of the scroll bar. */
7551 XtVaGetValues (widget
, XtNheight
, &height
, NULL
);
7554 if (abs (position
) >= height
)
7555 part
= (position
< 0) ? scroll_bar_above_handle
: scroll_bar_below_handle
;
7557 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7558 it maps line-movement to call_data = max(5, height/20). */
7559 else if (xaw3d_arrow_scroll
&& abs (position
) <= max (5, height
/ 20))
7560 part
= (position
< 0) ? scroll_bar_up_arrow
: scroll_bar_down_arrow
;
7562 part
= scroll_bar_move_ratio
;
7564 window_being_scrolled
= bar
->window
;
7565 bar
->dragging
= Qnil
;
7566 last_scroll_bar_part
= part
;
7567 x_send_scroll_bar_event (bar
->window
, part
, position
, height
);
7571 #endif /* not USE_MOTIF */
7574 /* Create the widget for scroll bar BAR on frame F. Record the widget
7575 and X window of the scroll bar in BAR. */
7578 x_create_toolkit_scroll_bar (f
, bar
)
7580 struct scroll_bar
*bar
;
7586 char *scroll_bar_name
= "verticalScrollBar";
7587 unsigned long pixel
;
7592 /* LessTif 0.85, problems:
7594 1. When the mouse if over the scroll bar, the scroll bar will
7595 get keyboard events. I didn't find a way to turn this off.
7597 2. Do we have to explicitly set the cursor to get an arrow
7598 cursor (see below)? */
7600 /* Set resources. Create the widget. */
7601 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7602 XtSetArg (av
[ac
], XmNminimum
, XM_SB_MIN
); ++ac
;
7603 XtSetArg (av
[ac
], XmNmaximum
, XM_SB_MAX
); ++ac
;
7604 XtSetArg (av
[ac
], XmNorientation
, XmVERTICAL
); ++ac
;
7605 XtSetArg (av
[ac
], XmNprocessingDirection
, XmMAX_ON_BOTTOM
), ++ac
;
7606 XtSetArg (av
[ac
], XmNincrement
, 1); ++ac
;
7607 XtSetArg (av
[ac
], XmNpageIncrement
, 1); ++ac
;
7609 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7612 XtSetArg (av
[ac
], XmNforeground
, pixel
);
7616 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7619 XtSetArg (av
[ac
], XmNbackground
, pixel
);
7623 widget
= XmCreateScrollBar (f
->output_data
.x
->edit_widget
,
7624 scroll_bar_name
, av
, ac
);
7626 /* Add one callback for everything that can happen. */
7627 XtAddCallback (widget
, XmNdecrementCallback
, xm_scroll_callback
,
7629 XtAddCallback (widget
, XmNdragCallback
, xm_scroll_callback
,
7631 XtAddCallback (widget
, XmNincrementCallback
, xm_scroll_callback
,
7633 XtAddCallback (widget
, XmNpageDecrementCallback
, xm_scroll_callback
,
7635 XtAddCallback (widget
, XmNpageIncrementCallback
, xm_scroll_callback
,
7637 XtAddCallback (widget
, XmNtoBottomCallback
, xm_scroll_callback
,
7639 XtAddCallback (widget
, XmNtoTopCallback
, xm_scroll_callback
,
7642 /* Realize the widget. Only after that is the X window created. */
7643 XtRealizeWidget (widget
);
7645 /* Set the cursor to an arrow. I didn't find a resource to do that.
7646 And I'm wondering why it hasn't an arrow cursor by default. */
7647 XDefineCursor (XtDisplay (widget
), XtWindow (widget
),
7648 f
->output_data
.x
->nontext_cursor
);
7650 #else /* !USE_MOTIF i.e. use Xaw */
7652 /* Set resources. Create the widget. The background of the
7653 Xaw3d scroll bar widget is a little bit light for my taste.
7654 We don't alter it here to let users change it according
7655 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7656 XtSetArg (av
[ac
], XtNmappedWhenManaged
, False
); ++ac
;
7657 XtSetArg (av
[ac
], XtNorientation
, XtorientVertical
); ++ac
;
7658 /* For smoother scrolling with Xaw3d -sm */
7659 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7660 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7662 pixel
= f
->output_data
.x
->scroll_bar_foreground_pixel
;
7665 XtSetArg (av
[ac
], XtNforeground
, pixel
);
7669 pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7672 XtSetArg (av
[ac
], XtNbackground
, pixel
);
7676 widget
= XtCreateWidget (scroll_bar_name
, scrollbarWidgetClass
,
7677 f
->output_data
.x
->edit_widget
, av
, ac
);
7681 char *val
= initial
;
7682 XtVaGetValues (widget
, XtNscrollVCursor
, (XtPointer
) &val
,
7683 XtNpickTop
, (XtPointer
) &xaw3d_pick_top
, NULL
);
7685 { /* ARROW_SCROLL */
7686 xaw3d_arrow_scroll
= True
;
7687 /* Isn't that just a personal preference ? -sm */
7688 XtVaSetValues (widget
, XtNcursorName
, "top_left_arrow", NULL
);
7692 /* Define callbacks. */
7693 XtAddCallback (widget
, XtNjumpProc
, xaw_jump_callback
, (XtPointer
) bar
);
7694 XtAddCallback (widget
, XtNscrollProc
, xaw_scroll_callback
,
7697 /* Realize the widget. Only after that is the X window created. */
7698 XtRealizeWidget (widget
);
7700 #endif /* !USE_MOTIF */
7702 /* Install an action hook that let's us detect when the user
7703 finishes interacting with a scroll bar. */
7704 if (action_hook_id
== 0)
7705 action_hook_id
= XtAppAddActionHook (Xt_app_con
, xt_action_hook
, 0);
7707 /* Remember X window and widget in the scroll bar vector. */
7708 SET_SCROLL_BAR_X_WIDGET (bar
, widget
);
7709 xwindow
= XtWindow (widget
);
7710 SET_SCROLL_BAR_X_WINDOW (bar
, xwindow
);
7716 /* Set the thumb size and position of scroll bar BAR. We are currently
7717 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7720 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
7721 struct scroll_bar
*bar
;
7722 int portion
, position
, whole
;
7725 Widget widget
= SCROLL_BAR_X_WIDGET (bar
);
7731 top
= (float) position
/ whole
;
7732 shown
= (float) portion
/ whole
;
7740 Boolean arrow1_selected
, arrow2_selected
;
7741 unsigned char flags
;
7742 XmScrollBarWidget sb
;
7744 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7745 is the scroll bar's maximum and MIN is the scroll bar's minimum
7747 size
= shown
* XM_SB_RANGE
;
7748 size
= min (size
, XM_SB_RANGE
);
7749 size
= max (size
, 1);
7751 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7752 value
= top
* XM_SB_RANGE
;
7753 value
= min (value
, XM_SB_MAX
- size
);
7754 value
= max (value
, XM_SB_MIN
);
7756 /* LessTif: Calling XmScrollBarSetValues after an increment or
7757 decrement turns off auto-repeat LessTif-internally. This can
7758 be seen in ScrollBar.c which resets Arrow1Selected and
7759 Arrow2Selected. It also sets internal flags so that LessTif
7760 believes the mouse is in the slider. We either have to change
7761 our code, or work around that by accessing private data. */
7763 sb
= (XmScrollBarWidget
) widget
;
7764 arrow1_selected
= sb
->scrollBar
.arrow1_selected
;
7765 arrow2_selected
= sb
->scrollBar
.arrow2_selected
;
7766 flags
= sb
->scrollBar
.flags
;
7768 if (NILP (bar
->dragging
))
7769 XmScrollBarSetValues (widget
, value
, size
, 0, 0, False
);
7770 else if (last_scroll_bar_part
== scroll_bar_down_arrow
)
7771 /* This has the negative side effect that the slider value is
7772 not what it would be if we scrolled here using line-wise or
7773 page-wise movement. */
7774 XmScrollBarSetValues (widget
, value
, XM_SB_RANGE
- value
, 0, 0, False
);
7777 /* If currently dragging, only update the slider size.
7778 This reduces flicker effects. */
7779 int old_value
, old_size
, increment
, page_increment
;
7781 XmScrollBarGetValues (widget
, &old_value
, &old_size
,
7782 &increment
, &page_increment
);
7783 XmScrollBarSetValues (widget
, old_value
,
7784 min (size
, XM_SB_RANGE
- old_value
),
7788 sb
->scrollBar
.arrow1_selected
= arrow1_selected
;
7789 sb
->scrollBar
.arrow2_selected
= arrow2_selected
;
7790 sb
->scrollBar
.flags
= flags
;
7792 #else /* !USE_MOTIF i.e. use Xaw */
7794 float old_top
, old_shown
;
7796 XtVaGetValues (widget
,
7797 XtNtopOfThumb
, &old_top
,
7798 XtNshown
, &old_shown
,
7802 /* Massage the top+shown values. */
7803 if (NILP (bar
->dragging
) || last_scroll_bar_part
== scroll_bar_down_arrow
)
7804 top
= max (0, min (1, top
));
7807 /* Keep two pixels available for moving the thumb down. */
7808 shown
= max (0, min (1 - top
- (2.0 / height
), shown
));
7810 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7811 check that your system's configuration file contains a define
7812 for `NARROWPROTO'. See s/freebsd.h for an example. */
7813 if (top
!= old_top
|| shown
!= old_shown
)
7815 if (NILP (bar
->dragging
))
7816 XawScrollbarSetThumb (widget
, top
, shown
);
7820 ScrollbarWidget sb
= (ScrollbarWidget
) widget
;
7823 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7824 if (xaw3d_arrow_scroll
)
7826 /* Xaw3d stupidly ignores resize requests while dragging
7827 so we have to make it believe it's not in dragging mode. */
7828 scroll_mode
= sb
->scrollbar
.scroll_mode
;
7829 if (scroll_mode
== 2)
7830 sb
->scrollbar
.scroll_mode
= 0;
7833 /* Try to make the scrolling a tad smoother. */
7834 if (!xaw3d_pick_top
)
7835 shown
= min (shown
, old_shown
);
7837 XawScrollbarSetThumb (widget
, top
, shown
);
7840 if (xaw3d_arrow_scroll
&& scroll_mode
== 2)
7841 sb
->scrollbar
.scroll_mode
= scroll_mode
;
7846 #endif /* !USE_MOTIF */
7851 #endif /* USE_TOOLKIT_SCROLL_BARS */
7855 /************************************************************************
7856 Scroll bars, general
7857 ************************************************************************/
7859 /* Create a scroll bar and return the scroll bar vector for it. W is
7860 the Emacs window on which to create the scroll bar. TOP, LEFT,
7861 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7864 static struct scroll_bar
*
7865 x_scroll_bar_create (w
, top
, left
, width
, height
)
7867 int top
, left
, width
, height
;
7869 struct frame
*f
= XFRAME (w
->frame
);
7870 struct scroll_bar
*bar
7871 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
7875 #if USE_TOOLKIT_SCROLL_BARS
7876 x_create_toolkit_scroll_bar (f
, bar
);
7877 #else /* not USE_TOOLKIT_SCROLL_BARS */
7879 XSetWindowAttributes a
;
7883 a
.background_pixel
= f
->output_data
.x
->scroll_bar_background_pixel
;
7884 if (a
.background_pixel
== -1)
7885 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
7887 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
7888 | ButtonMotionMask
| PointerMotionHintMask
7890 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
7892 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
7894 /* Clear the area of W that will serve as a scroll bar. This is
7895 for the case that a window has been split horizontally. In
7896 this case, no clear_frame is generated to reduce flickering. */
7897 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7899 window_box_height (w
), False
);
7901 window
= XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
7902 /* Position and size of scroll bar. */
7903 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7905 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7907 /* Border width, depth, class, and visual. */
7914 SET_SCROLL_BAR_X_WINDOW (bar
, window
);
7916 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7918 XSETWINDOW (bar
->window
, w
);
7919 XSETINT (bar
->top
, top
);
7920 XSETINT (bar
->left
, left
);
7921 XSETINT (bar
->width
, width
);
7922 XSETINT (bar
->height
, height
);
7923 XSETINT (bar
->start
, 0);
7924 XSETINT (bar
->end
, 0);
7925 bar
->dragging
= Qnil
;
7927 /* Add bar to its frame's list of scroll bars. */
7928 bar
->next
= FRAME_SCROLL_BARS (f
);
7930 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
7931 if (!NILP (bar
->next
))
7932 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
7934 /* Map the window/widget. */
7935 #if USE_TOOLKIT_SCROLL_BARS
7936 XtMapWidget (SCROLL_BAR_X_WIDGET (bar
));
7937 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
7938 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
7940 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
7942 #else /* not USE_TOOLKIT_SCROLL_BARS */
7943 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
7944 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7951 /* Draw BAR's handle in the proper position.
7953 If the handle is already drawn from START to END, don't bother
7954 redrawing it, unless REBUILD is non-zero; in that case, always
7955 redraw it. (REBUILD is handy for drawing the handle after expose
7958 Normally, we want to constrain the start and end of the handle to
7959 fit inside its rectangle, but if the user is dragging the scroll
7960 bar handle, we want to let them drag it down all the way, so that
7961 the bar's top is as far down as it goes; otherwise, there's no way
7962 to move to the very end of the buffer. */
7964 #ifndef USE_TOOLKIT_SCROLL_BARS
7967 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
7968 struct scroll_bar
*bar
;
7972 int dragging
= ! NILP (bar
->dragging
);
7973 Window w
= SCROLL_BAR_X_WINDOW (bar
);
7974 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
7975 GC gc
= f
->output_data
.x
->normal_gc
;
7977 /* If the display is already accurate, do nothing. */
7979 && start
== XINT (bar
->start
)
7980 && end
== XINT (bar
->end
))
7986 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
7987 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
7988 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
7990 /* Make sure the values are reasonable, and try to preserve
7991 the distance between start and end. */
7993 int length
= end
- start
;
7997 else if (start
> top_range
)
7999 end
= start
+ length
;
8003 else if (end
> top_range
&& ! dragging
)
8007 /* Store the adjusted setting in the scroll bar. */
8008 XSETINT (bar
->start
, start
);
8009 XSETINT (bar
->end
, end
);
8011 /* Clip the end position, just for display. */
8012 if (end
> top_range
)
8015 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8016 below top positions, to make sure the handle is always at least
8017 that many pixels tall. */
8018 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
8020 /* Draw the empty space above the handle. Note that we can't clear
8021 zero-height areas; that means "clear to end of window." */
8023 XClearArea (FRAME_X_DISPLAY (f
), w
,
8025 /* x, y, width, height, and exposures. */
8026 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8027 VERTICAL_SCROLL_BAR_TOP_BORDER
,
8028 inside_width
, start
,
8031 /* Change to proper foreground color if one is specified. */
8032 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8033 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8034 f
->output_data
.x
->scroll_bar_foreground_pixel
);
8036 /* Draw the handle itself. */
8037 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8039 /* x, y, width, height */
8040 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8041 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
8042 inside_width
, end
- start
);
8044 /* Restore the foreground color of the GC if we changed it above. */
8045 if (f
->output_data
.x
->scroll_bar_foreground_pixel
!= -1)
8046 XSetForeground (FRAME_X_DISPLAY (f
), gc
,
8047 f
->output_data
.x
->foreground_pixel
);
8049 /* Draw the empty space below the handle. Note that we can't
8050 clear zero-height areas; that means "clear to end of window." */
8051 if (end
< inside_height
)
8052 XClearArea (FRAME_X_DISPLAY (f
), w
,
8054 /* x, y, width, height, and exposures. */
8055 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
8056 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
8057 inside_width
, inside_height
- end
,
8065 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8067 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8071 x_scroll_bar_remove (bar
)
8072 struct scroll_bar
*bar
;
8076 #if USE_TOOLKIT_SCROLL_BARS
8077 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar
));
8078 #else /* not USE_TOOLKIT_SCROLL_BARS */
8080 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8081 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
8083 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8085 /* Disassociate this scroll bar from its window. */
8086 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
8092 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8093 that we are displaying PORTION characters out of a total of WHOLE
8094 characters, starting at POSITION. If WINDOW has no scroll bar,
8098 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
8100 int portion
, whole
, position
;
8102 struct frame
*f
= XFRAME (w
->frame
);
8103 struct scroll_bar
*bar
;
8104 int top
, height
, left
, sb_left
, width
, sb_width
;
8105 int window_x
, window_y
, window_width
, window_height
;
8107 /* Get window dimensions. */
8108 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
8110 width
= FRAME_SCROLL_BAR_COLS (f
) * CANON_X_UNIT (f
);
8111 height
= window_height
;
8113 /* Compute the left edge of the scroll bar area. */
8114 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8115 left
= XINT (w
->left
) + XINT (w
->width
) - FRAME_SCROLL_BAR_COLS (f
);
8117 left
= XFASTINT (w
->left
);
8118 left
*= CANON_X_UNIT (f
);
8119 left
+= FRAME_INTERNAL_BORDER_WIDTH (f
);
8121 /* Compute the width of the scroll bar which might be less than
8122 the width of the area reserved for the scroll bar. */
8123 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0)
8124 sb_width
= FRAME_SCROLL_BAR_PIXEL_WIDTH (f
);
8128 /* Compute the left edge of the scroll bar. */
8129 #ifdef USE_TOOLKIT_SCROLL_BARS
8130 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8131 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
8133 sb_left
= left
+ (width
- sb_width
) / 2;
8135 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
8136 sb_left
= left
+ width
- sb_width
;
8141 /* Does the scroll bar exist yet? */
8142 if (NILP (w
->vertical_scroll_bar
))
8145 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8146 left
, top
, width
, height
, False
);
8148 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
);
8152 /* It may just need to be moved and resized. */
8153 unsigned int mask
= 0;
8155 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
8159 if (sb_left
!= XINT (bar
->left
))
8161 if (top
!= XINT (bar
->top
))
8163 if (sb_width
!= XINT (bar
->width
))
8165 if (height
!= XINT (bar
->height
))
8168 #ifdef USE_TOOLKIT_SCROLL_BARS
8170 /* Since toolkit scroll bars are smaller than the space reserved
8171 for them on the frame, we have to clear "under" them. */
8172 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8173 left
, top
, width
, height
, False
);
8175 /* Move/size the scroll bar widget. */
8177 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar
),
8178 sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8180 sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
8183 #else /* not USE_TOOLKIT_SCROLL_BARS */
8185 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM
)
8187 /* Clear areas not covered by the scroll bar. This makes sure a
8188 previous mode line display is cleared after C-x 2 C-x 1, for
8189 example. Non-toolkit scroll bars are as wide as the area
8190 reserved for scroll bars - trim at both sides. */
8191 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8192 left
, top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8194 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
8195 left
+ width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8196 top
, VERTICAL_SCROLL_BAR_WIDTH_TRIM
,
8200 /* Move/size the scroll bar window. */
8205 wc
.x
= sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8207 wc
.width
= sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
8209 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
8213 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8215 /* Remember new settings. */
8216 XSETINT (bar
->left
, sb_left
);
8217 XSETINT (bar
->top
, top
);
8218 XSETINT (bar
->width
, sb_width
);
8219 XSETINT (bar
->height
, height
);
8224 #if USE_TOOLKIT_SCROLL_BARS
8225 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
8226 #else /* not USE_TOOLKIT_SCROLL_BARS */
8227 /* Set the scroll bar's current state, unless we're currently being
8229 if (NILP (bar
->dragging
))
8231 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
8234 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
8237 int start
= ((double) position
* top_range
) / whole
;
8238 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
8239 x_scroll_bar_set_handle (bar
, start
, end
, 0);
8242 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8244 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
8248 /* The following three hooks are used when we're doing a thorough
8249 redisplay of the frame. We don't explicitly know which scroll bars
8250 are going to be deleted, because keeping track of when windows go
8251 away is a real pain - "Can you say set-window-configuration, boys
8252 and girls?" Instead, we just assert at the beginning of redisplay
8253 that *all* scroll bars are to be removed, and then save a scroll bar
8254 from the fiery pit when we actually redisplay its window. */
8256 /* Arrange for all scroll bars on FRAME to be removed at the next call
8257 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8258 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8261 XTcondemn_scroll_bars (frame
)
8264 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8265 while (! NILP (FRAME_SCROLL_BARS (frame
)))
8268 bar
= FRAME_SCROLL_BARS (frame
);
8269 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
8270 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
8271 XSCROLL_BAR (bar
)->prev
= Qnil
;
8272 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
8273 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
8274 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
8278 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8279 Note that WINDOW isn't necessarily condemned at all. */
8281 XTredeem_scroll_bar (window
)
8282 struct window
*window
;
8284 struct scroll_bar
*bar
;
8286 /* We can't redeem this window's scroll bar if it doesn't have one. */
8287 if (NILP (window
->vertical_scroll_bar
))
8290 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
8292 /* Unlink it from the condemned list. */
8294 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
8296 if (NILP (bar
->prev
))
8298 /* If the prev pointer is nil, it must be the first in one of
8300 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
8301 /* It's not condemned. Everything's fine. */
8303 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
8304 window
->vertical_scroll_bar
))
8305 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
8307 /* If its prev pointer is nil, it must be at the front of
8308 one or the other! */
8312 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
8314 if (! NILP (bar
->next
))
8315 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
8317 bar
->next
= FRAME_SCROLL_BARS (f
);
8319 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
8320 if (! NILP (bar
->next
))
8321 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
8325 /* Remove all scroll bars on FRAME that haven't been saved since the
8326 last call to `*condemn_scroll_bars_hook'. */
8329 XTjudge_scroll_bars (f
)
8332 Lisp_Object bar
, next
;
8334 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
8336 /* Clear out the condemned list now so we won't try to process any
8337 more events on the hapless scroll bars. */
8338 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
8340 for (; ! NILP (bar
); bar
= next
)
8342 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
8344 x_scroll_bar_remove (b
);
8347 b
->next
= b
->prev
= Qnil
;
8350 /* Now there should be no references to the condemned scroll bars,
8351 and they should get garbage-collected. */
8355 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8356 is a no-op when using toolkit scroll bars.
8358 This may be called from a signal handler, so we have to ignore GC
8362 x_scroll_bar_expose (bar
, event
)
8363 struct scroll_bar
*bar
;
8366 #ifndef USE_TOOLKIT_SCROLL_BARS
8368 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8369 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8370 GC gc
= f
->output_data
.x
->normal_gc
;
8371 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
8375 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
8377 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8378 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
8380 /* x, y, width, height */
8382 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
8383 XINT (bar
->height
) - 1);
8387 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8390 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8391 is set to something other than no_event, it is enqueued.
8393 This may be called from a signal handler, so we have to ignore GC
8396 #ifndef USE_TOOLKIT_SCROLL_BARS
8399 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
8400 struct scroll_bar
*bar
;
8402 struct input_event
*emacs_event
;
8404 if (! GC_WINDOWP (bar
->window
))
8407 emacs_event
->kind
= scroll_bar_click
;
8408 emacs_event
->code
= event
->xbutton
.button
- Button1
;
8409 emacs_event
->modifiers
8410 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8411 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
8412 event
->xbutton
.state
)
8413 | (event
->type
== ButtonRelease
8416 emacs_event
->frame_or_window
= bar
->window
;
8417 emacs_event
->timestamp
= event
->xbutton
.time
;
8420 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8422 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8425 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8426 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
8429 if (y
> top_range
) y
= top_range
;
8431 if (y
< XINT (bar
->start
))
8432 emacs_event
->part
= scroll_bar_above_handle
;
8433 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8434 emacs_event
->part
= scroll_bar_handle
;
8436 emacs_event
->part
= scroll_bar_below_handle
;
8438 /* Just because the user has clicked on the handle doesn't mean
8439 they want to drag it. Lisp code needs to be able to decide
8440 whether or not we're dragging. */
8442 /* If the user has just clicked on the handle, record where they're
8444 if (event
->type
== ButtonPress
8445 && emacs_event
->part
== scroll_bar_handle
)
8446 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
8449 /* If the user has released the handle, set it to its final position. */
8450 if (event
->type
== ButtonRelease
8451 && ! NILP (bar
->dragging
))
8453 int new_start
= y
- XINT (bar
->dragging
);
8454 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8456 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8457 bar
->dragging
= Qnil
;
8460 /* Same deal here as the other #if 0. */
8462 /* Clicks on the handle are always reported as occurring at the top of
8464 if (emacs_event
->part
== scroll_bar_handle
)
8465 emacs_event
->x
= bar
->start
;
8467 XSETINT (emacs_event
->x
, y
);
8469 XSETINT (emacs_event
->x
, y
);
8472 XSETINT (emacs_event
->y
, top_range
);
8476 /* Handle some mouse motion while someone is dragging the scroll bar.
8478 This may be called from a signal handler, so we have to ignore GC
8482 x_scroll_bar_note_movement (bar
, event
)
8483 struct scroll_bar
*bar
;
8486 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
8488 last_mouse_movement_time
= event
->xmotion
.time
;
8491 XSETVECTOR (last_mouse_scroll_bar
, bar
);
8493 /* If we're dragging the bar, display it. */
8494 if (! GC_NILP (bar
->dragging
))
8496 /* Where should the handle be now? */
8497 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
8499 if (new_start
!= XINT (bar
->start
))
8501 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
8503 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
8508 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8510 /* Return information to the user about the current position of the mouse
8511 on the scroll bar. */
8514 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
8516 Lisp_Object
*bar_window
;
8517 enum scroll_bar_part
*part
;
8519 unsigned long *time
;
8521 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
8522 Window w
= SCROLL_BAR_X_WINDOW (bar
);
8523 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
8525 Window dummy_window
;
8527 unsigned int dummy_mask
;
8531 /* Get the mouse's position relative to the scroll bar window, and
8533 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
8535 /* Root, child, root x and root y. */
8536 &dummy_window
, &dummy_window
,
8537 &dummy_coord
, &dummy_coord
,
8539 /* Position relative to scroll bar. */
8542 /* Mouse buttons and modifier keys. */
8549 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
8552 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
8554 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
8556 if (! NILP (bar
->dragging
))
8557 win_y
-= XINT (bar
->dragging
);
8561 if (win_y
> top_range
)
8565 *bar_window
= bar
->window
;
8567 if (! NILP (bar
->dragging
))
8568 *part
= scroll_bar_handle
;
8569 else if (win_y
< XINT (bar
->start
))
8570 *part
= scroll_bar_above_handle
;
8571 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
8572 *part
= scroll_bar_handle
;
8574 *part
= scroll_bar_below_handle
;
8576 XSETINT (*x
, win_y
);
8577 XSETINT (*y
, top_range
);
8580 last_mouse_scroll_bar
= Qnil
;
8583 *time
= last_mouse_movement_time
;
8589 /* The screen has been cleared so we may have changed foreground or
8590 background colors, and the scroll bars may need to be redrawn.
8591 Clear out the scroll bars, and ask for expose events, so we can
8595 x_scroll_bar_clear (f
)
8598 #ifndef USE_TOOLKIT_SCROLL_BARS
8601 /* We can have scroll bars even if this is 0,
8602 if we just turned off scroll bar mode.
8603 But in that case we should not clear them. */
8604 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
8605 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
8606 bar
= XSCROLL_BAR (bar
)->next
)
8607 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
8609 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8612 /* This processes Expose events from the menu-bar specific X event
8613 loop in xmenu.c. This allows to redisplay the frame if necessary
8614 when handling menu-bar or pop-up items. */
8617 process_expose_from_menu (event
)
8621 struct x_display_info
*dpyinfo
;
8622 int frame_exposed_p
= 0;
8626 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
8627 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
8630 if (f
->async_visible
== 0)
8632 f
->async_visible
= 1;
8633 f
->async_iconified
= 0;
8634 f
->output_data
.x
->has_been_visible
= 1;
8635 SET_FRAME_GARBAGED (f
);
8639 expose_frame (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
8640 event
.xexpose
.x
, event
.xexpose
.y
,
8641 event
.xexpose
.width
, event
.xexpose
.height
);
8642 frame_exposed_p
= 1;
8647 struct scroll_bar
*bar
8648 = x_window_to_scroll_bar (event
.xexpose
.window
);
8651 x_scroll_bar_expose (bar
, &event
);
8655 return frame_exposed_p
;
8658 /* Define a queue to save up SelectionRequest events for later handling. */
8660 struct selection_event_queue
8663 struct selection_event_queue
*next
;
8666 static struct selection_event_queue
*queue
;
8668 /* Nonzero means queue up certain events--don't process them yet. */
8670 static int x_queue_selection_requests
;
8672 /* Queue up an X event *EVENT, to be processed later. */
8675 x_queue_event (f
, event
)
8679 struct selection_event_queue
*queue_tmp
8680 = (struct selection_event_queue
*) xmalloc (sizeof (struct selection_event_queue
));
8682 if (queue_tmp
!= NULL
)
8684 queue_tmp
->event
= *event
;
8685 queue_tmp
->next
= queue
;
8690 /* Take all the queued events and put them back
8691 so that they get processed afresh. */
8694 x_unqueue_events (display
)
8697 while (queue
!= NULL
)
8699 struct selection_event_queue
*queue_tmp
= queue
;
8700 XPutBackEvent (display
, &queue_tmp
->event
);
8701 queue
= queue_tmp
->next
;
8702 xfree ((char *)queue_tmp
);
8706 /* Start queuing SelectionRequest events. */
8709 x_start_queuing_selection_requests (display
)
8712 x_queue_selection_requests
++;
8715 /* Stop queuing SelectionRequest events. */
8718 x_stop_queuing_selection_requests (display
)
8721 x_queue_selection_requests
--;
8722 x_unqueue_events (display
);
8725 /* The main X event-reading loop - XTread_socket. */
8727 /* Time stamp of enter window event. This is only used by XTread_socket,
8728 but we have to put it out here, since static variables within functions
8729 sometimes don't work. */
8731 static Time enter_timestamp
;
8733 /* This holds the state XLookupString needs to implement dead keys
8734 and other tricks known as "compose processing". _X Window System_
8735 says that a portable program can't use this, but Stephen Gildea assures
8736 me that letting the compiler initialize it to zeros will work okay.
8738 This must be defined outside of XTread_socket, for the same reasons
8739 given for enter_time stamp, above. */
8741 static XComposeStatus compose_status
;
8743 /* Record the last 100 characters stored
8744 to help debug the loss-of-chars-during-GC problem. */
8746 static int temp_index
;
8747 static short temp_buffer
[100];
8749 /* Set this to nonzero to fake an "X I/O error"
8750 on a particular display. */
8752 struct x_display_info
*XTread_socket_fake_io_error
;
8754 /* When we find no input here, we occasionally do a no-op command
8755 to verify that the X server is still running and we can still talk with it.
8756 We try all the open displays, one by one.
8757 This variable is used for cycling thru the displays. */
8759 static struct x_display_info
*next_noop_dpyinfo
;
8761 #define SET_SAVED_MENU_EVENT(size) \
8764 if (f->output_data.x->saved_menu_event == 0) \
8765 f->output_data.x->saved_menu_event \
8766 = (XEvent *) xmalloc (sizeof (XEvent)); \
8767 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8768 if (numchars >= 1) \
8770 bufp->kind = menu_bar_activate_event; \
8771 XSETFRAME (bufp->frame_or_window, f); \
8779 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8780 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8782 /* Read events coming from the X server.
8783 This routine is called by the SIGIO handler.
8784 We return as soon as there are no more events to be read.
8786 Events representing keys are stored in buffer BUFP,
8787 which can hold up to NUMCHARS characters.
8788 We return the number of characters stored into the buffer,
8789 thus pretending to be `read'.
8791 EXPECTED is nonzero if the caller knows input is available. */
8794 XTread_socket (sd
, bufp
, numchars
, expected
)
8796 /* register */ struct input_event
*bufp
;
8797 /* register */ int numchars
;
8804 int event_found
= 0;
8805 struct x_display_info
*dpyinfo
;
8807 Status status_return
;
8810 if (interrupt_input_blocked
)
8812 interrupt_input_pending
= 1;
8816 interrupt_input_pending
= 0;
8819 /* So people can tell when we have read the available input. */
8820 input_signal_count
++;
8823 abort (); /* Don't think this happens. */
8825 /* Find the display we are supposed to read input for.
8826 It's the one communicating on descriptor SD. */
8827 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
8829 #if 0 /* This ought to be unnecessary; let's verify it. */
8831 /* If available, Xlib uses FIOSNBIO to make the socket
8832 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8833 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8834 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8835 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
8836 #endif /* ! defined (FIOSNBIO) */
8839 #if 0 /* This code can't be made to work, with multiple displays,
8840 and appears not to be used on any system any more.
8841 Also keyboard.c doesn't turn O_NDELAY on and off
8842 for X connections. */
8845 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
8847 extern int read_alarm_should_throw
;
8848 read_alarm_should_throw
= 1;
8849 XPeekEvent (dpyinfo
->display
, &event
);
8850 read_alarm_should_throw
= 0;
8852 #endif /* HAVE_SELECT */
8856 /* For debugging, this gives a way to fake an I/O error. */
8857 if (dpyinfo
== XTread_socket_fake_io_error
)
8859 XTread_socket_fake_io_error
= 0;
8860 x_io_error_quitter (dpyinfo
->display
);
8863 while (XPending (dpyinfo
->display
))
8865 XNextEvent (dpyinfo
->display
, &event
);
8867 if (display_busy_cursor_p
)
8869 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8870 display until the next X event is read and we come
8871 here again. Setting it to 1 inhibits busy-cursor
8872 display for direct commands. */
8873 if (event
.type
== MotionNotify
8874 || event
.type
== EnterNotify
8875 || (dpyinfo
->grabbed
8876 && event
.type
!= ButtonRelease
))
8877 inhibit_busy_cursor
= 2;
8879 inhibit_busy_cursor
= 1;
8884 /* Filter events for the current X input method.
8885 XFilterEvent returns non-zero if the input method has
8886 consumed the event. We pass the frame's X window to
8887 XFilterEvent because that's the one for which the IC
8890 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8893 && XFilterEvent (&event
, FRAME_X_WINDOW (f1
)))
8903 if (event
.xclient
.message_type
8904 == dpyinfo
->Xatom_wm_protocols
8905 && event
.xclient
.format
== 32)
8907 if (event
.xclient
.data
.l
[0]
8908 == dpyinfo
->Xatom_wm_take_focus
)
8910 /* Use x_any_window_to_frame because this
8911 could be the shell widget window
8912 if the frame has no title bar. */
8913 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
8915 /* Not quite sure this is needed -pd */
8916 if (f
&& FRAME_XIC (f
))
8917 XSetICFocus (FRAME_XIC (f
));
8919 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8920 instructs the WM to set the input focus automatically for
8921 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8922 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8923 it has set the focus. So, XSetInputFocus below is not
8926 The call to XSetInputFocus below has also caused trouble. In
8927 cases where the XSetInputFocus done by the WM and the one
8928 below are temporally close (on a fast machine), the call
8929 below can generate additional FocusIn events which confuse
8932 /* Since we set WM_TAKE_FOCUS, we must call
8933 XSetInputFocus explicitly. But not if f is null,
8934 since that might be an event for a deleted frame. */
8937 Display
*d
= event
.xclient
.display
;
8938 /* Catch and ignore errors, in case window has been
8939 iconified by a window manager such as GWM. */
8940 int count
= x_catch_errors (d
);
8941 XSetInputFocus (d
, event
.xclient
.window
,
8942 /* The ICCCM says this is
8943 the only valid choice. */
8945 event
.xclient
.data
.l
[1]);
8946 /* This is needed to detect the error
8947 if there is an error. */
8949 x_uncatch_errors (d
, count
);
8951 /* Not certain about handling scroll bars here */
8954 else if (event
.xclient
.data
.l
[0]
8955 == dpyinfo
->Xatom_wm_save_yourself
)
8957 /* Save state modify the WM_COMMAND property to
8958 something which can reinstate us. This notifies
8959 the session manager, who's looking for such a
8960 PropertyNotify. Can restart processing when
8961 a keyboard or mouse event arrives. */
8964 f
= x_top_window_to_frame (dpyinfo
,
8965 event
.xclient
.window
);
8967 /* This is just so we only give real data once
8968 for a single Emacs process. */
8969 if (f
== SELECTED_FRAME ())
8970 XSetCommand (FRAME_X_DISPLAY (f
),
8971 event
.xclient
.window
,
8972 initial_argv
, initial_argc
);
8974 XSetCommand (FRAME_X_DISPLAY (f
),
8975 event
.xclient
.window
,
8979 else if (event
.xclient
.data
.l
[0]
8980 == dpyinfo
->Xatom_wm_delete_window
)
8983 = x_any_window_to_frame (dpyinfo
,
8984 event
.xclient
.window
);
8991 bufp
->kind
= delete_window_event
;
8992 XSETFRAME (bufp
->frame_or_window
, f
);
9000 else if (event
.xclient
.message_type
9001 == dpyinfo
->Xatom_wm_configure_denied
)
9004 else if (event
.xclient
.message_type
9005 == dpyinfo
->Xatom_wm_window_moved
)
9009 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9011 new_x
= event
.xclient
.data
.s
[0];
9012 new_y
= event
.xclient
.data
.s
[1];
9016 f
->output_data
.x
->left_pos
= new_x
;
9017 f
->output_data
.x
->top_pos
= new_y
;
9021 else if (event
.xclient
.message_type
9022 == dpyinfo
->Xatom_editres
)
9025 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
9026 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
9029 #endif /* HACK_EDITRES */
9030 else if ((event
.xclient
.message_type
9031 == dpyinfo
->Xatom_DONE
)
9032 || (event
.xclient
.message_type
9033 == dpyinfo
->Xatom_PAGE
))
9035 /* Ghostview job completed. Kill it. We could
9036 reply with "Next" if we received "Page", but we
9037 currently never do because we are interested in
9038 images, only, which should have 1 page. */
9039 Pixmap pixmap
= (Pixmap
) event
.xclient
.data
.l
[1];
9041 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
9042 x_kill_gs_process (pixmap
, f
);
9043 expose_frame (f
, 0, 0, 0, 0);
9045 #ifdef USE_TOOLKIT_SCROLL_BARS
9046 /* Scroll bar callbacks send a ClientMessage from which
9047 we construct an input_event. */
9048 else if (event
.xclient
.message_type
9049 == dpyinfo
->Xatom_Scrollbar
)
9051 if (display_busy_cursor_p
)
9052 inhibit_busy_cursor
= 2;
9053 x_scroll_bar_to_input_event (&event
, bufp
);
9054 ++bufp
, ++count
, --numchars
;
9057 #endif /* USE_TOOLKIT_SCROLL_BARS */
9063 case SelectionNotify
:
9064 #ifdef USE_X_TOOLKIT
9065 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
9067 #endif /* not USE_X_TOOLKIT */
9068 x_handle_selection_notify (&event
.xselection
);
9071 case SelectionClear
: /* Someone has grabbed ownership. */
9072 #ifdef USE_X_TOOLKIT
9073 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
9075 #endif /* USE_X_TOOLKIT */
9077 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
9082 bufp
->kind
= selection_clear_event
;
9083 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9084 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9085 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9086 bufp
->frame_or_window
= Qnil
;
9094 case SelectionRequest
: /* Someone wants our selection. */
9095 #ifdef USE_X_TOOLKIT
9096 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
9098 #endif /* USE_X_TOOLKIT */
9099 if (x_queue_selection_requests
)
9100 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
9104 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
9109 bufp
->kind
= selection_request_event
;
9110 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
9111 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
9112 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
9113 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
9114 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
9115 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
9116 bufp
->frame_or_window
= Qnil
;
9124 case PropertyNotify
:
9125 #ifdef USE_X_TOOLKIT
9126 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
9128 #endif /* not USE_X_TOOLKIT */
9129 x_handle_property_notify (&event
.xproperty
);
9132 case ReparentNotify
:
9133 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
9137 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
9138 x_real_positions (f
, &x
, &y
);
9139 f
->output_data
.x
->left_pos
= x
;
9140 f
->output_data
.x
->top_pos
= y
;
9145 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
9148 if (f
->async_visible
== 0)
9150 f
->async_visible
= 1;
9151 f
->async_iconified
= 0;
9152 f
->output_data
.x
->has_been_visible
= 1;
9153 SET_FRAME_GARBAGED (f
);
9156 expose_frame (x_window_to_frame (dpyinfo
,
9157 event
.xexpose
.window
),
9158 event
.xexpose
.x
, event
.xexpose
.y
,
9159 event
.xexpose
.width
, event
.xexpose
.height
);
9163 #ifdef USE_TOOLKIT_SCROLL_BARS
9164 /* Dispatch event to the widget. */
9166 #else /* not USE_TOOLKIT_SCROLL_BARS */
9167 struct scroll_bar
*bar
9168 = x_window_to_scroll_bar (event
.xexpose
.window
);
9171 x_scroll_bar_expose (bar
, &event
);
9172 #ifdef USE_X_TOOLKIT
9175 #endif /* USE_X_TOOLKIT */
9176 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9180 case GraphicsExpose
: /* This occurs when an XCopyArea's
9181 source area was obscured or not
9183 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
9187 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
9188 event
.xgraphicsexpose
.width
,
9189 event
.xgraphicsexpose
.height
);
9191 #ifdef USE_X_TOOLKIT
9194 #endif /* USE_X_TOOLKIT */
9197 case NoExpose
: /* This occurs when an XCopyArea's
9198 source area was completely
9203 /* Redo the mouse-highlight after the tooltip has gone. */
9204 if (event
.xmap
.window
== tip_window
)
9207 redo_mouse_highlight ();
9210 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
9211 if (f
) /* F may no longer exist if
9212 the frame was deleted. */
9214 /* While a frame is unmapped, display generation is
9215 disabled; you don't want to spend time updating a
9216 display that won't ever be seen. */
9217 f
->async_visible
= 0;
9218 /* We can't distinguish, from the event, whether the window
9219 has become iconified or invisible. So assume, if it
9220 was previously visible, than now it is iconified.
9221 But x_make_frame_invisible clears both
9222 the visible flag and the iconified flag;
9223 and that way, we know the window is not iconified now. */
9224 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
9226 f
->async_iconified
= 1;
9228 bufp
->kind
= iconify_event
;
9229 XSETFRAME (bufp
->frame_or_window
, f
);
9238 if (event
.xmap
.window
== tip_window
)
9239 /* The tooltip has been drawn already. Avoid
9240 the SET_FRAME_GARBAGED below. */
9243 /* We use x_top_window_to_frame because map events can
9244 come for sub-windows and they don't mean that the
9245 frame is visible. */
9246 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
9249 f
->async_visible
= 1;
9250 f
->async_iconified
= 0;
9251 f
->output_data
.x
->has_been_visible
= 1;
9253 /* wait_reading_process_input will notice this and update
9254 the frame's display structures. */
9255 SET_FRAME_GARBAGED (f
);
9259 bufp
->kind
= deiconify_event
;
9260 XSETFRAME (bufp
->frame_or_window
, f
);
9265 else if (! NILP (Vframe_list
)
9266 && ! NILP (XCDR (Vframe_list
)))
9267 /* Force a redisplay sooner or later
9268 to update the frame titles
9269 in case this is the second frame. */
9270 record_asynch_buffer_change ();
9275 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
9278 /* I couldn't find a way to prevent LessTif scroll bars
9279 from consuming key events. */
9282 Widget widget
= XtWindowToWidget (dpyinfo
->display
,
9284 if (widget
&& XmIsScrollBar (widget
))
9286 widget
= XtParent (widget
);
9287 f
= x_any_window_to_frame (dpyinfo
, XtWindow (widget
));
9290 #endif /* USE_MOTIF */
9294 KeySym keysym
, orig_keysym
;
9295 /* al%imercury@uunet.uu.net says that making this 81 instead of
9296 80 fixed a bug whereby meta chars made his Emacs hang. */
9297 unsigned char copy_buffer
[81];
9301 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
9302 extra_keyboard_modifiers
);
9303 modifiers
= event
.xkey
.state
;
9305 /* This will have to go some day... */
9307 /* make_lispy_event turns chars into control chars.
9308 Don't do it here because XLookupString is too eager. */
9309 event
.xkey
.state
&= ~ControlMask
;
9310 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
9311 | dpyinfo
->super_mod_mask
9312 | dpyinfo
->hyper_mod_mask
9313 | dpyinfo
->alt_mod_mask
);
9315 /* In case Meta is ComposeCharacter,
9316 clear its status. According to Markus Ehrnsperger
9317 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9318 this enables ComposeCharacter to work whether or
9319 not it is combined with Meta. */
9320 if (modifiers
& dpyinfo
->meta_mod_mask
)
9321 bzero (&compose_status
, sizeof (compose_status
));
9326 nbytes
= XmbLookupString (FRAME_XIC (f
),
9327 &event
.xkey
, copy_buffer
,
9330 if (status_return
== XLookupNone
)
9332 else if (status_return
== XLookupChars
)
9334 else if (status_return
!= XLookupKeySym
9335 && status_return
!= XLookupBoth
)
9339 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9340 80, &keysym
, &compose_status
);
9342 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
9343 80, &keysym
, &compose_status
);
9346 orig_keysym
= keysym
;
9350 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
9351 || keysym
== XK_Delete
9352 #ifdef XK_ISO_Left_Tab
9353 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
9355 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
9356 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
9357 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
9359 /* This recognizes the "extended function keys".
9360 It seems there's no cleaner way.
9361 Test IsModifierKey to avoid handling mode_switch
9363 || ((unsigned) (keysym
) >= XK_Select
9364 && (unsigned)(keysym
) < XK_KP_Space
)
9366 #ifdef XK_dead_circumflex
9367 || orig_keysym
== XK_dead_circumflex
9369 #ifdef XK_dead_grave
9370 || orig_keysym
== XK_dead_grave
9372 #ifdef XK_dead_tilde
9373 || orig_keysym
== XK_dead_tilde
9375 #ifdef XK_dead_diaeresis
9376 || orig_keysym
== XK_dead_diaeresis
9378 #ifdef XK_dead_macron
9379 || orig_keysym
== XK_dead_macron
9381 #ifdef XK_dead_degree
9382 || orig_keysym
== XK_dead_degree
9384 #ifdef XK_dead_acute
9385 || orig_keysym
== XK_dead_acute
9387 #ifdef XK_dead_cedilla
9388 || orig_keysym
== XK_dead_cedilla
9390 #ifdef XK_dead_breve
9391 || orig_keysym
== XK_dead_breve
9393 #ifdef XK_dead_ogonek
9394 || orig_keysym
== XK_dead_ogonek
9396 #ifdef XK_dead_caron
9397 || orig_keysym
== XK_dead_caron
9399 #ifdef XK_dead_doubleacute
9400 || orig_keysym
== XK_dead_doubleacute
9402 #ifdef XK_dead_abovedot
9403 || orig_keysym
== XK_dead_abovedot
9405 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
9406 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
9407 /* Any "vendor-specific" key is ok. */
9408 || (orig_keysym
& (1 << 28)))
9409 && ! (IsModifierKey (orig_keysym
)
9411 #ifdef XK_Mode_switch
9412 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
9415 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
9417 #endif /* not HAVE_X11R5 */
9420 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9422 temp_buffer
[temp_index
++] = keysym
;
9423 bufp
->kind
= non_ascii_keystroke
;
9424 bufp
->code
= keysym
;
9425 XSETFRAME (bufp
->frame_or_window
, f
);
9427 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9429 bufp
->timestamp
= event
.xkey
.time
;
9434 if (display_busy_cursor_p
)
9435 if (keysym
!= XK_Return
|| minibuf_level
== 0)
9436 inhibit_busy_cursor
= 2;
9438 else if (numchars
> nbytes
)
9442 for (i
= 0; i
< nbytes
; i
++)
9444 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
9446 temp_buffer
[temp_index
++] = copy_buffer
[i
];
9447 bufp
->kind
= ascii_keystroke
;
9448 bufp
->code
= copy_buffer
[i
];
9449 XSETFRAME (bufp
->frame_or_window
, f
);
9451 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
9453 bufp
->timestamp
= event
.xkey
.time
;
9460 if (keysym
== NoSymbol
)
9471 /* Here's a possible interpretation of the whole
9472 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9473 you get a FocusIn event, you have to get a FocusOut
9474 event before you relinquish the focus. If you
9475 haven't received a FocusIn event, then a mere
9476 LeaveNotify is enough to free you. */
9480 int from_menu_bar_p
= 0;
9482 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9484 #ifdef LESSTIF_VERSION
9485 /* When clicking outside of a menu bar popup to close
9486 it, we get a FocusIn/ EnterNotify sequence of
9487 events. The flag event.xcrossing.focus is not set
9488 in the EnterNotify event of that sequence because
9489 the focus is in the menu bar,
9490 event.xcrossing.window is the frame's X window.
9491 Unconditionally setting the focus frame to null in
9492 this case is not the right thing, because no event
9493 follows that could set the focus frame to the right
9496 This could be a LessTif bug, but I wasn't able to
9497 reproduce the behavior in a simple test program.
9499 (gerd, LessTif 0.88.1). */
9501 if (!event
.xcrossing
.focus
9503 && f
->output_data
.x
->menubar_widget
)
9508 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9509 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9510 from_menu_bar_p
= 1;
9512 #endif /* LESSTIF_VERSION */
9514 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9516 /* Avoid nasty pop/raise loops. */
9517 if (f
&& (!(f
->auto_raise
)
9519 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
9521 x_new_focus_frame (dpyinfo
, f
);
9522 enter_timestamp
= event
.xcrossing
.time
;
9525 else if (f
== dpyinfo
->x_focus_frame
)
9526 x_new_focus_frame (dpyinfo
, 0);
9528 /* EnterNotify counts as mouse movement,
9529 so update things that depend on mouse position. */
9530 if (f
&& !f
->output_data
.x
->busy_p
)
9531 note_mouse_movement (f
, &event
.xmotion
);
9536 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9537 if (event
.xfocus
.detail
!= NotifyPointer
)
9538 dpyinfo
->x_focus_event_frame
= f
;
9540 x_new_focus_frame (dpyinfo
, f
);
9543 if (f
&& FRAME_XIC (f
))
9544 XSetICFocus (FRAME_XIC (f
));
9550 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
9554 int from_menu_bar_p
= 0;
9556 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9558 /* If we move outside the frame, then we're
9559 certainly no longer on any text in the frame. */
9560 clear_mouse_face (dpyinfo
);
9561 dpyinfo
->mouse_face_mouse_frame
= 0;
9564 /* Generate a nil HELP_EVENT to cancel a help-echo.
9565 Do it only if there's something to cancel.
9566 Otherwise, the startup message is cleared when
9567 the mouse leaves the frame. */
9568 if (any_help_event_p
)
9570 XSETFRAME (frame
, f
);
9571 bufp
->kind
= HELP_EVENT
;
9572 bufp
->frame_or_window
= Fcons (frame
, Qnil
);
9573 ++bufp
, ++count
, --numchars
;
9576 #ifdef LESSTIF_VERSION
9577 /* Please see the comment at the start of the
9578 EnterNotify case. */
9579 if (!event
.xcrossing
.focus
9580 && f
->output_data
.x
->menubar_widget
)
9584 XGetInputFocus (FRAME_X_DISPLAY (f
), &focus
, &revert
);
9585 if (focus
== XtWindow (f
->output_data
.x
->menubar_widget
))
9586 from_menu_bar_p
= 1;
9588 #endif /* LESSTIF_VERSION */
9590 if (event
.xcrossing
.focus
|| from_menu_bar_p
)
9591 x_mouse_leave (dpyinfo
);
9594 if (f
== dpyinfo
->x_focus_event_frame
)
9595 dpyinfo
->x_focus_event_frame
= 0;
9596 if (f
== dpyinfo
->x_focus_frame
)
9597 x_new_focus_frame (dpyinfo
, 0);
9603 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
9604 if (event
.xfocus
.detail
!= NotifyPointer
9605 && f
== dpyinfo
->x_focus_event_frame
)
9606 dpyinfo
->x_focus_event_frame
= 0;
9607 if (f
&& f
== dpyinfo
->x_focus_frame
)
9608 x_new_focus_frame (dpyinfo
, 0);
9611 if (f
&& FRAME_XIC (f
))
9612 XUnsetICFocus (FRAME_XIC (f
));
9619 previous_help_echo
= help_echo
;
9622 if (dpyinfo
->grabbed
&& last_mouse_frame
9623 && FRAME_LIVE_P (last_mouse_frame
))
9624 f
= last_mouse_frame
;
9626 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
9629 note_mouse_movement (f
, &event
.xmotion
);
9632 #ifndef USE_TOOLKIT_SCROLL_BARS
9633 struct scroll_bar
*bar
9634 = x_window_to_scroll_bar (event
.xmotion
.window
);
9637 x_scroll_bar_note_movement (bar
, &event
);
9638 #endif /* USE_TOOLKIT_SCROLL_BARS */
9640 /* If we move outside the frame, then we're
9641 certainly no longer on any text in the frame. */
9642 clear_mouse_face (dpyinfo
);
9645 /* If the contents of the global variable help_echo
9646 has changed, generate a HELP_EVENT. */
9647 if (STRINGP (help_echo
)
9648 || STRINGP (previous_help_echo
))
9653 XSETFRAME (frame
, f
);
9657 any_help_event_p
= 1;
9658 bufp
->kind
= HELP_EVENT
;
9659 bufp
->frame_or_window
= Fcons (frame
, help_echo
);
9660 ++bufp
, ++count
, --numchars
;
9666 case ConfigureNotify
:
9667 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
9670 #ifndef USE_X_TOOLKIT
9671 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
9672 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
9674 /* In the toolkit version, change_frame_size
9675 is called by the code that handles resizing
9676 of the EmacsFrame widget. */
9678 /* Even if the number of character rows and columns has
9679 not changed, the font size may have changed, so we need
9680 to check the pixel dimensions as well. */
9681 if (columns
!= f
->width
9682 || rows
!= f
->height
9683 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
9684 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
9686 change_frame_size (f
, rows
, columns
, 0, 1, 0);
9687 SET_FRAME_GARBAGED (f
);
9688 cancel_mouse_face (f
);
9692 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
9693 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
9695 /* What we have now is the position of Emacs's own window.
9696 Convert that to the position of the window manager window. */
9697 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
9698 &f
->output_data
.x
->top_pos
);
9700 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
9702 /* Since the WM decorations come below top_pos now,
9703 we must put them below top_pos in the future. */
9704 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
9705 x_wm_set_size_hint (f
, (long) 0, 0);
9708 /* Some window managers pass (0,0) as the location of
9709 the window, and the Motif event handler stores it
9710 in the emacs widget, which messes up Motif menus. */
9711 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
9713 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
9714 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
9716 #endif /* USE_MOTIF */
9723 /* If we decide we want to generate an event to be seen
9724 by the rest of Emacs, we put it here. */
9725 struct input_event emacs_event
;
9728 emacs_event
.kind
= no_event
;
9729 bzero (&compose_status
, sizeof (compose_status
));
9731 if (dpyinfo
->grabbed
9733 && FRAME_LIVE_P (last_mouse_frame
))
9734 f
= last_mouse_frame
;
9736 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9740 /* Is this in the tool-bar? */
9741 if (WINDOWP (f
->tool_bar_window
)
9742 && XFASTINT (XWINDOW (f
->tool_bar_window
)->height
))
9747 x
= event
.xbutton
.x
;
9748 y
= event
.xbutton
.y
;
9751 window
= window_from_coordinates (f
, x
, y
, &p
, 1);
9752 if (EQ (window
, f
->tool_bar_window
))
9754 x_handle_tool_bar_click (f
, &event
.xbutton
);
9760 if (!dpyinfo
->x_focus_frame
9761 || f
== dpyinfo
->x_focus_frame
)
9762 construct_mouse_click (&emacs_event
, &event
, f
);
9766 #ifndef USE_TOOLKIT_SCROLL_BARS
9767 struct scroll_bar
*bar
9768 = x_window_to_scroll_bar (event
.xbutton
.window
);
9771 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
9772 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9775 if (event
.type
== ButtonPress
)
9777 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
9778 last_mouse_frame
= f
;
9779 /* Ignore any mouse motion that happened
9780 before this event; any subsequent mouse-movement
9781 Emacs events should reflect only motion after
9787 last_tool_bar_item
= -1;
9788 if (display_busy_cursor_p
)
9789 inhibit_busy_cursor
= 2;
9793 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
9796 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
9798 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
9804 #ifdef USE_X_TOOLKIT
9805 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
9806 /* For a down-event in the menu bar,
9807 don't pass it to Xt right now.
9808 Instead, save it away
9809 and we will pass it to Xt from kbd_buffer_get_event.
9810 That way, we can run some Lisp code first. */
9811 if (f
&& event
.type
== ButtonPress
9812 /* Verify the event is really within the menu bar
9813 and not just sent to it due to grabbing. */
9814 && event
.xbutton
.x
>= 0
9815 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
9816 && event
.xbutton
.y
>= 0
9817 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
9818 && event
.xbutton
.same_screen
)
9820 SET_SAVED_BUTTON_EVENT
;
9821 XSETFRAME (last_mouse_press_frame
, f
);
9823 else if (event
.type
== ButtonPress
)
9825 last_mouse_press_frame
= Qnil
;
9829 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9830 but I am trying to be cautious. */
9831 else if (event
.type
== ButtonRelease
)
9833 if (!NILP (last_mouse_press_frame
))
9835 f
= XFRAME (last_mouse_press_frame
);
9836 if (f
->output_data
.x
)
9837 SET_SAVED_BUTTON_EVENT
;
9842 #endif /* USE_MOTIF */
9845 #endif /* USE_X_TOOLKIT */
9849 case CirculateNotify
:
9852 case CirculateRequest
:
9855 case VisibilityNotify
:
9859 /* Someone has changed the keyboard mapping - update the
9861 switch (event
.xmapping
.request
)
9863 case MappingModifier
:
9864 x_find_modifier_meanings (dpyinfo
);
9865 /* This is meant to fall through. */
9866 case MappingKeyboard
:
9867 XRefreshKeyboardMapping (&event
.xmapping
);
9873 #ifdef USE_X_TOOLKIT
9875 XtDispatchEvent (&event
);
9877 #endif /* USE_X_TOOLKIT */
9885 /* On some systems, an X bug causes Emacs to get no more events
9886 when the window is destroyed. Detect that. (1994.) */
9889 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9890 One XNOOP in 100 loops will make Emacs terminate.
9891 B. Bretthauer, 1994 */
9893 if (x_noop_count
>= 100)
9897 if (next_noop_dpyinfo
== 0)
9898 next_noop_dpyinfo
= x_display_list
;
9900 XNoOp (next_noop_dpyinfo
->display
);
9902 /* Each time we get here, cycle through the displays now open. */
9903 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
9907 /* If the focus was just given to an auto-raising frame,
9909 /* ??? This ought to be able to handle more than one such frame. */
9910 if (pending_autoraise_frame
)
9912 x_raise_frame (pending_autoraise_frame
);
9913 pending_autoraise_frame
= 0;
9923 /***********************************************************************
9925 ***********************************************************************/
9927 /* Note if the text cursor of window W has been overwritten by a
9928 drawing operation that outputs N glyphs starting at HPOS in the
9929 line given by output_cursor.vpos. N < 0 means all the rest of the
9930 line after HPOS has been written. */
9933 note_overwritten_text_cursor (w
, hpos
, n
)
9937 if (updated_area
== TEXT_AREA
9938 && output_cursor
.vpos
== w
->phys_cursor
.vpos
9939 && hpos
<= w
->phys_cursor
.hpos
9941 || hpos
+ n
> w
->phys_cursor
.hpos
))
9942 w
->phys_cursor_on_p
= 0;
9946 /* Set clipping for output in glyph row ROW. W is the window in which
9947 we operate. GC is the graphics context to set clipping in.
9948 WHOLE_LINE_P non-zero means include the areas used for truncation
9949 mark display and alike in the clipping rectangle.
9951 ROW may be a text row or, e.g., a mode line. Text rows must be
9952 clipped to the interior of the window dedicated to text display,
9953 mode lines must be clipped to the whole window. */
9956 x_clip_to_row (w
, row
, gc
, whole_line_p
)
9958 struct glyph_row
*row
;
9962 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9963 XRectangle clip_rect
;
9964 int window_x
, window_y
, window_width
, window_height
;
9966 window_box (w
, -1, &window_x
, &window_y
, &window_width
, &window_height
);
9968 clip_rect
.x
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
9969 clip_rect
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
9970 clip_rect
.y
= max (clip_rect
.y
, window_y
);
9971 clip_rect
.width
= window_width
;
9972 clip_rect
.height
= row
->visible_height
;
9974 /* If clipping to the whole line, including trunc marks, extend
9975 the rectangle to the left and increase its width. */
9978 clip_rect
.x
-= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f
);
9979 clip_rect
.width
+= FRAME_X_FLAGS_AREA_WIDTH (f
);
9982 XSetClipRectangles (FRAME_X_DISPLAY (f
), gc
, 0, 0, &clip_rect
, 1, Unsorted
);
9986 /* Draw a hollow box cursor on window W in glyph row ROW. */
9989 x_draw_hollow_cursor (w
, row
)
9991 struct glyph_row
*row
;
9993 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
9994 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
9995 Display
*dpy
= FRAME_X_DISPLAY (f
);
9998 struct glyph
*cursor_glyph
;
10001 /* Compute frame-relative coordinates from window-relative
10003 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10004 y
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
)
10005 + row
->ascent
- w
->phys_cursor_ascent
);
10006 h
= row
->height
- 1;
10008 /* Get the glyph the cursor is on. If we can't tell because
10009 the current matrix is invalid or such, give up. */
10010 cursor_glyph
= get_phys_cursor_glyph (w
);
10011 if (cursor_glyph
== NULL
)
10014 /* Compute the width of the rectangle to draw. If on a stretch
10015 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10016 rectangle as wide as the glyph, but use a canonical character
10018 wd
= cursor_glyph
->pixel_width
- 1;
10019 if (cursor_glyph
->type
== STRETCH_GLYPH
10020 && !x_stretch_cursor_p
)
10021 wd
= min (CANON_X_UNIT (f
), wd
);
10023 /* The foreground of cursor_gc is typically the same as the normal
10024 background color, which can cause the cursor box to be invisible. */
10025 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10026 if (dpyinfo
->scratch_cursor_gc
)
10027 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
10029 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_X_WINDOW (f
),
10030 GCForeground
, &xgcv
);
10031 gc
= dpyinfo
->scratch_cursor_gc
;
10033 /* Set clipping, draw the rectangle, and reset clipping again. */
10034 x_clip_to_row (w
, row
, gc
, 0);
10035 XDrawRectangle (dpy
, FRAME_X_WINDOW (f
), gc
, x
, y
, wd
, h
);
10036 XSetClipMask (dpy
, gc
, None
);
10040 /* Draw a bar cursor on window W in glyph row ROW.
10042 Implementation note: One would like to draw a bar cursor with an
10043 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10044 Unfortunately, I didn't find a font yet that has this property set.
10048 x_draw_bar_cursor (w
, row
)
10050 struct glyph_row
*row
;
10052 /* If cursor hpos is out of bounds, don't draw garbage. This can
10053 happen in mini-buffer windows when switching between echo area
10054 glyphs and mini-buffer. */
10055 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10057 struct frame
*f
= XFRAME (w
->frame
);
10058 struct glyph
*cursor_glyph
;
10061 unsigned long mask
;
10066 cursor_glyph
= get_phys_cursor_glyph (w
);
10067 if (cursor_glyph
== NULL
)
10070 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
10071 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
10072 xgcv
.graphics_exposures
= 0;
10073 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
10074 dpy
= FRAME_X_DISPLAY (f
);
10075 window
= FRAME_X_WINDOW (f
);
10076 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
10079 XChangeGC (dpy
, gc
, mask
, &xgcv
);
10082 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
10083 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
10086 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
10087 x_clip_to_row (w
, row
, gc
, 0);
10088 XFillRectangle (dpy
, window
, gc
,
10090 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
10091 min (cursor_glyph
->pixel_width
,
10092 f
->output_data
.x
->cursor_width
),
10094 XSetClipMask (dpy
, gc
, None
);
10099 /* Clear the cursor of window W to background color, and mark the
10100 cursor as not shown. This is used when the text where the cursor
10101 is is about to be rewritten. */
10107 if (FRAME_VISIBLE_P (XFRAME (w
->frame
)) && w
->phys_cursor_on_p
)
10108 x_update_window_cursor (w
, 0);
10112 /* Draw the cursor glyph of window W in glyph row ROW. See the
10113 comment of x_draw_glyphs for the meaning of HL. */
10116 x_draw_phys_cursor_glyph (w
, row
, hl
)
10118 struct glyph_row
*row
;
10119 enum draw_glyphs_face hl
;
10121 /* If cursor hpos is out of bounds, don't draw garbage. This can
10122 happen in mini-buffer windows when switching between echo area
10123 glyphs and mini-buffer. */
10124 if (w
->phys_cursor
.hpos
< row
->used
[TEXT_AREA
])
10126 x_draw_glyphs (w
, w
->phys_cursor
.x
, row
, TEXT_AREA
,
10127 w
->phys_cursor
.hpos
, w
->phys_cursor
.hpos
+ 1,
10130 /* When we erase the cursor, and ROW is overlapped by other
10131 rows, make sure that these overlapping parts of other rows
10133 if (hl
== DRAW_NORMAL_TEXT
&& row
->overlapped_p
)
10135 if (row
> w
->current_matrix
->rows
10136 && MATRIX_ROW_OVERLAPS_SUCC_P (row
- 1))
10137 x_fix_overlapping_area (w
, row
- 1, TEXT_AREA
);
10139 if (MATRIX_ROW_BOTTOM_Y (row
) < window_text_bottom_y (w
)
10140 && MATRIX_ROW_OVERLAPS_PRED_P (row
+ 1))
10141 x_fix_overlapping_area (w
, row
+ 1, TEXT_AREA
);
10147 /* Erase the image of a cursor of window W from the screen. */
10150 x_erase_phys_cursor (w
)
10153 struct frame
*f
= XFRAME (w
->frame
);
10154 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
10155 int hpos
= w
->phys_cursor
.hpos
;
10156 int vpos
= w
->phys_cursor
.vpos
;
10157 int mouse_face_here_p
= 0;
10158 struct glyph_matrix
*active_glyphs
= w
->current_matrix
;
10159 struct glyph_row
*cursor_row
;
10160 struct glyph
*cursor_glyph
;
10161 enum draw_glyphs_face hl
;
10163 /* No cursor displayed or row invalidated => nothing to do on the
10165 if (w
->phys_cursor_type
== NO_CURSOR
)
10166 goto mark_cursor_off
;
10168 /* VPOS >= active_glyphs->nrows means that window has been resized.
10169 Don't bother to erase the cursor. */
10170 if (vpos
>= active_glyphs
->nrows
)
10171 goto mark_cursor_off
;
10173 /* If row containing cursor is marked invalid, there is nothing we
10175 cursor_row
= MATRIX_ROW (active_glyphs
, vpos
);
10176 if (!cursor_row
->enabled_p
)
10177 goto mark_cursor_off
;
10179 /* This can happen when the new row is shorter than the old one.
10180 In this case, either x_draw_glyphs or clear_end_of_line
10181 should have cleared the cursor. Note that we wouldn't be
10182 able to erase the cursor in this case because we don't have a
10183 cursor glyph at hand. */
10184 if (w
->phys_cursor
.hpos
>= cursor_row
->used
[TEXT_AREA
])
10185 goto mark_cursor_off
;
10187 /* If the cursor is in the mouse face area, redisplay that when
10188 we clear the cursor. */
10189 if (w
== XWINDOW (dpyinfo
->mouse_face_window
)
10190 && (vpos
> dpyinfo
->mouse_face_beg_row
10191 || (vpos
== dpyinfo
->mouse_face_beg_row
10192 && hpos
>= dpyinfo
->mouse_face_beg_col
))
10193 && (vpos
< dpyinfo
->mouse_face_end_row
10194 || (vpos
== dpyinfo
->mouse_face_end_row
10195 && hpos
< dpyinfo
->mouse_face_end_col
))
10196 /* Don't redraw the cursor's spot in mouse face if it is at the
10197 end of a line (on a newline). The cursor appears there, but
10198 mouse highlighting does not. */
10199 && cursor_row
->used
[TEXT_AREA
] > hpos
)
10200 mouse_face_here_p
= 1;
10202 /* Maybe clear the display under the cursor. */
10203 if (w
->phys_cursor_type
== HOLLOW_BOX_CURSOR
)
10206 int header_line_height
= WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w
);
10208 cursor_glyph
= get_phys_cursor_glyph (w
);
10209 if (cursor_glyph
== NULL
)
10210 goto mark_cursor_off
;
10212 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
10214 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
10216 WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
,
10218 cursor_glyph
->pixel_width
,
10219 cursor_row
->visible_height
,
10223 /* Erase the cursor by redrawing the character underneath it. */
10224 if (mouse_face_here_p
)
10225 hl
= DRAW_MOUSE_FACE
;
10226 else if (cursor_row
->inverse_p
)
10227 hl
= DRAW_INVERSE_VIDEO
;
10229 hl
= DRAW_NORMAL_TEXT
;
10230 x_draw_phys_cursor_glyph (w
, cursor_row
, hl
);
10233 w
->phys_cursor_on_p
= 0;
10234 w
->phys_cursor_type
= NO_CURSOR
;
10238 /* Display or clear cursor of window W. If ON is zero, clear the
10239 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10240 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10243 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
)
10245 int on
, hpos
, vpos
, x
, y
;
10247 struct frame
*f
= XFRAME (w
->frame
);
10248 int new_cursor_type
;
10249 struct glyph_matrix
*current_glyphs
;
10250 struct glyph_row
*glyph_row
;
10251 struct glyph
*glyph
;
10253 /* This is pointless on invisible frames, and dangerous on garbaged
10254 windows and frames; in the latter case, the frame or window may
10255 be in the midst of changing its size, and x and y may be off the
10257 if (! FRAME_VISIBLE_P (f
)
10258 || FRAME_GARBAGED_P (f
)
10259 || vpos
>= w
->current_matrix
->nrows
10260 || hpos
>= w
->current_matrix
->matrix_w
)
10263 /* If cursor is off and we want it off, return quickly. */
10264 if (!on
&& !w
->phys_cursor_on_p
)
10267 current_glyphs
= w
->current_matrix
;
10268 glyph_row
= MATRIX_ROW (current_glyphs
, vpos
);
10269 glyph
= glyph_row
->glyphs
[TEXT_AREA
] + hpos
;
10271 /* If cursor row is not enabled, we don't really know where to
10272 display the cursor. */
10273 if (!glyph_row
->enabled_p
)
10275 w
->phys_cursor_on_p
= 0;
10279 xassert (interrupt_input_blocked
);
10281 /* Set new_cursor_type to the cursor we want to be displayed. In a
10282 mini-buffer window, we want the cursor only to appear if we are
10283 reading input from this window. For the selected window, we want
10284 the cursor type given by the frame parameter. If explicitly
10285 marked off, draw no cursor. In all other cases, we want a hollow
10287 if (cursor_in_echo_area
10288 && FRAME_HAS_MINIBUF_P (f
)
10289 && EQ (FRAME_MINIBUF_WINDOW (f
), echo_area_window
))
10291 if (w
== XWINDOW (echo_area_window
))
10292 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10294 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10298 if (w
!= XWINDOW (selected_window
)
10299 || f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
10301 if (MINI_WINDOW_P (w
))
10302 new_cursor_type
= NO_CURSOR
;
10304 new_cursor_type
= HOLLOW_BOX_CURSOR
;
10306 else if (w
->cursor_off_p
)
10307 new_cursor_type
= NO_CURSOR
;
10309 new_cursor_type
= FRAME_DESIRED_CURSOR (f
);
10312 /* If cursor is currently being shown and we don't want it to be or
10313 it is in the wrong place, or the cursor type is not what we want,
10315 if (w
->phys_cursor_on_p
10317 || w
->phys_cursor
.x
!= x
10318 || w
->phys_cursor
.y
!= y
10319 || new_cursor_type
!= w
->phys_cursor_type
))
10320 x_erase_phys_cursor (w
);
10322 /* If the cursor is now invisible and we want it to be visible,
10324 if (on
&& !w
->phys_cursor_on_p
)
10326 w
->phys_cursor_ascent
= glyph_row
->ascent
;
10327 w
->phys_cursor_height
= glyph_row
->height
;
10329 /* Set phys_cursor_.* before x_draw_.* is called because some
10330 of them may need the information. */
10331 w
->phys_cursor
.x
= x
;
10332 w
->phys_cursor
.y
= glyph_row
->y
;
10333 w
->phys_cursor
.hpos
= hpos
;
10334 w
->phys_cursor
.vpos
= vpos
;
10335 w
->phys_cursor_type
= new_cursor_type
;
10336 w
->phys_cursor_on_p
= 1;
10338 switch (new_cursor_type
)
10340 case HOLLOW_BOX_CURSOR
:
10341 x_draw_hollow_cursor (w
, glyph_row
);
10344 case FILLED_BOX_CURSOR
:
10345 x_draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
10349 x_draw_bar_cursor (w
, glyph_row
);
10361 if (updating_frame
!= f
)
10362 XFlush (FRAME_X_DISPLAY (f
));
10367 /* Display the cursor on window W, or clear it. X and Y are window
10368 relative pixel coordinates. HPOS and VPOS are glyph matrix
10369 positions. If W is not the selected window, display a hollow
10370 cursor. ON non-zero means display the cursor at X, Y which
10371 correspond to HPOS, VPOS, otherwise it is cleared. */
10374 x_display_cursor (w
, on
, hpos
, vpos
, x
, y
)
10376 int on
, hpos
, vpos
, x
, y
;
10379 x_display_and_set_cursor (w
, on
, hpos
, vpos
, x
, y
);
10384 /* Display the cursor on window W, or clear it, according to ON_P.
10385 Don't change the cursor's position. */
10388 x_update_cursor (f
, on_p
)
10391 x_update_cursor_in_window_tree (XWINDOW (f
->root_window
), on_p
);
10395 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10396 in the window tree rooted at W. */
10399 x_update_cursor_in_window_tree (w
, on_p
)
10405 if (!NILP (w
->hchild
))
10406 x_update_cursor_in_window_tree (XWINDOW (w
->hchild
), on_p
);
10407 else if (!NILP (w
->vchild
))
10408 x_update_cursor_in_window_tree (XWINDOW (w
->vchild
), on_p
);
10410 x_update_window_cursor (w
, on_p
);
10412 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
10417 /* Switch the display of W's cursor on or off, according to the value
10421 x_update_window_cursor (w
, on
)
10426 x_display_and_set_cursor (w
, on
, w
->phys_cursor
.hpos
, w
->phys_cursor
.vpos
,
10427 w
->phys_cursor
.x
, w
->phys_cursor
.y
);
10436 /* Refresh bitmap kitchen sink icon for frame F
10437 when we get an expose event for it. */
10443 /* Normally, the window manager handles this function. */
10446 /* Make the x-window of frame F use the gnu icon bitmap. */
10449 x_bitmap_icon (f
, file
)
10455 if (FRAME_X_WINDOW (f
) == 0)
10458 /* Free up our existing icon bitmap if any. */
10459 if (f
->output_data
.x
->icon_bitmap
> 0)
10460 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10461 f
->output_data
.x
->icon_bitmap
= 0;
10463 if (STRINGP (file
))
10464 bitmap_id
= x_create_bitmap_from_file (f
, file
);
10467 /* Create the GNU bitmap if necessary. */
10468 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
10469 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
10470 = x_create_bitmap_from_data (f
, gnu_bits
,
10471 gnu_width
, gnu_height
);
10473 /* The first time we create the GNU bitmap,
10474 this increments the ref-count one extra time.
10475 As a result, the GNU bitmap is never freed.
10476 That way, we don't have to worry about allocating it again. */
10477 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
10479 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
10482 x_wm_set_icon_pixmap (f
, bitmap_id
);
10483 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
10489 /* Make the x-window of frame F use a rectangle with text.
10490 Use ICON_NAME as the text. */
10493 x_text_icon (f
, icon_name
)
10497 if (FRAME_X_WINDOW (f
) == 0)
10502 XTextProperty text
;
10503 text
.value
= (unsigned char *) icon_name
;
10504 text
.encoding
= XA_STRING
;
10506 text
.nitems
= strlen (icon_name
);
10507 #ifdef USE_X_TOOLKIT
10508 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
10510 #else /* not USE_X_TOOLKIT */
10511 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
10512 #endif /* not USE_X_TOOLKIT */
10514 #else /* not HAVE_X11R4 */
10515 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
10516 #endif /* not HAVE_X11R4 */
10518 if (f
->output_data
.x
->icon_bitmap
> 0)
10519 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
10520 f
->output_data
.x
->icon_bitmap
= 0;
10521 x_wm_set_icon_pixmap (f
, 0);
10526 #define X_ERROR_MESSAGE_SIZE 200
10528 /* If non-nil, this should be a string.
10529 It means catch X errors and store the error message in this string. */
10531 static Lisp_Object x_error_message_string
;
10533 /* An X error handler which stores the error message in
10534 x_error_message_string. This is called from x_error_handler if
10535 x_catch_errors is in effect. */
10538 x_error_catcher (display
, error
)
10540 XErrorEvent
*error
;
10542 XGetErrorText (display
, error
->error_code
,
10543 XSTRING (x_error_message_string
)->data
,
10544 X_ERROR_MESSAGE_SIZE
);
10547 /* Begin trapping X errors for display DPY. Actually we trap X errors
10548 for all displays, but DPY should be the display you are actually
10551 After calling this function, X protocol errors no longer cause
10552 Emacs to exit; instead, they are recorded in the string
10553 stored in x_error_message_string.
10555 Calling x_check_errors signals an Emacs error if an X error has
10556 occurred since the last call to x_catch_errors or x_check_errors.
10558 Calling x_uncatch_errors resumes the normal error handling. */
10560 void x_check_errors ();
10561 static Lisp_Object
x_catch_errors_unwind ();
10564 x_catch_errors (dpy
)
10567 int count
= specpdl_ptr
- specpdl
;
10569 /* Make sure any errors from previous requests have been dealt with. */
10570 XSync (dpy
, False
);
10572 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
10574 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
10575 XSTRING (x_error_message_string
)->data
[0] = 0;
10580 /* Unbind the binding that we made to check for X errors. */
10583 x_catch_errors_unwind (old_val
)
10584 Lisp_Object old_val
;
10586 x_error_message_string
= old_val
;
10590 /* If any X protocol errors have arrived since the last call to
10591 x_catch_errors or x_check_errors, signal an Emacs error using
10592 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10595 x_check_errors (dpy
, format
)
10599 /* Make sure to catch any errors incurred so far. */
10600 XSync (dpy
, False
);
10602 if (XSTRING (x_error_message_string
)->data
[0])
10603 error (format
, XSTRING (x_error_message_string
)->data
);
10606 /* Nonzero if we had any X protocol errors
10607 since we did x_catch_errors on DPY. */
10610 x_had_errors_p (dpy
)
10613 /* Make sure to catch any errors incurred so far. */
10614 XSync (dpy
, False
);
10616 return XSTRING (x_error_message_string
)->data
[0] != 0;
10619 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10622 x_clear_errors (dpy
)
10625 XSTRING (x_error_message_string
)->data
[0] = 0;
10628 /* Stop catching X protocol errors and let them make Emacs die.
10629 DPY should be the display that was passed to x_catch_errors.
10630 COUNT should be the value that was returned by
10631 the corresponding call to x_catch_errors. */
10634 x_uncatch_errors (dpy
, count
)
10638 unbind_to (count
, Qnil
);
10642 static unsigned int x_wire_count
;
10645 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
10650 /* Handle SIGPIPE, which can happen when the connection to a server
10651 simply goes away. SIGPIPE is handled by x_connection_signal.
10652 Don't need to do anything, because the write which caused the
10653 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10654 which will do the appropriate cleanup for us. */
10657 x_connection_signal (signalnum
) /* If we don't have an argument, */
10658 int signalnum
; /* some compilers complain in signal calls. */
10661 /* USG systems forget handlers when they are used;
10662 must reestablish each time */
10663 signal (signalnum
, x_connection_signal
);
10667 /* Handling X errors. */
10669 /* Handle the loss of connection to display DISPLAY. */
10672 x_connection_closed (display
, error_message
)
10674 char *error_message
;
10676 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
10677 Lisp_Object frame
, tail
;
10679 /* Indicate that this display is dead. */
10681 #ifdef USE_X_TOOLKIT
10682 XtCloseDisplay (display
);
10685 dpyinfo
->display
= 0;
10687 /* First delete frames whose mini-buffers are on frames
10688 that are on the dead display. */
10689 FOR_EACH_FRAME (tail
, frame
)
10691 Lisp_Object minibuf_frame
;
10693 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
10694 if (FRAME_X_P (XFRAME (frame
))
10695 && FRAME_X_P (XFRAME (minibuf_frame
))
10696 && ! EQ (frame
, minibuf_frame
)
10697 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
10698 Fdelete_frame (frame
, Qt
);
10701 /* Now delete all remaining frames on the dead display.
10702 We are now sure none of these is used as the mini-buffer
10703 for another frame that we need to delete. */
10704 FOR_EACH_FRAME (tail
, frame
)
10705 if (FRAME_X_P (XFRAME (frame
))
10706 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
10708 /* Set this to t so that Fdelete_frame won't get confused
10709 trying to find a replacement. */
10710 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
10711 Fdelete_frame (frame
, Qt
);
10715 x_delete_display (dpyinfo
);
10717 if (x_display_list
== 0)
10719 fprintf (stderr
, "%s\n", error_message
);
10720 shut_down_emacs (0, 0, Qnil
);
10724 /* Ordinary stack unwind doesn't deal with these. */
10726 sigunblock (sigmask (SIGIO
));
10728 sigunblock (sigmask (SIGALRM
));
10729 TOTALLY_UNBLOCK_INPUT
;
10731 clear_waiting_for_input ();
10732 error ("%s", error_message
);
10735 /* This is the usual handler for X protocol errors.
10736 It kills all frames on the display that we got the error for.
10737 If that was the only one, it prints an error message and kills Emacs. */
10740 x_error_quitter (display
, error
)
10742 XErrorEvent
*error
;
10744 char buf
[256], buf1
[356];
10746 /* Note that there is no real way portable across R3/R4 to get the
10747 original error handler. */
10749 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
10750 sprintf (buf1
, "X protocol error: %s on protocol request %d",
10751 buf
, error
->request_code
);
10752 x_connection_closed (display
, buf1
);
10755 /* This is the first-level handler for X protocol errors.
10756 It calls x_error_quitter or x_error_catcher. */
10759 x_error_handler (display
, error
)
10761 XErrorEvent
*error
;
10763 if (! NILP (x_error_message_string
))
10764 x_error_catcher (display
, error
);
10766 x_error_quitter (display
, error
);
10770 /* This is the handler for X IO errors, always.
10771 It kills all frames on the display that we lost touch with.
10772 If that was the only one, it prints an error message and kills Emacs. */
10775 x_io_error_quitter (display
)
10780 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
10781 x_connection_closed (display
, buf
);
10785 /* Changing the font of the frame. */
10787 /* Give frame F the font named FONTNAME as its default font, and
10788 return the full name of that font. FONTNAME may be a wildcard
10789 pattern; in that case, we choose some font that fits the pattern.
10790 The return value shows which font we chose. */
10793 x_new_font (f
, fontname
)
10795 register char *fontname
;
10797 struct font_info
*fontp
10798 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
10803 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
10804 f
->output_data
.x
->baseline_offset
= fontp
->baseline_offset
;
10805 f
->output_data
.x
->fontset
= -1;
10807 /* Compute the scroll bar width in character columns. */
10808 if (f
->scroll_bar_pixel_width
> 0)
10810 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10811 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
10815 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
10816 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
10819 /* Now make the frame display the given font. */
10820 if (FRAME_X_WINDOW (f
) != 0)
10822 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
10823 f
->output_data
.x
->font
->fid
);
10824 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
10825 f
->output_data
.x
->font
->fid
);
10826 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
10827 f
->output_data
.x
->font
->fid
);
10829 frame_update_line_height (f
);
10830 x_set_window_size (f
, 0, f
->width
, f
->height
);
10833 /* If we are setting a new frame's font for the first time,
10834 there are no faces yet, so this font's height is the line height. */
10835 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
10837 return build_string (fontp
->full_name
);
10840 /* Give frame F the fontset named FONTSETNAME as its default font, and
10841 return the full name of that fontset. FONTSETNAME may be a wildcard
10842 pattern; in that case, we choose some fontset that fits the pattern.
10843 The return value shows which fontset we chose. */
10846 x_new_fontset (f
, fontsetname
)
10850 int fontset
= fs_query_fontset (f
, fontsetname
);
10851 struct fontset_info
*fontsetp
;
10852 Lisp_Object result
;
10857 if (f
->output_data
.x
->fontset
== fontset
)
10858 /* This fontset is already set in frame F. There's nothing more
10860 return build_string (fontsetname
);
10862 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
10864 if (!fontsetp
->fontname
[CHARSET_ASCII
])
10865 /* This fontset doesn't contain ASCII font. */
10868 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
10870 if (!STRINGP (result
))
10871 /* Can't load ASCII font. */
10874 /* Since x_new_font doesn't update any fontset information, do it now. */
10875 f
->output_data
.x
->fontset
= fontset
;
10876 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
10877 CHARSET_ASCII
, fontsetp
->fontname
[CHARSET_ASCII
], fontset
);
10879 return build_string (fontsetname
);
10882 /* Calculate the absolute position in frame F
10883 from its current recorded position values and gravity. */
10886 x_calc_absolute_position (f
)
10890 int win_x
= 0, win_y
= 0;
10891 int flags
= f
->output_data
.x
->size_hint_flags
;
10894 /* We have nothing to do if the current position
10895 is already for the top-left corner. */
10896 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
10899 #ifdef USE_X_TOOLKIT
10900 this_window
= XtWindow (f
->output_data
.x
->widget
);
10902 this_window
= FRAME_X_WINDOW (f
);
10905 /* Find the position of the outside upper-left corner of
10906 the inner window, with respect to the outer window.
10907 But do this only if we will need the results. */
10908 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
10913 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
10916 x_clear_errors (FRAME_X_DISPLAY (f
));
10917 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
10919 /* From-window, to-window. */
10921 f
->output_data
.x
->parent_desc
,
10923 /* From-position, to-position. */
10924 0, 0, &win_x
, &win_y
,
10926 /* Child of win. */
10928 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
10930 Window newroot
, newparent
= 0xdeadbeef;
10931 Window
*newchildren
;
10934 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
10935 &newparent
, &newchildren
, &nchildren
))
10938 XFree ((char *) newchildren
);
10940 f
->output_data
.x
->parent_desc
= newparent
;
10946 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
10950 /* Treat negative positions as relative to the leftmost bottommost
10951 position that fits on the screen. */
10952 if (flags
& XNegative
)
10953 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
10954 - 2 * f
->output_data
.x
->border_width
- win_x
10956 + f
->output_data
.x
->left_pos
);
10958 if (flags
& YNegative
)
10960 int menubar_height
= 0;
10962 #ifdef USE_X_TOOLKIT
10963 if (f
->output_data
.x
->menubar_widget
)
10965 = (f
->output_data
.x
->menubar_widget
->core
.height
10966 + f
->output_data
.x
->menubar_widget
->core
.border_width
);
10969 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
10970 - 2 * f
->output_data
.x
->border_width
10974 + f
->output_data
.x
->top_pos
);
10977 /* The left_pos and top_pos
10978 are now relative to the top and left screen edges,
10979 so the flags should correspond. */
10980 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
10983 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10984 to really change the position, and 0 when calling from
10985 x_make_frame_visible (in that case, XOFF and YOFF are the current
10986 position values). It is -1 when calling from x_set_frame_parameters,
10987 which means, do adjust for borders but don't change the gravity. */
10990 x_set_offset (f
, xoff
, yoff
, change_gravity
)
10992 register int xoff
, yoff
;
10993 int change_gravity
;
10995 int modified_top
, modified_left
;
10997 if (change_gravity
> 0)
10999 f
->output_data
.x
->top_pos
= yoff
;
11000 f
->output_data
.x
->left_pos
= xoff
;
11001 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
11003 f
->output_data
.x
->size_hint_flags
|= XNegative
;
11005 f
->output_data
.x
->size_hint_flags
|= YNegative
;
11006 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11008 x_calc_absolute_position (f
);
11011 x_wm_set_size_hint (f
, (long) 0, 0);
11013 modified_left
= f
->output_data
.x
->left_pos
;
11014 modified_top
= f
->output_data
.x
->top_pos
;
11015 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11016 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11017 /* It is a mystery why we need to add the border_width here
11018 when the frame is already visible, but experiment says we do. */
11019 if (change_gravity
!= 0)
11021 modified_left
+= f
->output_data
.x
->border_width
;
11022 modified_top
+= f
->output_data
.x
->border_width
;
11026 #ifdef USE_X_TOOLKIT
11027 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
11028 modified_left
, modified_top
);
11029 #else /* not USE_X_TOOLKIT */
11030 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11031 modified_left
, modified_top
);
11032 #endif /* not USE_X_TOOLKIT */
11036 /* Call this to change the size of frame F's x-window.
11037 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11038 for this size change and subsequent size changes.
11039 Otherwise we leave the window gravity unchanged. */
11042 x_set_window_size (f
, change_gravity
, cols
, rows
)
11044 int change_gravity
;
11047 #ifndef USE_X_TOOLKIT
11048 int pixelwidth
, pixelheight
;
11053 #ifdef USE_X_TOOLKIT
11055 /* The x and y position of the widget is clobbered by the
11056 call to XtSetValues within EmacsFrameSetCharSize.
11057 This is a real kludge, but I don't understand Xt so I can't
11058 figure out a correct fix. Can anyone else tell me? -- rms. */
11059 int xpos
= f
->output_data
.x
->widget
->core
.x
;
11060 int ypos
= f
->output_data
.x
->widget
->core
.y
;
11061 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
11062 f
->output_data
.x
->widget
->core
.x
= xpos
;
11063 f
->output_data
.x
->widget
->core
.y
= ypos
;
11066 #else /* not USE_X_TOOLKIT */
11068 check_frame_size (f
, &rows
, &cols
);
11069 f
->output_data
.x
->vertical_scroll_bar_extra
11070 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
11072 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
11073 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
11074 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
11075 f
->output_data
.x
->flags_areas_extra
11076 = FRAME_FLAGS_AREA_WIDTH (f
);
11077 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
11078 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
11080 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
11081 x_wm_set_size_hint (f
, (long) 0, 0);
11083 XSync (FRAME_X_DISPLAY (f
), False
);
11084 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11085 pixelwidth
, pixelheight
);
11087 /* Now, strictly speaking, we can't be sure that this is accurate,
11088 but the window manager will get around to dealing with the size
11089 change request eventually, and we'll hear how it went when the
11090 ConfigureNotify event gets here.
11092 We could just not bother storing any of this information here,
11093 and let the ConfigureNotify event set everything up, but that
11094 might be kind of confusing to the Lisp code, since size changes
11095 wouldn't be reported in the frame parameters until some random
11096 point in the future when the ConfigureNotify event arrives.
11098 We pass 1 for DELAY since we can't run Lisp code inside of
11100 change_frame_size (f
, rows
, cols
, 0, 1, 0);
11101 PIXEL_WIDTH (f
) = pixelwidth
;
11102 PIXEL_HEIGHT (f
) = pixelheight
;
11104 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11105 receive in the ConfigureNotify event; if we get what we asked
11106 for, then the event won't cause the screen to become garbaged, so
11107 we have to make sure to do it here. */
11108 SET_FRAME_GARBAGED (f
);
11110 XFlush (FRAME_X_DISPLAY (f
));
11112 #endif /* not USE_X_TOOLKIT */
11114 /* If cursor was outside the new size, mark it as off. */
11115 mark_window_cursors_off (XWINDOW (f
->root_window
));
11117 /* Clear out any recollection of where the mouse highlighting was,
11118 since it might be in a place that's outside the new frame size.
11119 Actually checking whether it is outside is a pain in the neck,
11120 so don't try--just let the highlighting be done afresh with new size. */
11121 cancel_mouse_face (f
);
11126 /* Mouse warping. */
11129 x_set_mouse_position (f
, x
, y
)
11135 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
11136 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
11138 if (pix_x
< 0) pix_x
= 0;
11139 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
11141 if (pix_y
< 0) pix_y
= 0;
11142 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
11146 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11147 0, 0, 0, 0, pix_x
, pix_y
);
11151 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11154 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
11160 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
11161 0, 0, 0, 0, pix_x
, pix_y
);
11165 /* focus shifting, raising and lowering. */
11168 x_focus_on_frame (f
)
11171 #if 0 /* This proves to be unpleasant. */
11175 /* I don't think that the ICCCM allows programs to do things like this
11176 without the interaction of the window manager. Whatever you end up
11177 doing with this code, do it to x_unfocus_frame too. */
11178 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
11179 RevertToPointerRoot
, CurrentTime
);
11184 x_unfocus_frame (f
)
11188 /* Look at the remarks in x_focus_on_frame. */
11189 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
11190 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
11191 RevertToPointerRoot
, CurrentTime
);
11195 /* Raise frame F. */
11201 if (f
->async_visible
)
11204 #ifdef USE_X_TOOLKIT
11205 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11206 #else /* not USE_X_TOOLKIT */
11207 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11208 #endif /* not USE_X_TOOLKIT */
11209 XFlush (FRAME_X_DISPLAY (f
));
11214 /* Lower frame F. */
11220 if (f
->async_visible
)
11223 #ifdef USE_X_TOOLKIT
11224 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
11225 #else /* not USE_X_TOOLKIT */
11226 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11227 #endif /* not USE_X_TOOLKIT */
11228 XFlush (FRAME_X_DISPLAY (f
));
11234 XTframe_raise_lower (f
, raise_flag
)
11244 /* Change of visibility. */
11246 /* This tries to wait until the frame is really visible.
11247 However, if the window manager asks the user where to position
11248 the frame, this will return before the user finishes doing that.
11249 The frame will not actually be visible at that time,
11250 but it will become visible later when the window manager
11251 finishes with it. */
11254 x_make_frame_visible (f
)
11258 int original_top
, original_left
;
11262 type
= x_icon_type (f
);
11264 x_bitmap_icon (f
, type
);
11266 if (! FRAME_VISIBLE_P (f
))
11268 /* We test FRAME_GARBAGED_P here to make sure we don't
11269 call x_set_offset a second time
11270 if we get to x_make_frame_visible a second time
11271 before the window gets really visible. */
11272 if (! FRAME_ICONIFIED_P (f
)
11273 && ! f
->output_data
.x
->asked_for_visible
)
11274 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11276 f
->output_data
.x
->asked_for_visible
= 1;
11278 if (! EQ (Vx_no_window_manager
, Qt
))
11279 x_wm_set_window_state (f
, NormalState
);
11280 #ifdef USE_X_TOOLKIT
11281 /* This was XtPopup, but that did nothing for an iconified frame. */
11282 XtMapWidget (f
->output_data
.x
->widget
);
11283 #else /* not USE_X_TOOLKIT */
11284 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11285 #endif /* not USE_X_TOOLKIT */
11286 #if 0 /* This seems to bring back scroll bars in the wrong places
11287 if the window configuration has changed. They seem
11288 to come back ok without this. */
11289 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
11290 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11294 XFlush (FRAME_X_DISPLAY (f
));
11296 /* Synchronize to ensure Emacs knows the frame is visible
11297 before we do anything else. We do this loop with input not blocked
11298 so that incoming events are handled. */
11301 int count
= input_signal_count
;
11302 /* This must be before UNBLOCK_INPUT
11303 since events that arrive in response to the actions above
11304 will set it when they are handled. */
11305 int previously_visible
= f
->output_data
.x
->has_been_visible
;
11307 original_left
= f
->output_data
.x
->left_pos
;
11308 original_top
= f
->output_data
.x
->top_pos
;
11310 /* This must come after we set COUNT. */
11313 /* We unblock here so that arriving X events are processed. */
11315 /* Now move the window back to where it was "supposed to be".
11316 But don't do it if the gravity is negative.
11317 When the gravity is negative, this uses a position
11318 that is 3 pixels too low. Perhaps that's really the border width.
11320 Don't do this if the window has never been visible before,
11321 because the window manager may choose the position
11322 and we don't want to override it. */
11324 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
11325 && f
->output_data
.x
->win_gravity
== NorthWestGravity
11326 && previously_visible
)
11330 unsigned int width
, height
, border
, depth
;
11334 /* On some window managers (such as FVWM) moving an existing
11335 window, even to the same place, causes the window manager
11336 to introduce an offset. This can cause the window to move
11337 to an unexpected location. Check the geometry (a little
11338 slow here) and then verify that the window is in the right
11339 place. If the window is not in the right place, move it
11340 there, and take the potential window manager hit. */
11341 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11342 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
11344 if (original_left
!= x
|| original_top
!= y
)
11345 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
11346 original_left
, original_top
);
11351 XSETFRAME (frame
, f
);
11356 /* Once we have handled input events,
11357 we should have received the MapNotify if one is coming.
11358 So if we have not got it yet, stop looping.
11359 Some window managers make their own decisions
11360 about visibility. */
11361 if (input_signal_count
!= count
)
11363 /* Machines that do polling rather than SIGIO have been observed
11364 to go into a busy-wait here. So we'll fake an alarm signal
11365 to let the handler know that there's something to be read.
11366 We used to raise a real alarm, but it seems that the handler
11367 isn't always enabled here. This is probably a bug. */
11368 if (input_polling_used ())
11370 /* It could be confusing if a real alarm arrives while processing
11371 the fake one. Turn it off and let the handler reset it. */
11373 input_poll_signal (0);
11375 /* Once we have handled input events,
11376 we should have received the MapNotify if one is coming.
11377 So if we have not got it yet, stop looping.
11378 Some window managers make their own decisions
11379 about visibility. */
11380 if (input_signal_count
!= count
)
11383 FRAME_SAMPLE_VISIBILITY (f
);
11387 /* Change from mapped state to withdrawn state. */
11389 /* Make the frame visible (mapped and not iconified). */
11392 x_make_frame_invisible (f
)
11397 #ifdef USE_X_TOOLKIT
11398 /* Use the frame's outermost window, not the one we normally draw on. */
11399 window
= XtWindow (f
->output_data
.x
->widget
);
11400 #else /* not USE_X_TOOLKIT */
11401 window
= FRAME_X_WINDOW (f
);
11402 #endif /* not USE_X_TOOLKIT */
11404 /* Don't keep the highlight on an invisible frame. */
11405 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11406 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11408 #if 0/* This might add unreliability; I don't trust it -- rms. */
11409 if (! f
->async_visible
&& ! f
->async_iconified
)
11415 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11416 that the current position of the window is user-specified, rather than
11417 program-specified, so that when the window is mapped again, it will be
11418 placed at the same location, without forcing the user to position it
11419 by hand again (they have already done that once for this window.) */
11420 x_wm_set_size_hint (f
, (long) 0, 1);
11424 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
11425 DefaultScreen (FRAME_X_DISPLAY (f
))))
11427 UNBLOCK_INPUT_RESIGNAL
;
11428 error ("Can't notify window manager of window withdrawal");
11430 #else /* ! defined (HAVE_X11R4) */
11432 /* Tell the window manager what we're going to do. */
11433 if (! EQ (Vx_no_window_manager
, Qt
))
11437 unmap
.xunmap
.type
= UnmapNotify
;
11438 unmap
.xunmap
.window
= window
;
11439 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
11440 unmap
.xunmap
.from_configure
= False
;
11441 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11442 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11444 SubstructureRedirectMaskSubstructureNotifyMask
,
11447 UNBLOCK_INPUT_RESIGNAL
;
11448 error ("Can't notify window manager of withdrawal");
11452 /* Unmap the window ourselves. Cheeky! */
11453 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
11454 #endif /* ! defined (HAVE_X11R4) */
11456 /* We can't distinguish this from iconification
11457 just by the event that we get from the server.
11458 So we can't win using the usual strategy of letting
11459 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11460 and synchronize with the server to make sure we agree. */
11462 FRAME_ICONIFIED_P (f
) = 0;
11463 f
->async_visible
= 0;
11464 f
->async_iconified
= 0;
11471 /* Change window state from mapped to iconified. */
11474 x_iconify_frame (f
)
11480 /* Don't keep the highlight on an invisible frame. */
11481 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
11482 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
11484 if (f
->async_iconified
)
11489 FRAME_SAMPLE_VISIBILITY (f
);
11491 type
= x_icon_type (f
);
11493 x_bitmap_icon (f
, type
);
11495 #ifdef USE_X_TOOLKIT
11497 if (! FRAME_VISIBLE_P (f
))
11499 if (! EQ (Vx_no_window_manager
, Qt
))
11500 x_wm_set_window_state (f
, IconicState
);
11501 /* This was XtPopup, but that did nothing for an iconified frame. */
11502 XtMapWidget (f
->output_data
.x
->widget
);
11503 /* The server won't give us any event to indicate
11504 that an invisible frame was changed to an icon,
11505 so we have to record it here. */
11508 f
->async_iconified
= 1;
11509 f
->async_visible
= 0;
11514 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
11515 XtWindow (f
->output_data
.x
->widget
),
11516 DefaultScreen (FRAME_X_DISPLAY (f
)));
11520 error ("Can't notify window manager of iconification");
11522 f
->async_iconified
= 1;
11523 f
->async_visible
= 0;
11527 XFlush (FRAME_X_DISPLAY (f
));
11529 #else /* not USE_X_TOOLKIT */
11531 /* Make sure the X server knows where the window should be positioned,
11532 in case the user deiconifies with the window manager. */
11533 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
11534 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
11536 /* Since we don't know which revision of X we're running, we'll use both
11537 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11539 /* X11R4: send a ClientMessage to the window manager using the
11540 WM_CHANGE_STATE type. */
11544 message
.xclient
.window
= FRAME_X_WINDOW (f
);
11545 message
.xclient
.type
= ClientMessage
;
11546 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
11547 message
.xclient
.format
= 32;
11548 message
.xclient
.data
.l
[0] = IconicState
;
11550 if (! XSendEvent (FRAME_X_DISPLAY (f
),
11551 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
11553 SubstructureRedirectMask
| SubstructureNotifyMask
,
11556 UNBLOCK_INPUT_RESIGNAL
;
11557 error ("Can't notify window manager of iconification");
11561 /* X11R3: set the initial_state field of the window manager hints to
11563 x_wm_set_window_state (f
, IconicState
);
11565 if (!FRAME_VISIBLE_P (f
))
11567 /* If the frame was withdrawn, before, we must map it. */
11568 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
11571 f
->async_iconified
= 1;
11572 f
->async_visible
= 0;
11574 XFlush (FRAME_X_DISPLAY (f
));
11576 #endif /* not USE_X_TOOLKIT */
11579 /* Destroy the X window of frame F. */
11582 x_destroy_window (f
)
11585 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
11589 /* If a display connection is dead, don't try sending more
11590 commands to the X server. */
11591 if (dpyinfo
->display
!= 0)
11593 if (f
->output_data
.x
->icon_desc
!= 0)
11594 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
11598 XDestroyIC (FRAME_XIC (f
));
11599 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11600 /* This line causes crashes on Solaris with Openwin,
11601 due to an apparent bug in XCloseIM.
11602 X11R6 seems not to have the bug. */
11603 XCloseIM (FRAME_XIM (f
));
11607 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
11608 #ifdef USE_X_TOOLKIT
11609 if (f
->output_data
.x
->widget
)
11610 XtDestroyWidget (f
->output_data
.x
->widget
);
11611 free_frame_menubar (f
);
11612 #endif /* USE_X_TOOLKIT */
11614 free_frame_faces (f
);
11615 XFlush (FRAME_X_DISPLAY (f
));
11618 if (f
->output_data
.x
->saved_menu_event
)
11619 xfree (f
->output_data
.x
->saved_menu_event
);
11621 xfree (f
->output_data
.x
);
11622 f
->output_data
.x
= 0;
11623 if (f
== dpyinfo
->x_focus_frame
)
11624 dpyinfo
->x_focus_frame
= 0;
11625 if (f
== dpyinfo
->x_focus_event_frame
)
11626 dpyinfo
->x_focus_event_frame
= 0;
11627 if (f
== dpyinfo
->x_highlight_frame
)
11628 dpyinfo
->x_highlight_frame
= 0;
11630 dpyinfo
->reference_count
--;
11632 if (f
== dpyinfo
->mouse_face_mouse_frame
)
11634 dpyinfo
->mouse_face_beg_row
11635 = dpyinfo
->mouse_face_beg_col
= -1;
11636 dpyinfo
->mouse_face_end_row
11637 = dpyinfo
->mouse_face_end_col
= -1;
11638 dpyinfo
->mouse_face_window
= Qnil
;
11639 dpyinfo
->mouse_face_deferred_gc
= 0;
11640 dpyinfo
->mouse_face_mouse_frame
= 0;
11646 /* Setting window manager hints. */
11648 /* Set the normal size hints for the window manager, for frame F.
11649 FLAGS is the flags word to use--or 0 meaning preserve the flags
11650 that the window now has.
11651 If USER_POSITION is nonzero, we set the USPosition
11652 flag (this is useful when FLAGS is 0). */
11655 x_wm_set_size_hint (f
, flags
, user_position
)
11660 XSizeHints size_hints
;
11662 #ifdef USE_X_TOOLKIT
11665 Dimension widget_width
, widget_height
;
11666 Window window
= XtWindow (f
->output_data
.x
->widget
);
11667 #else /* not USE_X_TOOLKIT */
11668 Window window
= FRAME_X_WINDOW (f
);
11669 #endif /* not USE_X_TOOLKIT */
11671 /* Setting PMaxSize caused various problems. */
11672 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
11674 size_hints
.x
= f
->output_data
.x
->left_pos
;
11675 size_hints
.y
= f
->output_data
.x
->top_pos
;
11677 #ifdef USE_X_TOOLKIT
11678 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
11679 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
11680 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
11681 size_hints
.height
= widget_height
;
11682 size_hints
.width
= widget_width
;
11683 #else /* not USE_X_TOOLKIT */
11684 size_hints
.height
= PIXEL_HEIGHT (f
);
11685 size_hints
.width
= PIXEL_WIDTH (f
);
11686 #endif /* not USE_X_TOOLKIT */
11688 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
11689 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
11690 size_hints
.max_width
11691 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
11692 size_hints
.max_height
11693 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
11695 /* Calculate the base and minimum sizes.
11697 (When we use the X toolkit, we don't do it here.
11698 Instead we copy the values that the widgets are using, below.) */
11699 #ifndef USE_X_TOOLKIT
11701 int base_width
, base_height
;
11702 int min_rows
= 0, min_cols
= 0;
11704 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
11705 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
11707 check_frame_size (f
, &min_rows
, &min_cols
);
11709 /* The window manager uses the base width hints to calculate the
11710 current number of rows and columns in the frame while
11711 resizing; min_width and min_height aren't useful for this
11712 purpose, since they might not give the dimensions for a
11713 zero-row, zero-column frame.
11715 We use the base_width and base_height members if we have
11716 them; otherwise, we set the min_width and min_height members
11717 to the size for a zero x zero frame. */
11720 size_hints
.flags
|= PBaseSize
;
11721 size_hints
.base_width
= base_width
;
11722 size_hints
.base_height
= base_height
;
11723 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
11724 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
11726 size_hints
.min_width
= base_width
;
11727 size_hints
.min_height
= base_height
;
11731 /* If we don't need the old flags, we don't need the old hint at all. */
11734 size_hints
.flags
|= flags
;
11737 #endif /* not USE_X_TOOLKIT */
11740 XSizeHints hints
; /* Sometimes I hate X Windows... */
11741 long supplied_return
;
11745 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
11748 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
11751 #ifdef USE_X_TOOLKIT
11752 size_hints
.base_height
= hints
.base_height
;
11753 size_hints
.base_width
= hints
.base_width
;
11754 size_hints
.min_height
= hints
.min_height
;
11755 size_hints
.min_width
= hints
.min_width
;
11759 size_hints
.flags
|= flags
;
11764 if (hints
.flags
& PSize
)
11765 size_hints
.flags
|= PSize
;
11766 if (hints
.flags
& PPosition
)
11767 size_hints
.flags
|= PPosition
;
11768 if (hints
.flags
& USPosition
)
11769 size_hints
.flags
|= USPosition
;
11770 if (hints
.flags
& USSize
)
11771 size_hints
.flags
|= USSize
;
11775 #ifndef USE_X_TOOLKIT
11780 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
11781 size_hints
.flags
|= PWinGravity
;
11785 size_hints
.flags
&= ~ PPosition
;
11786 size_hints
.flags
|= USPosition
;
11788 #endif /* PWinGravity */
11791 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11793 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
11797 /* Used for IconicState or NormalState */
11800 x_wm_set_window_state (f
, state
)
11804 #ifdef USE_X_TOOLKIT
11807 XtSetArg (al
[0], XtNinitialState
, state
);
11808 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11809 #else /* not USE_X_TOOLKIT */
11810 Window window
= FRAME_X_WINDOW (f
);
11812 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
11813 f
->output_data
.x
->wm_hints
.initial_state
= state
;
11815 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11816 #endif /* not USE_X_TOOLKIT */
11820 x_wm_set_icon_pixmap (f
, pixmap_id
)
11824 Pixmap icon_pixmap
;
11826 #ifndef USE_X_TOOLKIT
11827 Window window
= FRAME_X_WINDOW (f
);
11832 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
11833 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
11837 /* It seems there is no way to turn off use of an icon pixmap.
11838 The following line does it, only if no icon has yet been created,
11839 for some window managers. But with mwm it crashes.
11840 Some people say it should clear the IconPixmapHint bit in this case,
11841 but that doesn't work, and the X consortium said it isn't the
11842 right thing at all. Since there is no way to win,
11843 best to explicitly give up. */
11845 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
11851 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11855 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
11856 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
11859 #else /* not USE_X_TOOLKIT */
11861 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
11862 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11864 #endif /* not USE_X_TOOLKIT */
11868 x_wm_set_icon_position (f
, icon_x
, icon_y
)
11870 int icon_x
, icon_y
;
11872 #ifdef USE_X_TOOLKIT
11873 Window window
= XtWindow (f
->output_data
.x
->widget
);
11875 Window window
= FRAME_X_WINDOW (f
);
11878 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
11879 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
11880 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
11882 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
11886 /***********************************************************************
11888 ***********************************************************************/
11890 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
11893 x_get_font_info (f
, font_idx
)
11897 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
11901 /* Return a list of names of available fonts matching PATTERN on frame
11902 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11903 to be listed. Frame F NULL means we have not yet created any
11904 frame on X, and consult the first display in x_display_list.
11905 MAXNAMES sets a limit on how many fonts to match. */
11908 x_list_fonts (f
, pattern
, size
, maxnames
)
11910 Lisp_Object pattern
;
11914 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
= Qnil
;
11915 Lisp_Object tem
, second_best
;
11916 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
11917 int try_XLoadQueryFont
= 0;
11920 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
11921 if (NILP (patterns
))
11922 patterns
= Fcons (pattern
, Qnil
);
11924 if (maxnames
== 1 && !size
)
11925 /* We can return any single font matching PATTERN. */
11926 try_XLoadQueryFont
= 1;
11928 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
11933 pattern
= XCAR (patterns
);
11934 /* See if we cached the result for this particular query.
11935 The cache is an alist of the form:
11936 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11938 if (f
&& (tem
= XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
),
11939 key
= Fcons (pattern
, make_number (maxnames
)),
11940 !NILP (list
= Fassoc (key
, tem
))))
11942 list
= Fcdr_safe (list
);
11943 /* We have a cashed list. Don't have to get the list again. */
11947 /* At first, put PATTERN in the cache. */
11950 count
= x_catch_errors (dpy
);
11952 if (try_XLoadQueryFont
)
11955 unsigned long value
;
11957 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
11958 if (x_had_errors_p (dpy
))
11960 /* This error is perhaps due to insufficient memory on X
11961 server. Let's just ignore it. */
11963 x_clear_errors (dpy
);
11967 && XGetFontProperty (font
, XA_FONT
, &value
))
11969 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
11970 int len
= strlen (name
);
11973 /* If DXPC (a Differential X Protocol Compressor)
11974 Ver.3.7 is running, XGetAtomName will return null
11975 string. We must avoid such a name. */
11977 try_XLoadQueryFont
= 0;
11981 names
= (char **) alloca (sizeof (char *));
11982 /* Some systems only allow alloca assigned to a
11984 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
11985 bcopy (name
, names
[0], len
+ 1);
11990 try_XLoadQueryFont
= 0;
11993 XFreeFont (dpy
, font
);
11996 if (!try_XLoadQueryFont
)
11998 /* We try at least 10 fonts because XListFonts will return
11999 auto-scaled fonts at the head. */
12000 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, max (maxnames
, 10),
12002 if (x_had_errors_p (dpy
))
12004 /* This error is perhaps due to insufficient memory on X
12005 server. Let's just ignore it. */
12007 x_clear_errors (dpy
);
12011 x_uncatch_errors (dpy
, count
);
12018 /* Make a list of all the fonts we got back.
12019 Store that in the font cache for the display. */
12020 for (i
= 0; i
< num_fonts
; i
++)
12023 char *p
= names
[i
];
12024 int average_width
= -1, dashes
= 0;
12026 /* Count the number of dashes in NAMES[I]. If there are
12027 14 dashes, and the field value following 12th dash
12028 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12029 is usually too ugly to be used for editing. Let's
12035 if (dashes
== 7) /* PIXEL_SIZE field */
12037 else if (dashes
== 12) /* AVERAGE_WIDTH field */
12038 average_width
= atoi (p
);
12040 if (dashes
< 14 || average_width
!= 0)
12042 tem
= build_string (names
[i
]);
12043 if (NILP (Fassoc (tem
, list
)))
12045 if (STRINGP (Vx_pixel_size_width_font_regexp
)
12046 && ((fast_c_string_match_ignore_case
12047 (Vx_pixel_size_width_font_regexp
, names
[i
]))
12049 /* We can set the value of PIXEL_SIZE to the
12050 width of this font. */
12051 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
12053 /* For the moment, width is not known. */
12054 list
= Fcons (Fcons (tem
, Qnil
), list
);
12058 if (!try_XLoadQueryFont
)
12059 XFreeFontNames (names
);
12062 /* Now store the result in the cache. */
12064 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)
12065 = Fcons (Fcons (key
, list
),
12066 XCDR (FRAME_X_DISPLAY_INFO (f
)->name_list_element
));
12069 if (NILP (list
)) continue; /* Try the remaining alternatives. */
12071 newlist
= second_best
= Qnil
;
12072 /* Make a list of the fonts that have the right width. */
12073 for (; CONSP (list
); list
= XCDR (list
))
12079 if (!CONSP (tem
) || NILP (XCAR (tem
)))
12083 newlist
= Fcons (XCAR (tem
), newlist
);
12087 if (!INTEGERP (XCDR (tem
)))
12089 /* Since we have not yet known the size of this font, we
12090 must try slow function call XLoadQueryFont. */
12091 XFontStruct
*thisinfo
;
12094 count
= x_catch_errors (dpy
);
12095 thisinfo
= XLoadQueryFont (dpy
,
12096 XSTRING (XCAR (tem
))->data
);
12097 if (x_had_errors_p (dpy
))
12099 /* This error is perhaps due to insufficient memory on X
12100 server. Let's just ignore it. */
12102 x_clear_errors (dpy
);
12104 x_uncatch_errors (dpy
, count
);
12110 = (thisinfo
->min_bounds
.width
== 0
12112 : make_number (thisinfo
->max_bounds
.width
));
12113 XFreeFont (dpy
, thisinfo
);
12116 /* For unknown reason, the previous call of XListFont had
12117 returned a font which can't be opened. Record the size
12118 as 0 not to try to open it again. */
12119 XCDR (tem
) = make_number (0);
12122 found_size
= XINT (XCDR (tem
));
12123 if (found_size
== size
)
12124 newlist
= Fcons (XCAR (tem
), newlist
);
12125 else if (found_size
> 0)
12127 if (NILP (second_best
))
12129 else if (found_size
< size
)
12131 if (XINT (XCDR (second_best
)) > size
12132 || XINT (XCDR (second_best
)) < found_size
)
12137 if (XINT (XCDR (second_best
)) > size
12138 && XINT (XCDR (second_best
)) > found_size
)
12143 if (!NILP (newlist
))
12145 else if (!NILP (second_best
))
12147 newlist
= Fcons (XCAR (second_best
), Qnil
);
12158 /* Check that FONT is valid on frame F. It is if it can be found in F's
12162 x_check_font (f
, font
)
12167 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12169 xassert (font
!= NULL
);
12171 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12172 if (dpyinfo
->font_table
[i
].name
12173 && font
== dpyinfo
->font_table
[i
].font
)
12176 xassert (i
< dpyinfo
->n_fonts
);
12179 #endif /* GLYPH_DEBUG != 0 */
12181 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12182 Note: There are (broken) X fonts out there with invalid XFontStruct
12183 min_bounds contents. For example, handa@etl.go.jp reports that
12184 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12185 have font->min_bounds.width == 0. */
12188 x_font_min_bounds (font
, w
, h
)
12192 *h
= FONT_HEIGHT (font
);
12193 *w
= font
->min_bounds
.width
;
12195 /* Try to handle the case where FONT->min_bounds has invalid
12196 contents. Since the only font known to have invalid min_bounds
12197 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12199 *w
= font
->max_bounds
.width
;
12203 /* Compute the smallest character width and smallest font height over
12204 all fonts available on frame F. Set the members smallest_char_width
12205 and smallest_font_height in F's x_display_info structure to
12206 the values computed. Value is non-zero if smallest_font_height or
12207 smallest_char_width become smaller than they were before. */
12210 x_compute_min_glyph_bounds (f
)
12214 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12216 int old_width
= dpyinfo
->smallest_char_width
;
12217 int old_height
= dpyinfo
->smallest_font_height
;
12219 dpyinfo
->smallest_font_height
= 100000;
12220 dpyinfo
->smallest_char_width
= 100000;
12222 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12223 if (dpyinfo
->font_table
[i
].name
)
12225 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
12228 font
= (XFontStruct
*) fontp
->font
;
12229 xassert (font
!= (XFontStruct
*) ~0);
12230 x_font_min_bounds (font
, &w
, &h
);
12232 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
12233 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
12236 xassert (dpyinfo
->smallest_char_width
> 0
12237 && dpyinfo
->smallest_font_height
> 0);
12239 return (dpyinfo
->n_fonts
== 1
12240 || dpyinfo
->smallest_char_width
< old_width
12241 || dpyinfo
->smallest_font_height
< old_height
);
12245 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12246 pointer to the structure font_info while allocating it dynamically.
12247 If SIZE is 0, load any size of font.
12248 If loading is failed, return NULL. */
12251 x_load_font (f
, fontname
, size
)
12253 register char *fontname
;
12256 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12257 Lisp_Object font_names
;
12260 /* Get a list of all the fonts that match this name. Once we
12261 have a list of matching fonts, we compare them against the fonts
12262 we already have by comparing names. */
12263 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
12265 if (!NILP (font_names
))
12270 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12271 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
12272 if (dpyinfo
->font_table
[i
].name
12273 && (!strcmp (dpyinfo
->font_table
[i
].name
,
12274 XSTRING (XCAR (tail
))->data
)
12275 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
12276 XSTRING (XCAR (tail
))->data
)))
12277 return (dpyinfo
->font_table
+ i
);
12280 /* Load the font and add it to the table. */
12284 struct font_info
*fontp
;
12285 unsigned long value
;
12288 /* If we have found fonts by x_list_font, load one of them. If
12289 not, we still try to load a font by the name given as FONTNAME
12290 because XListFonts (called in x_list_font) of some X server has
12291 a bug of not finding a font even if the font surely exists and
12292 is loadable by XLoadQueryFont. */
12293 if (size
> 0 && !NILP (font_names
))
12294 fontname
= (char *) XSTRING (XCAR (font_names
))->data
;
12297 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
12298 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
12299 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
12301 /* This error is perhaps due to insufficient memory on X
12302 server. Let's just ignore it. */
12304 x_clear_errors (FRAME_X_DISPLAY (f
));
12306 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
12311 /* Find a free slot in the font table. */
12312 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
12313 if (dpyinfo
->font_table
[i
].name
== NULL
)
12316 /* If no free slot found, maybe enlarge the font table. */
12317 if (i
== dpyinfo
->n_fonts
12318 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
12321 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
12322 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
12323 dpyinfo
->font_table
12324 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
12327 fontp
= dpyinfo
->font_table
+ i
;
12328 if (i
== dpyinfo
->n_fonts
)
12329 ++dpyinfo
->n_fonts
;
12331 /* Now fill in the slots of *FONTP. */
12333 fontp
->font
= font
;
12334 fontp
->font_idx
= i
;
12335 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
12336 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
12338 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12340 if (XGetFontProperty (font
, XA_FONT
, &value
))
12342 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
12346 /* Count the number of dashes in the "full name".
12347 If it is too few, this isn't really the font's full name,
12349 In X11R4, the fonts did not come with their canonical names
12360 full_name
= (char *) xmalloc (p
- name
+ 1);
12361 bcopy (name
, full_name
, p
- name
+ 1);
12367 if (full_name
!= 0)
12368 fontp
->full_name
= full_name
;
12370 fontp
->full_name
= fontp
->name
;
12372 fontp
->size
= font
->max_bounds
.width
;
12373 fontp
->height
= FONT_HEIGHT (font
);
12375 /* For some font, ascent and descent in max_bounds field is
12376 larger than the above value. */
12377 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
12378 if (max_height
> fontp
->height
)
12379 fontp
->height
= max_height
;
12382 if (NILP (font_names
))
12384 /* We come here because of a bug of XListFonts mentioned at
12385 the head of this block. Let's store this information in
12386 the cache for x_list_fonts. */
12387 Lisp_Object lispy_name
= build_string (fontname
);
12388 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
12390 XCDR (dpyinfo
->name_list_element
)
12391 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
12392 Fcons (Fcons (lispy_full_name
,
12393 make_number (fontp
->size
)),
12395 XCDR (dpyinfo
->name_list_element
));
12397 XCDR (dpyinfo
->name_list_element
)
12398 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
12399 Fcons (Fcons (lispy_full_name
,
12400 make_number (fontp
->size
)),
12402 XCDR (dpyinfo
->name_list_element
));
12405 /* The slot `encoding' specifies how to map a character
12406 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12407 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12408 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12409 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12410 2:0xA020..0xFF7F). For the moment, we don't know which charset
12411 uses this font. So, we set information in fontp->encoding[1]
12412 which is never used by any charset. If mapping can't be
12413 decided, set FONT_ENCODING_NOT_DECIDED. */
12415 = (font
->max_byte1
== 0
12417 ? (font
->min_char_or_byte2
< 0x80
12418 ? (font
->max_char_or_byte2
< 0x80
12419 ? 0 /* 0x20..0x7F */
12420 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
12421 : 1) /* 0xA0..0xFF */
12423 : (font
->min_byte1
< 0x80
12424 ? (font
->max_byte1
< 0x80
12425 ? (font
->min_char_or_byte2
< 0x80
12426 ? (font
->max_char_or_byte2
< 0x80
12427 ? 0 /* 0x2020..0x7F7F */
12428 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
12429 : 3) /* 0x20A0..0x7FFF */
12430 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
12431 : (font
->min_char_or_byte2
< 0x80
12432 ? (font
->max_char_or_byte2
< 0x80
12433 ? 2 /* 0xA020..0xFF7F */
12434 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
12435 : 1))); /* 0xA0A0..0xFFFF */
12437 fontp
->baseline_offset
12438 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
12439 ? (long) value
: 0);
12440 fontp
->relative_compose
12441 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
12442 ? (long) value
: 0);
12443 fontp
->default_ascent
12444 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
12445 ? (long) value
: 0);
12447 /* Set global flag fonts_changed_p to non-zero if the font loaded
12448 has a character with a smaller width than any other character
12449 before, or if the font loaded has a smalle>r height than any
12450 other font loaded before. If this happens, it will make a
12451 glyph matrix reallocation necessary. */
12452 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
12459 /* Return a pointer to struct font_info of a font named FONTNAME for
12460 frame F. If no such font is loaded, return NULL. */
12463 x_query_font (f
, fontname
)
12465 register char *fontname
;
12467 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
12470 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
12471 if (dpyinfo
->font_table
[i
].name
12472 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
12473 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
12474 return (dpyinfo
->font_table
+ i
);
12479 /* Find a CCL program for a font specified by FONTP, and set the member
12480 `encoder' of the structure. */
12483 x_find_ccl_program (fontp
)
12484 struct font_info
*fontp
;
12486 Lisp_Object list
, elt
;
12488 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
12492 && STRINGP (XCAR (elt
))
12493 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
12499 struct ccl_program
*ccl
12500 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
12502 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
12505 fontp
->font_encoder
= ccl
;
12511 /***********************************************************************
12513 ***********************************************************************/
12515 #ifdef USE_X_TOOLKIT
12516 static XrmOptionDescRec emacs_options
[] = {
12517 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
12518 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
12520 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12521 XrmoptionSepArg
, NULL
},
12522 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
12524 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12525 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12526 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
12527 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12528 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
12529 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
12530 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
12532 #endif /* USE_X_TOOLKIT */
12534 static int x_initialized
;
12536 #ifdef MULTI_KBOARD
12537 /* Test whether two display-name strings agree up to the dot that separates
12538 the screen number from the server number. */
12540 same_x_server (name1
, name2
)
12541 char *name1
, *name2
;
12543 int seen_colon
= 0;
12544 unsigned char *system_name
= XSTRING (Vsystem_name
)->data
;
12545 int system_name_length
= strlen (system_name
);
12546 int length_until_period
= 0;
12548 while (system_name
[length_until_period
] != 0
12549 && system_name
[length_until_period
] != '.')
12550 length_until_period
++;
12552 /* Treat `unix' like an empty host name. */
12553 if (! strncmp (name1
, "unix:", 5))
12555 if (! strncmp (name2
, "unix:", 5))
12557 /* Treat this host's name like an empty host name. */
12558 if (! strncmp (name1
, system_name
, system_name_length
)
12559 && name1
[system_name_length
] == ':')
12560 name1
+= system_name_length
;
12561 if (! strncmp (name2
, system_name
, system_name_length
)
12562 && name2
[system_name_length
] == ':')
12563 name2
+= system_name_length
;
12564 /* Treat this host's domainless name like an empty host name. */
12565 if (! strncmp (name1
, system_name
, length_until_period
)
12566 && name1
[length_until_period
] == ':')
12567 name1
+= length_until_period
;
12568 if (! strncmp (name2
, system_name
, length_until_period
)
12569 && name2
[length_until_period
] == ':')
12570 name2
+= length_until_period
;
12572 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
12576 if (seen_colon
&& *name1
== '.')
12580 && (*name1
== '.' || *name1
== '\0')
12581 && (*name2
== '.' || *name2
== '\0'));
12585 struct x_display_info
*
12586 x_term_init (display_name
, xrm_option
, resource_name
)
12587 Lisp_Object display_name
;
12589 char *resource_name
;
12593 struct x_display_info
*dpyinfo
;
12598 if (!x_initialized
)
12604 #ifdef USE_X_TOOLKIT
12605 /* weiner@footloose.sps.mot.com reports that this causes
12607 X protocol error: BadAtom (invalid Atom parameter)
12608 on protocol request 18skiloaf.
12609 So let's not use it until R6. */
12610 #ifdef HAVE_X11XTR6
12611 XtSetLanguageProc (NULL
, NULL
, NULL
);
12622 argv
[argc
++] = "-xrm";
12623 argv
[argc
++] = xrm_option
;
12625 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
12626 resource_name
, EMACS_CLASS
,
12627 emacs_options
, XtNumber (emacs_options
),
12630 #ifdef HAVE_X11XTR6
12631 /* I think this is to compensate for XtSetLanguageProc. */
12636 #else /* not USE_X_TOOLKIT */
12638 XSetLocaleModifiers ("");
12640 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
12641 #endif /* not USE_X_TOOLKIT */
12643 /* Detect failure. */
12650 /* We have definitely succeeded. Record the new connection. */
12652 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
12654 #ifdef MULTI_KBOARD
12656 struct x_display_info
*share
;
12659 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
12660 share
= share
->next
, tail
= XCDR (tail
))
12661 if (same_x_server (XSTRING (XCAR (XCAR (tail
)))->data
,
12662 XSTRING (display_name
)->data
))
12665 dpyinfo
->kboard
= share
->kboard
;
12668 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
12669 init_kboard (dpyinfo
->kboard
);
12670 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
12672 char *vendor
= ServerVendor (dpy
);
12673 dpyinfo
->kboard
->Vsystem_key_alist
12674 = call1 (Qvendor_specific_keysyms
,
12675 build_string (vendor
? vendor
: ""));
12678 dpyinfo
->kboard
->next_kboard
= all_kboards
;
12679 all_kboards
= dpyinfo
->kboard
;
12680 /* Don't let the initial kboard remain current longer than necessary.
12681 That would cause problems if a file loaded on startup tries to
12682 prompt in the mini-buffer. */
12683 if (current_kboard
== initial_kboard
)
12684 current_kboard
= dpyinfo
->kboard
;
12686 dpyinfo
->kboard
->reference_count
++;
12690 /* Put this display on the chain. */
12691 dpyinfo
->next
= x_display_list
;
12692 x_display_list
= dpyinfo
;
12694 /* Put it on x_display_name_list as well, to keep them parallel. */
12695 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
12696 x_display_name_list
);
12697 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
12699 dpyinfo
->display
= dpy
;
12702 XSetAfterFunction (x_current_display
, x_trace_wire
);
12706 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
12707 + STRING_BYTES (XSTRING (Vsystem_name
))
12709 sprintf (dpyinfo
->x_id_name
, "%s@%s",
12710 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
12712 /* Figure out which modifier bits mean what. */
12713 x_find_modifier_meanings (dpyinfo
);
12715 /* Get the scroll bar cursor. */
12716 dpyinfo
->vertical_scroll_bar_cursor
12717 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
12719 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
12720 resource_name
, EMACS_CLASS
);
12721 #ifdef HAVE_XRMSETDATABASE
12722 XrmSetDatabase (dpyinfo
->display
, xrdb
);
12724 dpyinfo
->display
->db
= xrdb
;
12726 /* Put the rdb where we can find it in a way that works on
12728 dpyinfo
->xrdb
= xrdb
;
12730 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
12731 DefaultScreen (dpyinfo
->display
));
12732 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
12733 &dpyinfo
->n_planes
);
12734 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
12735 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
12736 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
12737 dpyinfo
->grabbed
= 0;
12738 dpyinfo
->reference_count
= 0;
12739 dpyinfo
->icon_bitmap_id
= -1;
12740 dpyinfo
->font_table
= NULL
;
12741 dpyinfo
->n_fonts
= 0;
12742 dpyinfo
->font_table_size
= 0;
12743 dpyinfo
->bitmaps
= 0;
12744 dpyinfo
->bitmaps_size
= 0;
12745 dpyinfo
->bitmaps_last
= 0;
12746 dpyinfo
->scratch_cursor_gc
= 0;
12747 dpyinfo
->mouse_face_mouse_frame
= 0;
12748 dpyinfo
->mouse_face_deferred_gc
= 0;
12749 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
12750 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
12751 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
12752 dpyinfo
->mouse_face_window
= Qnil
;
12753 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
12754 dpyinfo
->mouse_face_defer
= 0;
12755 dpyinfo
->x_focus_frame
= 0;
12756 dpyinfo
->x_focus_event_frame
= 0;
12757 dpyinfo
->x_highlight_frame
= 0;
12758 dpyinfo
->image_cache
= make_image_cache ();
12761 int screen_number
= XScreenNumberOfScreen (dpyinfo
->screen
);
12762 double pixels
= DisplayHeight (dpyinfo
->display
, screen_number
);
12763 double mm
= DisplayHeightMM (dpyinfo
->display
, screen_number
);
12764 dpyinfo
->resy
= pixels
* 25.4 / mm
;
12765 pixels
= DisplayWidth (dpyinfo
->display
, screen_number
);
12766 mm
= DisplayWidthMM (dpyinfo
->display
, screen_number
);
12767 dpyinfo
->resx
= pixels
* 25.4 / mm
;
12770 dpyinfo
->Xatom_wm_protocols
12771 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
12772 dpyinfo
->Xatom_wm_take_focus
12773 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
12774 dpyinfo
->Xatom_wm_save_yourself
12775 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
12776 dpyinfo
->Xatom_wm_delete_window
12777 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
12778 dpyinfo
->Xatom_wm_change_state
12779 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
12780 dpyinfo
->Xatom_wm_configure_denied
12781 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
12782 dpyinfo
->Xatom_wm_window_moved
12783 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
12784 dpyinfo
->Xatom_editres
12785 = XInternAtom (dpyinfo
->display
, "Editres", False
);
12786 dpyinfo
->Xatom_CLIPBOARD
12787 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
12788 dpyinfo
->Xatom_TIMESTAMP
12789 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
12790 dpyinfo
->Xatom_TEXT
12791 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
12792 dpyinfo
->Xatom_COMPOUND_TEXT
12793 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
12794 dpyinfo
->Xatom_DELETE
12795 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
12796 dpyinfo
->Xatom_MULTIPLE
12797 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
12798 dpyinfo
->Xatom_INCR
12799 = XInternAtom (dpyinfo
->display
, "INCR", False
);
12800 dpyinfo
->Xatom_EMACS_TMP
12801 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
12802 dpyinfo
->Xatom_TARGETS
12803 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
12804 dpyinfo
->Xatom_NULL
12805 = XInternAtom (dpyinfo
->display
, "NULL", False
);
12806 dpyinfo
->Xatom_ATOM_PAIR
12807 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
12808 /* For properties of font. */
12809 dpyinfo
->Xatom_PIXEL_SIZE
12810 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
12811 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
12812 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
12813 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
12814 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
12815 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
12816 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
12818 /* Ghostscript support. */
12819 dpyinfo
->Xatom_PAGE
= XInternAtom (dpyinfo
->display
, "PAGE", False
);
12820 dpyinfo
->Xatom_DONE
= XInternAtom (dpyinfo
->display
, "DONE", False
);
12822 dpyinfo
->Xatom_Scrollbar
= XInternAtom (dpyinfo
->display
, "SCROLLBAR",
12825 dpyinfo
->cut_buffers_initialized
= 0;
12827 connection
= ConnectionNumber (dpyinfo
->display
);
12828 dpyinfo
->connection
= connection
;
12833 null_bits
[0] = 0x00;
12835 dpyinfo
->null_pixel
12836 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12837 null_bits
, 1, 1, (long) 0, (long) 0,
12842 extern int gray_bitmap_width
, gray_bitmap_height
;
12843 extern unsigned char *gray_bitmap_bits
;
12845 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
12847 gray_bitmap_width
, gray_bitmap_height
,
12848 (unsigned long) 1, (unsigned long) 0, 1);
12851 #ifdef subprocesses
12852 /* This is only needed for distinguishing keyboard and process input. */
12853 if (connection
!= 0)
12854 add_keyboard_wait_descriptor (connection
);
12857 #ifndef F_SETOWN_BUG
12859 #ifdef F_SETOWN_SOCK_NEG
12860 /* stdin is a socket here */
12861 fcntl (connection
, F_SETOWN
, -getpid ());
12862 #else /* ! defined (F_SETOWN_SOCK_NEG) */
12863 fcntl (connection
, F_SETOWN
, getpid ());
12864 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
12865 #endif /* ! defined (F_SETOWN) */
12866 #endif /* F_SETOWN_BUG */
12869 if (interrupt_input
)
12870 init_sigio (connection
);
12871 #endif /* ! defined (SIGIO) */
12874 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
12875 /* Make sure that we have a valid font for dialog boxes
12876 so that Xt does not crash. */
12878 Display
*dpy
= dpyinfo
->display
;
12879 XrmValue d
, fr
, to
;
12883 d
.addr
= (XPointer
)&dpy
;
12884 d
.size
= sizeof (Display
*);
12885 fr
.addr
= XtDefaultFont
;
12886 fr
.size
= sizeof (XtDefaultFont
);
12887 to
.size
= sizeof (Font
*);
12888 to
.addr
= (XPointer
)&font
;
12889 count
= x_catch_errors (dpy
);
12890 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
12892 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
12893 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
12894 x_uncatch_errors (dpy
, count
);
12904 /* Get rid of display DPYINFO, assuming all frames are already gone,
12905 and without sending any more commands to the X server. */
12908 x_delete_display (dpyinfo
)
12909 struct x_display_info
*dpyinfo
;
12911 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
12913 /* Discard this display from x_display_name_list and x_display_list.
12914 We can't use Fdelq because that can quit. */
12915 if (! NILP (x_display_name_list
)
12916 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
12917 x_display_name_list
= XCDR (x_display_name_list
);
12922 tail
= x_display_name_list
;
12923 while (CONSP (tail
) && CONSP (XCDR (tail
)))
12925 if (EQ (XCAR (XCDR (tail
)),
12926 dpyinfo
->name_list_element
))
12928 XCDR (tail
) = XCDR (XCDR (tail
));
12931 tail
= XCDR (tail
);
12935 if (x_display_list
== dpyinfo
)
12936 x_display_list
= dpyinfo
->next
;
12939 struct x_display_info
*tail
;
12941 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
12942 if (tail
->next
== dpyinfo
)
12943 tail
->next
= tail
->next
->next
;
12946 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12947 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
12948 XrmDestroyDatabase (dpyinfo
->xrdb
);
12951 #ifdef MULTI_KBOARD
12952 if (--dpyinfo
->kboard
->reference_count
== 0)
12953 delete_kboard (dpyinfo
->kboard
);
12955 xfree (dpyinfo
->font_table
);
12956 xfree (dpyinfo
->x_id_name
);
12960 /* Set up use of X before we make the first connection. */
12962 static struct redisplay_interface x_redisplay_interface
=
12967 x_clear_end_of_line
,
12969 x_after_update_window_line
,
12970 x_update_window_begin
,
12971 x_update_window_end
,
12974 x_get_glyph_overhangs
,
12975 x_fix_overlapping_area
12981 rif
= &x_redisplay_interface
;
12983 clear_frame_hook
= x_clear_frame
;
12984 ins_del_lines_hook
= x_ins_del_lines
;
12985 change_line_highlight_hook
= x_change_line_highlight
;
12986 delete_glyphs_hook
= x_delete_glyphs
;
12987 ring_bell_hook
= XTring_bell
;
12988 reset_terminal_modes_hook
= XTreset_terminal_modes
;
12989 set_terminal_modes_hook
= XTset_terminal_modes
;
12990 update_begin_hook
= x_update_begin
;
12991 update_end_hook
= x_update_end
;
12992 set_terminal_window_hook
= XTset_terminal_window
;
12993 read_socket_hook
= XTread_socket
;
12994 frame_up_to_date_hook
= XTframe_up_to_date
;
12995 reassert_line_highlight_hook
= XTreassert_line_highlight
;
12996 mouse_position_hook
= XTmouse_position
;
12997 frame_rehighlight_hook
= XTframe_rehighlight
;
12998 frame_raise_lower_hook
= XTframe_raise_lower
;
12999 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
13000 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
13001 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
13002 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
13003 estimate_mode_line_height_hook
= x_estimate_mode_line_height
;
13005 scroll_region_ok
= 1; /* we'll scroll partial frames */
13006 char_ins_del_ok
= 0; /* just as fast to write the line */
13007 line_ins_del_ok
= 1; /* we'll just blt 'em */
13008 fast_clear_end_of_line
= 1; /* X does this well */
13009 memory_below_frame
= 0; /* we don't remember what scrolls
13014 last_tool_bar_item
= -1;
13015 any_help_event_p
= 0;
13017 /* Try to use interrupt input; if we can't, then start polling. */
13018 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
13020 #ifdef USE_X_TOOLKIT
13021 XtToolkitInitialize ();
13022 Xt_app_con
= XtCreateApplicationContext ();
13023 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
13025 #if USE_TOOLKIT_SCROLL_BARS
13026 xaw3d_arrow_scroll
= False
;
13027 xaw3d_pick_top
= True
;
13030 /* Note that there is no real way portable across R3/R4 to get the
13031 original error handler. */
13032 XSetErrorHandler (x_error_handler
);
13033 XSetIOErrorHandler (x_io_error_quitter
);
13035 /* Disable Window Change signals; they are handled by X events. */
13037 signal (SIGWINCH
, SIG_DFL
);
13038 #endif /* ! defined (SIGWINCH) */
13040 signal (SIGPIPE
, x_connection_signal
);
13047 staticpro (&x_error_message_string
);
13048 x_error_message_string
= Qnil
;
13050 staticpro (&x_display_name_list
);
13051 x_display_name_list
= Qnil
;
13053 staticpro (&last_mouse_scroll_bar
);
13054 last_mouse_scroll_bar
= Qnil
;
13056 staticpro (&Qvendor_specific_keysyms
);
13057 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
13059 staticpro (&last_mouse_press_frame
);
13060 last_mouse_press_frame
= Qnil
;
13062 staticpro (&help_echo
);
13064 staticpro (&previous_help_echo
);
13065 previous_help_echo
= Qnil
;
13067 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
,
13068 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13069 For example, if a block cursor is over a tab, it will be drawn as\n\
13070 wide as that tab on the display.");
13071 x_stretch_cursor_p
= 0;
13073 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p
,
13074 "If not nil, Emacs uses toolkit scroll bars.");
13075 #if USE_TOOLKIT_SCROLL_BARS
13076 x_toolkit_scroll_bars_p
= 1;
13078 x_toolkit_scroll_bars_p
= 0;
13081 defsubr (&Sxt_process_timeouts
);
13082 staticpro (&last_mouse_motion_frame
);
13083 last_mouse_motion_frame
= Qnil
;
13086 #endif /* not HAVE_X_WINDOWS */