(note_mouse_highlight): Don't use mouse-face if hidden.
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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)
10 any later version.
11
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.
16
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. */
21
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
24
25 #include <config.h>
26
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. */
29 #include <signal.h>
30
31 #include <stdio.h>
32
33 #ifdef HAVE_X_WINDOWS
34
35 #include "lisp.h"
36 #include "blockinput.h"
37
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"
41
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
46
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
56
57 #include "systty.h"
58 #include "systime.h"
59
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
69
70 #include "charset.h"
71 #include "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #include "gnu.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85 #include "process.h"
86 #include "atimer.h"
87 #include "keymap.h"
88
89 #ifdef USE_X_TOOLKIT
90 #include <X11/Shell.h>
91 #endif
92
93 #ifdef HAVE_SYS_TIME_H
94 #include <sys/time.h>
95 #endif
96 #ifdef HAVE_UNISTD_H
97 #include <unistd.h>
98 #endif
99
100 #ifdef USE_LUCID
101 extern int xlwmenu_window_p P_ ((Widget w, Window window));
102 extern void xlwmenu_redisplay P_ ((Widget));
103 #endif
104
105 #ifdef USE_X_TOOLKIT
106
107 extern void free_frame_menubar P_ ((struct frame *));
108 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
109 int));
110
111 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112 #define HACK_EDITRES
113 extern void _XEditResCheckMessages ();
114 #endif /* not NO_EDITRES */
115
116 /* Include toolkit specific headers for the scroll bar widget. */
117
118 #ifdef USE_TOOLKIT_SCROLL_BARS
119 #if defined USE_MOTIF
120 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
121 #include <Xm/ScrollBar.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
123
124 #ifdef HAVE_XAW3D
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
133 #ifndef XtNpickTop
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
138
139 #endif /* USE_X_TOOLKIT */
140
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
144 #endif
145
146 #ifdef USE_X_TOOLKIT
147 #include "widget.h"
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
150 #endif
151 #endif
152
153 #define abs(x) ((x) < 0 ? -(x) : (x))
154
155 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
156
157 \f
158 /* Fringe bitmaps. */
159
160 enum fringe_bitmap_type
161 {
162 NO_FRINGE_BITMAP,
163 LEFT_TRUNCATION_BITMAP,
164 RIGHT_TRUNCATION_BITMAP,
165 OVERLAY_ARROW_BITMAP,
166 CONTINUED_LINE_BITMAP,
167 CONTINUATION_LINE_BITMAP,
168 ZV_LINE_BITMAP
169 };
170
171 /* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
173
174 #define zv_width 8
175 #define zv_height 72
176 #define zv_period 3
177 static unsigned char zv_bits[] = {
178 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
179 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
180 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
181 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
182 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
183 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
186
187 /* An arrow like this: `<-'. */
188
189 #define left_width 8
190 #define left_height 8
191 static unsigned char left_bits[] = {
192 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
193
194 /* Right truncation arrow bitmap `->'. */
195
196 #define right_width 8
197 #define right_height 8
198 static unsigned char right_bits[] = {
199 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
200
201 /* Marker for continued lines. */
202
203 #define continued_width 8
204 #define continued_height 8
205 static unsigned char continued_bits[] = {
206 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
207
208 /* Marker for continuation lines. */
209
210 #define continuation_width 8
211 #define continuation_height 8
212 static unsigned char continuation_bits[] = {
213 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
214
215 /* Overlay arrow bitmap. */
216
217 #if 0
218 /* A bomb. */
219 #define ov_width 8
220 #define ov_height 8
221 static unsigned char ov_bits[] = {
222 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
223 #else
224 /* A triangular arrow. */
225 #define ov_width 8
226 #define ov_height 8
227 static unsigned char ov_bits[] = {
228 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
229
230 #endif
231
232 extern Lisp_Object Qhelp_echo;
233
234 \f
235 /* Non-nil means Emacs uses toolkit scroll bars. */
236
237 Lisp_Object Vx_toolkit_scroll_bars;
238
239 /* If a string, XTread_socket generates an event to display that string.
240 (The display is done in read_char.) */
241
242 static Lisp_Object help_echo;
243 static Lisp_Object help_echo_window;
244 static Lisp_Object help_echo_object;
245 static int help_echo_pos;
246
247 /* Temporary variable for XTread_socket. */
248
249 static Lisp_Object previous_help_echo;
250
251 /* Non-zero means that a HELP_EVENT has been generated since Emacs
252 start. */
253
254 static int any_help_event_p;
255
256 /* Non-zero means autoselect window with the mouse cursor. */
257
258 int mouse_autoselect_window;
259
260 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
261 static Lisp_Object last_window;
262
263 /* Non-zero means draw block and hollow cursor as wide as the glyph
264 under it. For example, if a block cursor is over a tab, it will be
265 drawn as wide as that tab on the display. */
266
267 int x_stretch_cursor_p;
268
269 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
270
271 int x_use_underline_position_properties;
272
273 /* This is a chain of structures for all the X displays currently in
274 use. */
275
276 struct x_display_info *x_display_list;
277
278 /* This is a list of cons cells, each of the form (NAME
279 . FONT-LIST-CACHE), one for each element of x_display_list and in
280 the same order. NAME is the name of the frame. FONT-LIST-CACHE
281 records previous values returned by x-list-fonts. */
282
283 Lisp_Object x_display_name_list;
284
285 /* Frame being updated by update_frame. This is declared in term.c.
286 This is set by update_begin and looked at by all the XT functions.
287 It is zero while not inside an update. In that case, the XT
288 functions assume that `selected_frame' is the frame to apply to. */
289
290 extern struct frame *updating_frame;
291
292 /* This is a frame waiting to be auto-raised, within XTread_socket. */
293
294 struct frame *pending_autoraise_frame;
295
296 #ifdef USE_X_TOOLKIT
297 /* The application context for Xt use. */
298 XtAppContext Xt_app_con;
299 static String Xt_default_resources[] = {0};
300 #endif /* USE_X_TOOLKIT */
301
302 /* Nominal cursor position -- where to draw output.
303 HPOS and VPOS are window relative glyph matrix coordinates.
304 X and Y are window relative pixel coordinates. */
305
306 struct cursor_pos output_cursor;
307
308 /* Non-zero means user is interacting with a toolkit scroll bar. */
309
310 static int toolkit_scroll_bar_interaction;
311
312 /* Mouse movement.
313
314 Formerly, we used PointerMotionHintMask (in standard_event_mask)
315 so that we would have to call XQueryPointer after each MotionNotify
316 event to ask for another such event. However, this made mouse tracking
317 slow, and there was a bug that made it eventually stop.
318
319 Simply asking for MotionNotify all the time seems to work better.
320
321 In order to avoid asking for motion events and then throwing most
322 of them away or busy-polling the server for mouse positions, we ask
323 the server for pointer motion hints. This means that we get only
324 one event per group of mouse movements. "Groups" are delimited by
325 other kinds of events (focus changes and button clicks, for
326 example), or by XQueryPointer calls; when one of these happens, we
327 get another MotionNotify event the next time the mouse moves. This
328 is at least as efficient as getting motion events when mouse
329 tracking is on, and I suspect only negligibly worse when tracking
330 is off. */
331
332 /* Where the mouse was last time we reported a mouse event. */
333
334 FRAME_PTR last_mouse_frame;
335 static XRectangle last_mouse_glyph;
336 static Lisp_Object last_mouse_press_frame;
337
338 /* The scroll bar in which the last X motion event occurred.
339
340 If the last X motion event occurred in a scroll bar, we set this so
341 XTmouse_position can know whether to report a scroll bar motion or
342 an ordinary motion.
343
344 If the last X motion event didn't occur in a scroll bar, we set
345 this to Qnil, to tell XTmouse_position to return an ordinary motion
346 event. */
347
348 static Lisp_Object last_mouse_scroll_bar;
349
350 /* This is a hack. We would really prefer that XTmouse_position would
351 return the time associated with the position it returns, but there
352 doesn't seem to be any way to wrest the time-stamp from the server
353 along with the position query. So, we just keep track of the time
354 of the last movement we received, and return that in hopes that
355 it's somewhat accurate. */
356
357 static Time last_mouse_movement_time;
358
359 /* Incremented by XTread_socket whenever it really tries to read
360 events. */
361
362 #ifdef __STDC__
363 static int volatile input_signal_count;
364 #else
365 static int input_signal_count;
366 #endif
367
368 /* Used locally within XTread_socket. */
369
370 static int x_noop_count;
371
372 /* Initial values of argv and argc. */
373
374 extern char **initial_argv;
375 extern int initial_argc;
376
377 extern Lisp_Object Vcommand_line_args, Vsystem_name;
378
379 /* Tells if a window manager is present or not. */
380
381 extern Lisp_Object Vx_no_window_manager;
382
383 extern Lisp_Object Qface, Qmouse_face;
384
385 extern int errno;
386
387 /* A mask of extra modifier bits to put into every keyboard char. */
388
389 extern EMACS_INT extra_keyboard_modifiers;
390
391 /* The keysyms to use for the various modifiers. */
392
393 Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
394 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
395
396 static Lisp_Object Qvendor_specific_keysyms;
397 static Lisp_Object Qlatin_1, Qutf_8;
398
399 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
400 extern Lisp_Object x_icon_type P_ ((struct frame *));
401
402
403 /* Enumeration for overriding/changing the face to use for drawing
404 glyphs in x_draw_glyphs. */
405
406 enum draw_glyphs_face
407 {
408 DRAW_NORMAL_TEXT,
409 DRAW_INVERSE_VIDEO,
410 DRAW_CURSOR,
411 DRAW_MOUSE_FACE,
412 DRAW_IMAGE_RAISED,
413 DRAW_IMAGE_SUNKEN
414 };
415
416 static int cursor_in_mouse_face_p P_ ((struct window *));
417 static int clear_mouse_face P_ ((struct x_display_info *));
418 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
419 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
420 static const XColor *x_color_cells P_ ((Display *, int *));
421 static void x_update_window_end P_ ((struct window *, int, int));
422 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
423 void x_delete_display P_ ((struct x_display_info *));
424 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
425 unsigned));
426 static int fast_find_position P_ ((struct window *, int, int *, int *,
427 int *, int *, Lisp_Object));
428 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
429 int *, int *, int *, int *, int));
430 static void set_output_cursor P_ ((struct cursor_pos *));
431 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
432 int *, int *, int *, int));
433 static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
434 int, int));
435 static void note_mouse_highlight P_ ((struct frame *, int, int));
436 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
437 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
438 static void show_mouse_face P_ ((struct x_display_info *,
439 enum draw_glyphs_face));
440 static int x_io_error_quitter P_ ((Display *));
441 int x_catch_errors P_ ((Display *));
442 void x_uncatch_errors P_ ((Display *, int));
443 void x_lower_frame P_ ((struct frame *));
444 void x_scroll_bar_clear P_ ((struct frame *));
445 int x_had_errors_p P_ ((Display *));
446 void x_wm_set_size_hint P_ ((struct frame *, long, int));
447 void x_raise_frame P_ ((struct frame *));
448 void x_set_window_size P_ ((struct frame *, int, int, int));
449 void x_wm_set_window_state P_ ((struct frame *, int));
450 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
451 void x_initialize P_ ((void));
452 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
453 static int x_compute_min_glyph_bounds P_ ((struct frame *));
454 static void x_draw_phys_cursor_glyph P_ ((struct window *,
455 struct glyph_row *,
456 enum draw_glyphs_face));
457 static void x_update_end P_ ((struct frame *));
458 static void XTframe_up_to_date P_ ((struct frame *));
459 static void XTset_terminal_modes P_ ((void));
460 static void XTreset_terminal_modes P_ ((void));
461 static void XTcursor_to P_ ((int, int, int, int));
462 static void x_write_glyphs P_ ((struct glyph *, int));
463 static void x_clear_end_of_line P_ ((int));
464 static void x_clear_frame P_ ((void));
465 static void x_clear_cursor P_ ((struct window *));
466 static void frame_highlight P_ ((struct frame *));
467 static void frame_unhighlight P_ ((struct frame *));
468 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
469 static int x_focus_changed P_ ((int,
470 int,
471 struct x_display_info *,
472 struct frame *,
473 struct input_event *,
474 int));
475 static int x_detect_focus_change P_ ((struct x_display_info *,
476 XEvent *,
477 struct input_event *,
478 int));
479 static void XTframe_rehighlight P_ ((struct frame *));
480 static void x_frame_rehighlight P_ ((struct x_display_info *));
481 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
482 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
483 enum text_cursor_kinds));
484 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
485 XRectangle *));
486 static void expose_frame P_ ((struct frame *, int, int, int, int));
487 static int expose_window_tree P_ ((struct window *, XRectangle *));
488 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
489 struct glyph_row *));
490 static int expose_window P_ ((struct window *, XRectangle *));
491 static void expose_area P_ ((struct window *, struct glyph_row *,
492 XRectangle *, enum glyph_row_area));
493 static int expose_line P_ ((struct window *, struct glyph_row *,
494 XRectangle *));
495 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
496 static void x_update_window_cursor P_ ((struct window *, int));
497 static void x_erase_phys_cursor P_ ((struct window *));
498 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
499 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
500 enum fringe_bitmap_type, int left_p));
501
502 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
503 GC, int));
504 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
505 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
506 static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
507 int, int, int, int));
508 static void x_flush P_ ((struct frame *f));
509 static void x_update_begin P_ ((struct frame *));
510 static void x_update_window_begin P_ ((struct window *));
511 static void x_draw_vertical_border P_ ((struct window *));
512 static void x_after_update_window_line P_ ((struct glyph_row *));
513 static INLINE void take_vertical_position_into_account P_ ((struct it *));
514 static void x_produce_stretch_glyph P_ ((struct it *));
515 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
516 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
517 enum scroll_bar_part *,
518 Lisp_Object *, Lisp_Object *,
519 unsigned long *));
520 static void x_check_fullscreen P_ ((struct frame *));
521 static void x_check_fullscreen_move P_ ((struct frame *));
522
523 /* Flush display of frame F, or of all frames if F is null. */
524
525 static void
526 x_flush (f)
527 struct frame *f;
528 {
529 BLOCK_INPUT;
530 if (f == NULL)
531 {
532 Lisp_Object rest, frame;
533 FOR_EACH_FRAME (rest, frame)
534 x_flush (XFRAME (frame));
535 }
536 else if (FRAME_X_P (f))
537 XFlush (FRAME_X_DISPLAY (f));
538 UNBLOCK_INPUT;
539 }
540
541
542 /* Remove calls to XFlush by defining XFlush to an empty replacement.
543 Calls to XFlush should be unnecessary because the X output buffer
544 is flushed automatically as needed by calls to XPending,
545 XNextEvent, or XWindowEvent according to the XFlush man page.
546 XTread_socket calls XPending. Removing XFlush improves
547 performance. */
548
549 #define XFlush(DISPLAY) (void) 0
550
551 \f
552 /***********************************************************************
553 Debugging
554 ***********************************************************************/
555
556 #if 0
557
558 /* This is a function useful for recording debugging information about
559 the sequence of occurrences in this file. */
560
561 struct record
562 {
563 char *locus;
564 int type;
565 };
566
567 struct record event_record[100];
568
569 int event_record_index;
570
571 record_event (locus, type)
572 char *locus;
573 int type;
574 {
575 if (event_record_index == sizeof (event_record) / sizeof (struct record))
576 event_record_index = 0;
577
578 event_record[event_record_index].locus = locus;
579 event_record[event_record_index].type = type;
580 event_record_index++;
581 }
582
583 #endif /* 0 */
584
585
586 \f
587 /* Return the struct x_display_info corresponding to DPY. */
588
589 struct x_display_info *
590 x_display_info_for_display (dpy)
591 Display *dpy;
592 {
593 struct x_display_info *dpyinfo;
594
595 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
596 if (dpyinfo->display == dpy)
597 return dpyinfo;
598
599 return 0;
600 }
601
602
603 \f
604 /***********************************************************************
605 Starting and ending an update
606 ***********************************************************************/
607
608 /* Start an update of frame F. This function is installed as a hook
609 for update_begin, i.e. it is called when update_begin is called.
610 This function is called prior to calls to x_update_window_begin for
611 each window being updated. Currently, there is nothing to do here
612 because all interesting stuff is done on a window basis. */
613
614 static void
615 x_update_begin (f)
616 struct frame *f;
617 {
618 /* Nothing to do. */
619 }
620
621
622 /* Start update of window W. Set the global variable updated_window
623 to the window being updated and set output_cursor to the cursor
624 position of W. */
625
626 static void
627 x_update_window_begin (w)
628 struct window *w;
629 {
630 struct frame *f = XFRAME (WINDOW_FRAME (w));
631 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
632
633 updated_window = w;
634 set_output_cursor (&w->cursor);
635
636 BLOCK_INPUT;
637
638 if (f == display_info->mouse_face_mouse_frame)
639 {
640 /* Don't do highlighting for mouse motion during the update. */
641 display_info->mouse_face_defer = 1;
642
643 /* If F needs to be redrawn, simply forget about any prior mouse
644 highlighting. */
645 if (FRAME_GARBAGED_P (f))
646 display_info->mouse_face_window = Qnil;
647
648 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
649 their mouse_face_p flag set, which means that they are always
650 unequal to rows in a desired matrix which never have that
651 flag set. So, rows containing mouse-face glyphs are never
652 scrolled, and we don't have to switch the mouse highlight off
653 here to prevent it from being scrolled. */
654
655 /* Can we tell that this update does not affect the window
656 where the mouse highlight is? If so, no need to turn off.
657 Likewise, don't do anything if the frame is garbaged;
658 in that case, the frame's current matrix that we would use
659 is all wrong, and we will redisplay that line anyway. */
660 if (!NILP (display_info->mouse_face_window)
661 && w == XWINDOW (display_info->mouse_face_window))
662 {
663 int i;
664
665 for (i = 0; i < w->desired_matrix->nrows; ++i)
666 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
667 break;
668
669 if (i < w->desired_matrix->nrows)
670 clear_mouse_face (display_info);
671 }
672 #endif /* 0 */
673 }
674
675 UNBLOCK_INPUT;
676 }
677
678
679 /* Draw a vertical window border to the right of window W if W doesn't
680 have vertical scroll bars. */
681
682 static void
683 x_draw_vertical_border (w)
684 struct window *w;
685 {
686 struct frame *f = XFRAME (WINDOW_FRAME (w));
687
688 /* Redraw borders between horizontally adjacent windows. Don't
689 do it for frames with vertical scroll bars because either the
690 right scroll bar of a window, or the left scroll bar of its
691 neighbor will suffice as a border. */
692 if (!WINDOW_RIGHTMOST_P (w)
693 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
694 {
695 int x0, x1, y0, y1;
696
697 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
698 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
699 y1 -= 1;
700
701 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
702 f->output_data.x->normal_gc, x1, y0, x1, y1);
703 }
704 }
705
706
707 /* End update of window W (which is equal to updated_window).
708
709 Draw vertical borders between horizontally adjacent windows, and
710 display W's cursor if CURSOR_ON_P is non-zero.
711
712 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
713 glyphs in mouse-face were overwritten. In that case we have to
714 make sure that the mouse-highlight is properly redrawn.
715
716 W may be a menu bar pseudo-window in case we don't have X toolkit
717 support. Such windows don't have a cursor, so don't display it
718 here. */
719
720 static void
721 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
722 struct window *w;
723 int cursor_on_p, mouse_face_overwritten_p;
724 {
725 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
726
727 if (!w->pseudo_window_p)
728 {
729 BLOCK_INPUT;
730
731 if (cursor_on_p)
732 x_display_and_set_cursor (w, 1, output_cursor.hpos,
733 output_cursor.vpos,
734 output_cursor.x, output_cursor.y);
735
736 x_draw_vertical_border (w);
737 UNBLOCK_INPUT;
738 }
739
740 /* If a row with mouse-face was overwritten, arrange for
741 XTframe_up_to_date to redisplay the mouse highlight. */
742 if (mouse_face_overwritten_p)
743 {
744 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
745 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
746 dpyinfo->mouse_face_window = Qnil;
747 }
748
749 updated_window = NULL;
750 }
751
752
753 /* End update of frame F. This function is installed as a hook in
754 update_end. */
755
756 static void
757 x_update_end (f)
758 struct frame *f;
759 {
760 /* Mouse highlight may be displayed again. */
761 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
762
763 BLOCK_INPUT;
764 XFlush (FRAME_X_DISPLAY (f));
765 UNBLOCK_INPUT;
766 }
767
768
769 /* This function is called from various places in xdisp.c whenever a
770 complete update has been performed. The global variable
771 updated_window is not available here. */
772
773 static void
774 XTframe_up_to_date (f)
775 struct frame *f;
776 {
777 if (FRAME_X_P (f))
778 {
779 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
780
781 if (dpyinfo->mouse_face_deferred_gc
782 || f == dpyinfo->mouse_face_mouse_frame)
783 {
784 BLOCK_INPUT;
785 if (dpyinfo->mouse_face_mouse_frame)
786 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
787 dpyinfo->mouse_face_mouse_x,
788 dpyinfo->mouse_face_mouse_y);
789 dpyinfo->mouse_face_deferred_gc = 0;
790 UNBLOCK_INPUT;
791 }
792 }
793 }
794
795
796 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
797 arrow bitmaps, or clear the fringes if no bitmaps are required
798 before DESIRED_ROW is made current. The window being updated is
799 found in updated_window. This function It is called from
800 update_window_line only if it is known that there are differences
801 between bitmaps to be drawn between current row and DESIRED_ROW. */
802
803 static void
804 x_after_update_window_line (desired_row)
805 struct glyph_row *desired_row;
806 {
807 struct window *w = updated_window;
808 struct frame *f;
809 int width, height;
810
811 xassert (w);
812
813 if (!desired_row->mode_line_p && !w->pseudo_window_p)
814 {
815 BLOCK_INPUT;
816 x_draw_row_fringe_bitmaps (w, desired_row);
817 UNBLOCK_INPUT;
818 }
819
820 /* When a window has disappeared, make sure that no rest of
821 full-width rows stays visible in the internal border. Could
822 check here if updated_window is the leftmost/rightmost window,
823 but I guess it's not worth doing since vertically split windows
824 are almost never used, internal border is rarely set, and the
825 overhead is very small. */
826 if (windows_or_buffers_changed
827 && desired_row->full_width_p
828 && (f = XFRAME (w->frame),
829 width = FRAME_INTERNAL_BORDER_WIDTH (f),
830 width != 0)
831 && (height = desired_row->visible_height,
832 height > 0))
833 {
834 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
835
836 /* Internal border is drawn below the tool bar. */
837 if (WINDOWP (f->tool_bar_window)
838 && w == XWINDOW (f->tool_bar_window))
839 y -= width;
840
841 BLOCK_INPUT;
842 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
843 0, y, width, height, False);
844 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
845 f->output_data.x->pixel_width - width,
846 y, width, height, False);
847 UNBLOCK_INPUT;
848 }
849 }
850
851
852 /* Draw the bitmap WHICH in one of the left or right fringes of
853 window W. ROW is the glyph row for which to display the bitmap; it
854 determines the vertical position at which the bitmap has to be
855 drawn. */
856
857 static void
858 x_draw_fringe_bitmap (w, row, which, left_p)
859 struct window *w;
860 struct glyph_row *row;
861 enum fringe_bitmap_type which;
862 int left_p;
863 {
864 struct frame *f = XFRAME (WINDOW_FRAME (w));
865 Display *display = FRAME_X_DISPLAY (f);
866 Window window = FRAME_X_WINDOW (f);
867 int x, y, wd, h, dy;
868 int b1, b2;
869 unsigned char *bits = NULL;
870 Pixmap pixmap;
871 GC gc = f->output_data.x->normal_gc;
872 struct face *face;
873 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
874
875 /* Must clip because of partially visible lines. */
876 x_clip_to_row (w, row, gc, 1);
877
878 /* Convert row to frame coordinates. */
879 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
880
881 switch (which)
882 {
883 case NO_FRINGE_BITMAP:
884 wd = 0;
885 h = 0;
886 break;
887
888 case LEFT_TRUNCATION_BITMAP:
889 wd = left_width;
890 h = left_height;
891 bits = left_bits;
892 break;
893
894 case OVERLAY_ARROW_BITMAP:
895 wd = ov_width;
896 h = ov_height;
897 bits = ov_bits;
898 break;
899
900 case RIGHT_TRUNCATION_BITMAP:
901 wd = right_width;
902 h = right_height;
903 bits = right_bits;
904 break;
905
906 case CONTINUED_LINE_BITMAP:
907 wd = continued_width;
908 h = continued_height;
909 bits = continued_bits;
910 break;
911
912 case CONTINUATION_LINE_BITMAP:
913 wd = continuation_width;
914 h = continuation_height;
915 bits = continuation_bits;
916 break;
917
918 case ZV_LINE_BITMAP:
919 wd = zv_width;
920 h = zv_height - (y % zv_period);
921 bits = zv_bits + (y % zv_period);
922 break;
923
924 default:
925 abort ();
926 }
927
928 /* Clip bitmap if too high. */
929 if (h > row->height)
930 h = row->height;
931
932 /* Set dy to the offset in the row to start drawing the bitmap. */
933 dy = (row->height - h) / 2;
934
935 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
936 PREPARE_FACE_FOR_DISPLAY (f, face);
937
938 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
939 the fringe. */
940 b1 = b2 = -1;
941 if (left_p)
942 {
943 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
944 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
945 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
946 - wd
947 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
948 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
949 {
950 /* If W has a vertical border to its left, don't draw over it. */
951 int border = ((XFASTINT (w->left) > 0
952 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
953 ? 1 : 0);
954 b1 = (window_box_left (w, -1)
955 - FRAME_X_LEFT_FRINGE_WIDTH (f)
956 + border);
957 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
958 }
959 }
960 else
961 {
962 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
963 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
964 x = (window_box_right (w, -1)
965 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
966 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
967 the fringe. */
968 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
969 {
970 b1 = window_box_right (w, -1);
971 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
972 }
973 }
974
975 if (b1 >= 0)
976 {
977 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
978
979 /* In case the same realized face is used for fringes and
980 for something displayed in the text (e.g. face `region' on
981 mono-displays, the fill style may have been changed to
982 FillSolid in x_draw_glyph_string_background. */
983 if (face->stipple)
984 XSetFillStyle (display, face->gc, FillOpaqueStippled);
985 else
986 XSetForeground (display, face->gc, face->background);
987
988 XFillRectangle (display, window, face->gc,
989 b1,
990 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
991 row->y)),
992 b2,
993 row->visible_height);
994 if (!face->stipple)
995 XSetForeground (display, face->gc, face->foreground);
996 }
997
998 if (which != NO_FRINGE_BITMAP)
999 {
1000 /* Draw the bitmap. I believe these small pixmaps can be cached
1001 by the server. */
1002 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
1003 face->foreground,
1004 face->background, depth);
1005 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
1006 XFreePixmap (display, pixmap);
1007 }
1008
1009 XSetClipMask (display, gc, None);
1010 }
1011
1012
1013 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1014 function with input blocked. */
1015
1016 static void
1017 x_draw_row_fringe_bitmaps (w, row)
1018 struct window *w;
1019 struct glyph_row *row;
1020 {
1021 struct frame *f = XFRAME (w->frame);
1022 enum fringe_bitmap_type bitmap;
1023
1024 xassert (interrupt_input_blocked);
1025
1026 /* If row is completely invisible, because of vscrolling, we
1027 don't have to draw anything. */
1028 if (row->visible_height <= 0)
1029 return;
1030
1031 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1032 {
1033 /* Decide which bitmap to draw in the left fringe. */
1034 if (row->overlay_arrow_p)
1035 bitmap = OVERLAY_ARROW_BITMAP;
1036 else if (row->truncated_on_left_p)
1037 bitmap = LEFT_TRUNCATION_BITMAP;
1038 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1039 bitmap = CONTINUATION_LINE_BITMAP;
1040 else if (row->indicate_empty_line_p)
1041 bitmap = ZV_LINE_BITMAP;
1042 else
1043 bitmap = NO_FRINGE_BITMAP;
1044
1045 x_draw_fringe_bitmap (w, row, bitmap, 1);
1046 }
1047
1048 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1049 {
1050 /* Decide which bitmap to draw in the right fringe. */
1051 if (row->truncated_on_right_p)
1052 bitmap = RIGHT_TRUNCATION_BITMAP;
1053 else if (row->continued_p)
1054 bitmap = CONTINUED_LINE_BITMAP;
1055 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1056 bitmap = ZV_LINE_BITMAP;
1057 else
1058 bitmap = NO_FRINGE_BITMAP;
1059
1060 x_draw_fringe_bitmap (w, row, bitmap, 0);
1061 }
1062 }
1063
1064 \f
1065
1066 /* This is called when starting Emacs and when restarting after
1067 suspend. When starting Emacs, no X window is mapped. And nothing
1068 must be done to Emacs's own window if it is suspended (though that
1069 rarely happens). */
1070
1071 static void
1072 XTset_terminal_modes ()
1073 {
1074 }
1075
1076 /* This is called when exiting or suspending Emacs. Exiting will make
1077 the X-windows go away, and suspending requires no action. */
1078
1079 static void
1080 XTreset_terminal_modes ()
1081 {
1082 }
1083
1084
1085 \f
1086 /***********************************************************************
1087 Output Cursor
1088 ***********************************************************************/
1089
1090 /* Set the global variable output_cursor to CURSOR. All cursor
1091 positions are relative to updated_window. */
1092
1093 static void
1094 set_output_cursor (cursor)
1095 struct cursor_pos *cursor;
1096 {
1097 output_cursor.hpos = cursor->hpos;
1098 output_cursor.vpos = cursor->vpos;
1099 output_cursor.x = cursor->x;
1100 output_cursor.y = cursor->y;
1101 }
1102
1103
1104 /* Set a nominal cursor position.
1105
1106 HPOS and VPOS are column/row positions in a window glyph matrix. X
1107 and Y are window text area relative pixel positions.
1108
1109 If this is done during an update, updated_window will contain the
1110 window that is being updated and the position is the future output
1111 cursor position for that window. If updated_window is null, use
1112 selected_window and display the cursor at the given position. */
1113
1114 static void
1115 XTcursor_to (vpos, hpos, y, x)
1116 int vpos, hpos, y, x;
1117 {
1118 struct window *w;
1119
1120 /* If updated_window is not set, work on selected_window. */
1121 if (updated_window)
1122 w = updated_window;
1123 else
1124 w = XWINDOW (selected_window);
1125
1126 /* Set the output cursor. */
1127 output_cursor.hpos = hpos;
1128 output_cursor.vpos = vpos;
1129 output_cursor.x = x;
1130 output_cursor.y = y;
1131
1132 /* If not called as part of an update, really display the cursor.
1133 This will also set the cursor position of W. */
1134 if (updated_window == NULL)
1135 {
1136 BLOCK_INPUT;
1137 x_display_cursor (w, 1, hpos, vpos, x, y);
1138 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1139 UNBLOCK_INPUT;
1140 }
1141 }
1142
1143
1144 \f
1145 /***********************************************************************
1146 Display Iterator
1147 ***********************************************************************/
1148
1149 /* Function prototypes of this page. */
1150
1151 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1152 struct glyph *,
1153 XChar2b *,
1154 int *));
1155 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1156 int, XChar2b *, int,
1157 int));
1158 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1159 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1160 static void x_append_glyph P_ ((struct it *));
1161 static void x_append_composite_glyph P_ ((struct it *));
1162 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1163 int, int, double));
1164 static void x_produce_glyphs P_ ((struct it *));
1165 static void x_produce_image_glyph P_ ((struct it *it));
1166
1167
1168 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1169 is not contained in the font. */
1170
1171 static INLINE XCharStruct *
1172 x_per_char_metric (font, char2b)
1173 XFontStruct *font;
1174 XChar2b *char2b;
1175 {
1176 /* The result metric information. */
1177 XCharStruct *pcm = NULL;
1178
1179 xassert (font && char2b);
1180
1181 if (font->per_char != NULL)
1182 {
1183 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1184 {
1185 /* min_char_or_byte2 specifies the linear character index
1186 corresponding to the first element of the per_char array,
1187 max_char_or_byte2 is the index of the last character. A
1188 character with non-zero CHAR2B->byte1 is not in the font.
1189 A character with byte2 less than min_char_or_byte2 or
1190 greater max_char_or_byte2 is not in the font. */
1191 if (char2b->byte1 == 0
1192 && char2b->byte2 >= font->min_char_or_byte2
1193 && char2b->byte2 <= font->max_char_or_byte2)
1194 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1195 }
1196 else
1197 {
1198 /* If either min_byte1 or max_byte1 are nonzero, both
1199 min_char_or_byte2 and max_char_or_byte2 are less than
1200 256, and the 2-byte character index values corresponding
1201 to the per_char array element N (counting from 0) are:
1202
1203 byte1 = N/D + min_byte1
1204 byte2 = N\D + min_char_or_byte2
1205
1206 where:
1207
1208 D = max_char_or_byte2 - min_char_or_byte2 + 1
1209 / = integer division
1210 \ = integer modulus */
1211 if (char2b->byte1 >= font->min_byte1
1212 && char2b->byte1 <= font->max_byte1
1213 && char2b->byte2 >= font->min_char_or_byte2
1214 && char2b->byte2 <= font->max_char_or_byte2)
1215 {
1216 pcm = (font->per_char
1217 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1218 * (char2b->byte1 - font->min_byte1))
1219 + (char2b->byte2 - font->min_char_or_byte2));
1220 }
1221 }
1222 }
1223 else
1224 {
1225 /* If the per_char pointer is null, all glyphs between the first
1226 and last character indexes inclusive have the same
1227 information, as given by both min_bounds and max_bounds. */
1228 if (char2b->byte2 >= font->min_char_or_byte2
1229 && char2b->byte2 <= font->max_char_or_byte2)
1230 pcm = &font->max_bounds;
1231 }
1232
1233 return ((pcm == NULL
1234 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1235 ? NULL : pcm);
1236 }
1237
1238
1239 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1240 the two-byte form of C. Encoding is returned in *CHAR2B. */
1241
1242 static INLINE void
1243 x_encode_char (c, char2b, font_info)
1244 int c;
1245 XChar2b *char2b;
1246 struct font_info *font_info;
1247 {
1248 int charset = CHAR_CHARSET (c);
1249 XFontStruct *font = font_info->font;
1250
1251 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1252 This may be either a program in a special encoder language or a
1253 fixed encoding. */
1254 if (font_info->font_encoder)
1255 {
1256 /* It's a program. */
1257 struct ccl_program *ccl = font_info->font_encoder;
1258
1259 if (CHARSET_DIMENSION (charset) == 1)
1260 {
1261 ccl->reg[0] = charset;
1262 ccl->reg[1] = char2b->byte2;
1263 ccl->reg[2] = -1;
1264 }
1265 else
1266 {
1267 ccl->reg[0] = charset;
1268 ccl->reg[1] = char2b->byte1;
1269 ccl->reg[2] = char2b->byte2;
1270 }
1271
1272 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1273
1274 /* We assume that MSBs are appropriately set/reset by CCL
1275 program. */
1276 if (font->max_byte1 == 0) /* 1-byte font */
1277 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1278 else
1279 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1280 }
1281 else if (font_info->encoding[charset])
1282 {
1283 /* Fixed encoding scheme. See fontset.h for the meaning of the
1284 encoding numbers. */
1285 int enc = font_info->encoding[charset];
1286
1287 if ((enc == 1 || enc == 2)
1288 && CHARSET_DIMENSION (charset) == 2)
1289 char2b->byte1 |= 0x80;
1290
1291 if (enc == 1 || enc == 3)
1292 char2b->byte2 |= 0x80;
1293 }
1294 }
1295
1296
1297 /* Get face and two-byte form of character C in face FACE_ID on frame
1298 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1299 means we want to display multibyte text. DISPLAY_P non-zero means
1300 make sure that X resources for the face returned are allocated.
1301 Value is a pointer to a realized face that is ready for display if
1302 DISPLAY_P is non-zero. */
1303
1304 static INLINE struct face *
1305 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
1306 struct frame *f;
1307 int c, face_id;
1308 XChar2b *char2b;
1309 int multibyte_p, display_p;
1310 {
1311 struct face *face = FACE_FROM_ID (f, face_id);
1312
1313 if (!multibyte_p)
1314 {
1315 /* Unibyte case. We don't have to encode, but we have to make
1316 sure to use a face suitable for unibyte. */
1317 char2b->byte1 = 0;
1318 char2b->byte2 = c;
1319 face_id = FACE_FOR_CHAR (f, face, c);
1320 face = FACE_FROM_ID (f, face_id);
1321 }
1322 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1323 {
1324 /* Case of ASCII in a face known to fit ASCII. */
1325 char2b->byte1 = 0;
1326 char2b->byte2 = c;
1327 }
1328 else
1329 {
1330 int c1, c2, charset;
1331
1332 /* Split characters into bytes. If c2 is -1 afterwards, C is
1333 really a one-byte character so that byte1 is zero. */
1334 SPLIT_CHAR (c, charset, c1, c2);
1335 if (c2 > 0)
1336 char2b->byte1 = c1, char2b->byte2 = c2;
1337 else
1338 char2b->byte1 = 0, char2b->byte2 = c1;
1339
1340 /* Maybe encode the character in *CHAR2B. */
1341 if (face->font != NULL)
1342 {
1343 struct font_info *font_info
1344 = FONT_INFO_FROM_ID (f, face->font_info_id);
1345 if (font_info)
1346 x_encode_char (c, char2b, font_info);
1347 }
1348 }
1349
1350 /* Make sure X resources of the face are allocated. */
1351 if (display_p)
1352 {
1353 xassert (face != NULL);
1354 PREPARE_FACE_FOR_DISPLAY (f, face);
1355 }
1356
1357 return face;
1358 }
1359
1360
1361 /* Get face and two-byte form of character glyph GLYPH on frame F.
1362 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1363 a pointer to a realized face that is ready for display. */
1364
1365 static INLINE struct face *
1366 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1367 struct frame *f;
1368 struct glyph *glyph;
1369 XChar2b *char2b;
1370 int *two_byte_p;
1371 {
1372 struct face *face;
1373
1374 xassert (glyph->type == CHAR_GLYPH);
1375 face = FACE_FROM_ID (f, glyph->face_id);
1376
1377 if (two_byte_p)
1378 *two_byte_p = 0;
1379
1380 if (!glyph->multibyte_p)
1381 {
1382 /* Unibyte case. We don't have to encode, but we have to make
1383 sure to use a face suitable for unibyte. */
1384 char2b->byte1 = 0;
1385 char2b->byte2 = glyph->u.ch;
1386 }
1387 else if (glyph->u.ch < 128
1388 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1389 {
1390 /* Case of ASCII in a face known to fit ASCII. */
1391 char2b->byte1 = 0;
1392 char2b->byte2 = glyph->u.ch;
1393 }
1394 else
1395 {
1396 int c1, c2, charset;
1397
1398 /* Split characters into bytes. If c2 is -1 afterwards, C is
1399 really a one-byte character so that byte1 is zero. */
1400 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1401 if (c2 > 0)
1402 char2b->byte1 = c1, char2b->byte2 = c2;
1403 else
1404 char2b->byte1 = 0, char2b->byte2 = c1;
1405
1406 /* Maybe encode the character in *CHAR2B. */
1407 if (charset != CHARSET_ASCII)
1408 {
1409 struct font_info *font_info
1410 = FONT_INFO_FROM_ID (f, face->font_info_id);
1411 if (font_info)
1412 {
1413 x_encode_char (glyph->u.ch, char2b, font_info);
1414 if (two_byte_p)
1415 *two_byte_p
1416 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1417 }
1418 }
1419 }
1420
1421 /* Make sure X resources of the face are allocated. */
1422 xassert (face != NULL);
1423 PREPARE_FACE_FOR_DISPLAY (f, face);
1424 return face;
1425 }
1426
1427
1428 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1429 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1430
1431 static INLINE void
1432 x_append_glyph (it)
1433 struct it *it;
1434 {
1435 struct glyph *glyph;
1436 enum glyph_row_area area = it->area;
1437
1438 xassert (it->glyph_row);
1439 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1440
1441 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1442 if (glyph < it->glyph_row->glyphs[area + 1])
1443 {
1444 glyph->charpos = CHARPOS (it->position);
1445 glyph->object = it->object;
1446 glyph->pixel_width = it->pixel_width;
1447 glyph->voffset = it->voffset;
1448 glyph->type = CHAR_GLYPH;
1449 glyph->multibyte_p = it->multibyte_p;
1450 glyph->left_box_line_p = it->start_of_box_run_p;
1451 glyph->right_box_line_p = it->end_of_box_run_p;
1452 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1453 || it->phys_descent > it->descent);
1454 glyph->padding_p = 0;
1455 glyph->glyph_not_available_p = it->glyph_not_available_p;
1456 glyph->face_id = it->face_id;
1457 glyph->u.ch = it->char_to_display;
1458 ++it->glyph_row->used[area];
1459 }
1460 }
1461
1462 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1463 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1464
1465 static INLINE void
1466 x_append_composite_glyph (it)
1467 struct it *it;
1468 {
1469 struct glyph *glyph;
1470 enum glyph_row_area area = it->area;
1471
1472 xassert (it->glyph_row);
1473
1474 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1475 if (glyph < it->glyph_row->glyphs[area + 1])
1476 {
1477 glyph->charpos = CHARPOS (it->position);
1478 glyph->object = it->object;
1479 glyph->pixel_width = it->pixel_width;
1480 glyph->voffset = it->voffset;
1481 glyph->type = COMPOSITE_GLYPH;
1482 glyph->multibyte_p = it->multibyte_p;
1483 glyph->left_box_line_p = it->start_of_box_run_p;
1484 glyph->right_box_line_p = it->end_of_box_run_p;
1485 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1486 || it->phys_descent > it->descent);
1487 glyph->padding_p = 0;
1488 glyph->glyph_not_available_p = 0;
1489 glyph->face_id = it->face_id;
1490 glyph->u.cmp_id = it->cmp_id;
1491 ++it->glyph_row->used[area];
1492 }
1493 }
1494
1495
1496 /* Change IT->ascent and IT->height according to the setting of
1497 IT->voffset. */
1498
1499 static INLINE void
1500 take_vertical_position_into_account (it)
1501 struct it *it;
1502 {
1503 if (it->voffset)
1504 {
1505 if (it->voffset < 0)
1506 /* Increase the ascent so that we can display the text higher
1507 in the line. */
1508 it->ascent += abs (it->voffset);
1509 else
1510 /* Increase the descent so that we can display the text lower
1511 in the line. */
1512 it->descent += it->voffset;
1513 }
1514 }
1515
1516
1517 /* Produce glyphs/get display metrics for the image IT is loaded with.
1518 See the description of struct display_iterator in dispextern.h for
1519 an overview of struct display_iterator. */
1520
1521 static void
1522 x_produce_image_glyph (it)
1523 struct it *it;
1524 {
1525 struct image *img;
1526 struct face *face;
1527
1528 xassert (it->what == IT_IMAGE);
1529
1530 face = FACE_FROM_ID (it->f, it->face_id);
1531 img = IMAGE_FROM_ID (it->f, it->image_id);
1532 xassert (img);
1533
1534 /* Make sure X resources of the face and image are loaded. */
1535 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1536 prepare_image_for_display (it->f, img);
1537
1538 it->ascent = it->phys_ascent = image_ascent (img, face);
1539 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1540 it->pixel_width = img->width + 2 * img->hmargin;
1541
1542 it->nglyphs = 1;
1543
1544 if (face->box != FACE_NO_BOX)
1545 {
1546 if (face->box_line_width > 0)
1547 {
1548 it->ascent += face->box_line_width;
1549 it->descent += face->box_line_width;
1550 }
1551
1552 if (it->start_of_box_run_p)
1553 it->pixel_width += abs (face->box_line_width);
1554 if (it->end_of_box_run_p)
1555 it->pixel_width += abs (face->box_line_width);
1556 }
1557
1558 take_vertical_position_into_account (it);
1559
1560 if (it->glyph_row)
1561 {
1562 struct glyph *glyph;
1563 enum glyph_row_area area = it->area;
1564
1565 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1566 if (glyph < it->glyph_row->glyphs[area + 1])
1567 {
1568 glyph->charpos = CHARPOS (it->position);
1569 glyph->object = it->object;
1570 glyph->pixel_width = it->pixel_width;
1571 glyph->voffset = it->voffset;
1572 glyph->type = IMAGE_GLYPH;
1573 glyph->multibyte_p = it->multibyte_p;
1574 glyph->left_box_line_p = it->start_of_box_run_p;
1575 glyph->right_box_line_p = it->end_of_box_run_p;
1576 glyph->overlaps_vertically_p = 0;
1577 glyph->padding_p = 0;
1578 glyph->glyph_not_available_p = 0;
1579 glyph->face_id = it->face_id;
1580 glyph->u.img_id = img->id;
1581 ++it->glyph_row->used[area];
1582 }
1583 }
1584 }
1585
1586
1587 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1588 of the glyph, WIDTH and HEIGHT are the width and height of the
1589 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1590 ascent of the glyph (0 <= ASCENT <= 1). */
1591
1592 static void
1593 x_append_stretch_glyph (it, object, width, height, ascent)
1594 struct it *it;
1595 Lisp_Object object;
1596 int width, height;
1597 double ascent;
1598 {
1599 struct glyph *glyph;
1600 enum glyph_row_area area = it->area;
1601
1602 xassert (ascent >= 0 && ascent <= 1);
1603
1604 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1605 if (glyph < it->glyph_row->glyphs[area + 1])
1606 {
1607 glyph->charpos = CHARPOS (it->position);
1608 glyph->object = object;
1609 glyph->pixel_width = width;
1610 glyph->voffset = it->voffset;
1611 glyph->type = STRETCH_GLYPH;
1612 glyph->multibyte_p = it->multibyte_p;
1613 glyph->left_box_line_p = it->start_of_box_run_p;
1614 glyph->right_box_line_p = it->end_of_box_run_p;
1615 glyph->overlaps_vertically_p = 0;
1616 glyph->padding_p = 0;
1617 glyph->glyph_not_available_p = 0;
1618 glyph->face_id = it->face_id;
1619 glyph->u.stretch.ascent = height * ascent;
1620 glyph->u.stretch.height = height;
1621 ++it->glyph_row->used[area];
1622 }
1623 }
1624
1625
1626 /* Produce a stretch glyph for iterator IT. IT->object is the value
1627 of the glyph property displayed. The value must be a list
1628 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1629 being recognized:
1630
1631 1. `:width WIDTH' specifies that the space should be WIDTH *
1632 canonical char width wide. WIDTH may be an integer or floating
1633 point number.
1634
1635 2. `:relative-width FACTOR' specifies that the width of the stretch
1636 should be computed from the width of the first character having the
1637 `glyph' property, and should be FACTOR times that width.
1638
1639 3. `:align-to HPOS' specifies that the space should be wide enough
1640 to reach HPOS, a value in canonical character units.
1641
1642 Exactly one of the above pairs must be present.
1643
1644 4. `:height HEIGHT' specifies that the height of the stretch produced
1645 should be HEIGHT, measured in canonical character units.
1646
1647 5. `:relative-height FACTOR' specifies that the height of the
1648 stretch should be FACTOR times the height of the characters having
1649 the glyph property.
1650
1651 Either none or exactly one of 4 or 5 must be present.
1652
1653 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1654 of the stretch should be used for the ascent of the stretch.
1655 ASCENT must be in the range 0 <= ASCENT <= 100. */
1656
1657 #define NUMVAL(X) \
1658 ((INTEGERP (X) || FLOATP (X)) \
1659 ? XFLOATINT (X) \
1660 : - 1)
1661
1662
1663 static void
1664 x_produce_stretch_glyph (it)
1665 struct it *it;
1666 {
1667 /* (space :width WIDTH :height HEIGHT. */
1668 #if GLYPH_DEBUG
1669 extern Lisp_Object Qspace;
1670 #endif
1671 extern Lisp_Object QCwidth, QCheight, QCascent;
1672 extern Lisp_Object QCrelative_width, QCrelative_height;
1673 extern Lisp_Object QCalign_to;
1674 Lisp_Object prop, plist;
1675 double width = 0, height = 0, ascent = 0;
1676 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1677 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1678
1679 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1680
1681 /* List should start with `space'. */
1682 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1683 plist = XCDR (it->object);
1684
1685 /* Compute the width of the stretch. */
1686 if (prop = Fplist_get (plist, QCwidth),
1687 NUMVAL (prop) > 0)
1688 /* Absolute width `:width WIDTH' specified and valid. */
1689 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1690 else if (prop = Fplist_get (plist, QCrelative_width),
1691 NUMVAL (prop) > 0)
1692 {
1693 /* Relative width `:relative-width FACTOR' specified and valid.
1694 Compute the width of the characters having the `glyph'
1695 property. */
1696 struct it it2;
1697 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1698
1699 it2 = *it;
1700 if (it->multibyte_p)
1701 {
1702 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1703 - IT_BYTEPOS (*it));
1704 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1705 }
1706 else
1707 it2.c = *p, it2.len = 1;
1708
1709 it2.glyph_row = NULL;
1710 it2.what = IT_CHARACTER;
1711 x_produce_glyphs (&it2);
1712 width = NUMVAL (prop) * it2.pixel_width;
1713 }
1714 else if (prop = Fplist_get (plist, QCalign_to),
1715 NUMVAL (prop) > 0)
1716 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1717 else
1718 /* Nothing specified -> width defaults to canonical char width. */
1719 width = CANON_X_UNIT (it->f);
1720
1721 /* Compute height. */
1722 if (prop = Fplist_get (plist, QCheight),
1723 NUMVAL (prop) > 0)
1724 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1725 else if (prop = Fplist_get (plist, QCrelative_height),
1726 NUMVAL (prop) > 0)
1727 height = FONT_HEIGHT (font) * NUMVAL (prop);
1728 else
1729 height = FONT_HEIGHT (font);
1730
1731 /* Compute percentage of height used for ascent. If
1732 `:ascent ASCENT' is present and valid, use that. Otherwise,
1733 derive the ascent from the font in use. */
1734 if (prop = Fplist_get (plist, QCascent),
1735 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1736 ascent = NUMVAL (prop) / 100.0;
1737 else
1738 ascent = (double) font->ascent / FONT_HEIGHT (font);
1739
1740 if (width <= 0)
1741 width = 1;
1742 if (height <= 0)
1743 height = 1;
1744
1745 if (it->glyph_row)
1746 {
1747 Lisp_Object object = it->stack[it->sp - 1].string;
1748 if (!STRINGP (object))
1749 object = it->w->buffer;
1750 x_append_stretch_glyph (it, object, width, height, ascent);
1751 }
1752
1753 it->pixel_width = width;
1754 it->ascent = it->phys_ascent = height * ascent;
1755 it->descent = it->phys_descent = height - it->ascent;
1756 it->nglyphs = 1;
1757
1758 if (face->box != FACE_NO_BOX)
1759 {
1760 if (face->box_line_width > 0)
1761 {
1762 it->ascent += face->box_line_width;
1763 it->descent += face->box_line_width;
1764 }
1765
1766 if (it->start_of_box_run_p)
1767 it->pixel_width += abs (face->box_line_width);
1768 if (it->end_of_box_run_p)
1769 it->pixel_width += abs (face->box_line_width);
1770 }
1771
1772 take_vertical_position_into_account (it);
1773 }
1774
1775 /* Return proper value to be used as baseline offset of font that has
1776 ASCENT and DESCENT to draw characters by the font at the vertical
1777 center of the line of frame F.
1778
1779 Here, out task is to find the value of BOFF in the following figure;
1780
1781 -------------------------+-----------+-
1782 -+-+---------+-+ | |
1783 | | | | | |
1784 | | | | F_ASCENT F_HEIGHT
1785 | | | ASCENT | |
1786 HEIGHT | | | | |
1787 | | |-|-+------+-----------|------- baseline
1788 | | | | BOFF | |
1789 | |---------|-+-+ | |
1790 | | | DESCENT | |
1791 -+-+---------+-+ F_DESCENT |
1792 -------------------------+-----------+-
1793
1794 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1795 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1796 DESCENT = FONT->descent
1797 HEIGHT = FONT_HEIGHT (FONT)
1798 F_DESCENT = (F->output_data.x->font->descent
1799 - F->output_data.x->baseline_offset)
1800 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1801 */
1802
1803 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1804 ((FONT)->descent \
1805 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1806 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1807 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1808
1809 /* Produce glyphs/get display metrics for the display element IT is
1810 loaded with. See the description of struct display_iterator in
1811 dispextern.h for an overview of struct display_iterator. */
1812
1813 static void
1814 x_produce_glyphs (it)
1815 struct it *it;
1816 {
1817 it->glyph_not_available_p = 0;
1818
1819 if (it->what == IT_CHARACTER)
1820 {
1821 XChar2b char2b;
1822 XFontStruct *font;
1823 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1824 XCharStruct *pcm;
1825 int font_not_found_p;
1826 struct font_info *font_info;
1827 int boff; /* baseline offset */
1828 /* We may change it->multibyte_p upon unibyte<->multibyte
1829 conversion. So, save the current value now and restore it
1830 later.
1831
1832 Note: It seems that we don't have to record multibyte_p in
1833 struct glyph because the character code itself tells if or
1834 not the character is multibyte. Thus, in the future, we must
1835 consider eliminating the field `multibyte_p' in the struct
1836 glyph. */
1837 int saved_multibyte_p = it->multibyte_p;
1838
1839 /* Maybe translate single-byte characters to multibyte, or the
1840 other way. */
1841 it->char_to_display = it->c;
1842 if (!ASCII_BYTE_P (it->c))
1843 {
1844 if (unibyte_display_via_language_environment
1845 && SINGLE_BYTE_CHAR_P (it->c)
1846 && (it->c >= 0240
1847 || !NILP (Vnonascii_translation_table)))
1848 {
1849 it->char_to_display = unibyte_char_to_multibyte (it->c);
1850 it->multibyte_p = 1;
1851 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1852 face = FACE_FROM_ID (it->f, it->face_id);
1853 }
1854 else if (!SINGLE_BYTE_CHAR_P (it->c)
1855 && !it->multibyte_p)
1856 {
1857 it->multibyte_p = 1;
1858 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1859 face = FACE_FROM_ID (it->f, it->face_id);
1860 }
1861 }
1862
1863 /* Get font to use. Encode IT->char_to_display. */
1864 x_get_char_face_and_encoding (it->f, it->char_to_display,
1865 it->face_id, &char2b,
1866 it->multibyte_p, 0);
1867 font = face->font;
1868
1869 /* When no suitable font found, use the default font. */
1870 font_not_found_p = font == NULL;
1871 if (font_not_found_p)
1872 {
1873 font = FRAME_FONT (it->f);
1874 boff = it->f->output_data.x->baseline_offset;
1875 font_info = NULL;
1876 }
1877 else
1878 {
1879 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1880 boff = font_info->baseline_offset;
1881 if (font_info->vertical_centering)
1882 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1883 }
1884
1885 if (it->char_to_display >= ' '
1886 && (!it->multibyte_p || it->char_to_display < 128))
1887 {
1888 /* Either unibyte or ASCII. */
1889 int stretched_p;
1890
1891 it->nglyphs = 1;
1892
1893 pcm = x_per_char_metric (font, &char2b);
1894 it->ascent = font->ascent + boff;
1895 it->descent = font->descent - boff;
1896
1897 if (pcm)
1898 {
1899 it->phys_ascent = pcm->ascent + boff;
1900 it->phys_descent = pcm->descent - boff;
1901 it->pixel_width = pcm->width;
1902 }
1903 else
1904 {
1905 it->glyph_not_available_p = 1;
1906 it->phys_ascent = font->ascent + boff;
1907 it->phys_descent = font->descent - boff;
1908 it->pixel_width = FONT_WIDTH (font);
1909 }
1910
1911 /* If this is a space inside a region of text with
1912 `space-width' property, change its width. */
1913 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1914 if (stretched_p)
1915 it->pixel_width *= XFLOATINT (it->space_width);
1916
1917 /* If face has a box, add the box thickness to the character
1918 height. If character has a box line to the left and/or
1919 right, add the box line width to the character's width. */
1920 if (face->box != FACE_NO_BOX)
1921 {
1922 int thick = face->box_line_width;
1923
1924 if (thick > 0)
1925 {
1926 it->ascent += thick;
1927 it->descent += thick;
1928 }
1929 else
1930 thick = -thick;
1931
1932 if (it->start_of_box_run_p)
1933 it->pixel_width += thick;
1934 if (it->end_of_box_run_p)
1935 it->pixel_width += thick;
1936 }
1937
1938 /* If face has an overline, add the height of the overline
1939 (1 pixel) and a 1 pixel margin to the character height. */
1940 if (face->overline_p)
1941 it->ascent += 2;
1942
1943 take_vertical_position_into_account (it);
1944
1945 /* If we have to actually produce glyphs, do it. */
1946 if (it->glyph_row)
1947 {
1948 if (stretched_p)
1949 {
1950 /* Translate a space with a `space-width' property
1951 into a stretch glyph. */
1952 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1953 x_append_stretch_glyph (it, it->object, it->pixel_width,
1954 it->ascent + it->descent, ascent);
1955 }
1956 else
1957 x_append_glyph (it);
1958
1959 /* If characters with lbearing or rbearing are displayed
1960 in this line, record that fact in a flag of the
1961 glyph row. This is used to optimize X output code. */
1962 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1963 it->glyph_row->contains_overlapping_glyphs_p = 1;
1964 }
1965 }
1966 else if (it->char_to_display == '\n')
1967 {
1968 /* A newline has no width but we need the height of the line. */
1969 it->pixel_width = 0;
1970 it->nglyphs = 0;
1971 it->ascent = it->phys_ascent = font->ascent + boff;
1972 it->descent = it->phys_descent = font->descent - boff;
1973
1974 if (face->box != FACE_NO_BOX
1975 && face->box_line_width > 0)
1976 {
1977 it->ascent += face->box_line_width;
1978 it->descent += face->box_line_width;
1979 }
1980 }
1981 else if (it->char_to_display == '\t')
1982 {
1983 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1984 int x = it->current_x + it->continuation_lines_width;
1985 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1986
1987 /* If the distance from the current position to the next tab
1988 stop is less than a canonical character width, use the
1989 tab stop after that. */
1990 if (next_tab_x - x < CANON_X_UNIT (it->f))
1991 next_tab_x += tab_width;
1992
1993 it->pixel_width = next_tab_x - x;
1994 it->nglyphs = 1;
1995 it->ascent = it->phys_ascent = font->ascent + boff;
1996 it->descent = it->phys_descent = font->descent - boff;
1997
1998 if (it->glyph_row)
1999 {
2000 double ascent = (double) it->ascent / (it->ascent + it->descent);
2001 x_append_stretch_glyph (it, it->object, it->pixel_width,
2002 it->ascent + it->descent, ascent);
2003 }
2004 }
2005 else
2006 {
2007 /* A multi-byte character. Assume that the display width of the
2008 character is the width of the character multiplied by the
2009 width of the font. */
2010
2011 /* If we found a font, this font should give us the right
2012 metrics. If we didn't find a font, use the frame's
2013 default font and calculate the width of the character
2014 from the charset width; this is what old redisplay code
2015 did. */
2016 pcm = x_per_char_metric (font, &char2b);
2017 if (font_not_found_p || !pcm)
2018 {
2019 int charset = CHAR_CHARSET (it->char_to_display);
2020
2021 it->glyph_not_available_p = 1;
2022 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2023 * CHARSET_WIDTH (charset));
2024 it->phys_ascent = font->ascent + boff;
2025 it->phys_descent = font->descent - boff;
2026 }
2027 else
2028 {
2029 it->pixel_width = pcm->width;
2030 it->phys_ascent = pcm->ascent + boff;
2031 it->phys_descent = pcm->descent - boff;
2032 if (it->glyph_row
2033 && (pcm->lbearing < 0
2034 || pcm->rbearing > pcm->width))
2035 it->glyph_row->contains_overlapping_glyphs_p = 1;
2036 }
2037 it->nglyphs = 1;
2038 it->ascent = font->ascent + boff;
2039 it->descent = font->descent - boff;
2040 if (face->box != FACE_NO_BOX)
2041 {
2042 int thick = face->box_line_width;
2043
2044 if (thick > 0)
2045 {
2046 it->ascent += thick;
2047 it->descent += thick;
2048 }
2049 else
2050 thick = - thick;
2051
2052 if (it->start_of_box_run_p)
2053 it->pixel_width += thick;
2054 if (it->end_of_box_run_p)
2055 it->pixel_width += thick;
2056 }
2057
2058 /* If face has an overline, add the height of the overline
2059 (1 pixel) and a 1 pixel margin to the character height. */
2060 if (face->overline_p)
2061 it->ascent += 2;
2062
2063 take_vertical_position_into_account (it);
2064
2065 if (it->glyph_row)
2066 x_append_glyph (it);
2067 }
2068 it->multibyte_p = saved_multibyte_p;
2069 }
2070 else if (it->what == IT_COMPOSITION)
2071 {
2072 /* Note: A composition is represented as one glyph in the
2073 glyph matrix. There are no padding glyphs. */
2074 XChar2b char2b;
2075 XFontStruct *font;
2076 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2077 XCharStruct *pcm;
2078 int font_not_found_p;
2079 struct font_info *font_info;
2080 int boff; /* baseline offset */
2081 struct composition *cmp = composition_table[it->cmp_id];
2082
2083 /* Maybe translate single-byte characters to multibyte. */
2084 it->char_to_display = it->c;
2085 if (unibyte_display_via_language_environment
2086 && SINGLE_BYTE_CHAR_P (it->c)
2087 && (it->c >= 0240
2088 || (it->c >= 0200
2089 && !NILP (Vnonascii_translation_table))))
2090 {
2091 it->char_to_display = unibyte_char_to_multibyte (it->c);
2092 }
2093
2094 /* Get face and font to use. Encode IT->char_to_display. */
2095 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2096 face = FACE_FROM_ID (it->f, it->face_id);
2097 x_get_char_face_and_encoding (it->f, it->char_to_display,
2098 it->face_id, &char2b, it->multibyte_p, 0);
2099 font = face->font;
2100
2101 /* When no suitable font found, use the default font. */
2102 font_not_found_p = font == NULL;
2103 if (font_not_found_p)
2104 {
2105 font = FRAME_FONT (it->f);
2106 boff = it->f->output_data.x->baseline_offset;
2107 font_info = NULL;
2108 }
2109 else
2110 {
2111 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2112 boff = font_info->baseline_offset;
2113 if (font_info->vertical_centering)
2114 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2115 }
2116
2117 /* There are no padding glyphs, so there is only one glyph to
2118 produce for the composition. Important is that pixel_width,
2119 ascent and descent are the values of what is drawn by
2120 draw_glyphs (i.e. the values of the overall glyphs composed). */
2121 it->nglyphs = 1;
2122
2123 /* If we have not yet calculated pixel size data of glyphs of
2124 the composition for the current face font, calculate them
2125 now. Theoretically, we have to check all fonts for the
2126 glyphs, but that requires much time and memory space. So,
2127 here we check only the font of the first glyph. This leads
2128 to incorrect display very rarely, and C-l (recenter) can
2129 correct the display anyway. */
2130 if (cmp->font != (void *) font)
2131 {
2132 /* Ascent and descent of the font of the first character of
2133 this composition (adjusted by baseline offset). Ascent
2134 and descent of overall glyphs should not be less than
2135 them respectively. */
2136 int font_ascent = font->ascent + boff;
2137 int font_descent = font->descent - boff;
2138 /* Bounding box of the overall glyphs. */
2139 int leftmost, rightmost, lowest, highest;
2140 int i, width, ascent, descent;
2141
2142 cmp->font = (void *) font;
2143
2144 /* Initialize the bounding box. */
2145 if (font_info
2146 && (pcm = x_per_char_metric (font, &char2b)))
2147 {
2148 width = pcm->width;
2149 ascent = pcm->ascent;
2150 descent = pcm->descent;
2151 }
2152 else
2153 {
2154 width = FONT_WIDTH (font);
2155 ascent = font->ascent;
2156 descent = font->descent;
2157 }
2158
2159 rightmost = width;
2160 lowest = - descent + boff;
2161 highest = ascent + boff;
2162 leftmost = 0;
2163
2164 if (font_info
2165 && font_info->default_ascent
2166 && CHAR_TABLE_P (Vuse_default_ascent)
2167 && !NILP (Faref (Vuse_default_ascent,
2168 make_number (it->char_to_display))))
2169 highest = font_info->default_ascent + boff;
2170
2171 /* Draw the first glyph at the normal position. It may be
2172 shifted to right later if some other glyphs are drawn at
2173 the left. */
2174 cmp->offsets[0] = 0;
2175 cmp->offsets[1] = boff;
2176
2177 /* Set cmp->offsets for the remaining glyphs. */
2178 for (i = 1; i < cmp->glyph_len; i++)
2179 {
2180 int left, right, btm, top;
2181 int ch = COMPOSITION_GLYPH (cmp, i);
2182 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2183
2184 face = FACE_FROM_ID (it->f, face_id);
2185 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2186 it->multibyte_p, 0);
2187 font = face->font;
2188 if (font == NULL)
2189 {
2190 font = FRAME_FONT (it->f);
2191 boff = it->f->output_data.x->baseline_offset;
2192 font_info = NULL;
2193 }
2194 else
2195 {
2196 font_info
2197 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2198 boff = font_info->baseline_offset;
2199 if (font_info->vertical_centering)
2200 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2201 }
2202
2203 if (font_info
2204 && (pcm = x_per_char_metric (font, &char2b)))
2205 {
2206 width = pcm->width;
2207 ascent = pcm->ascent;
2208 descent = pcm->descent;
2209 }
2210 else
2211 {
2212 width = FONT_WIDTH (font);
2213 ascent = 1;
2214 descent = 0;
2215 }
2216
2217 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2218 {
2219 /* Relative composition with or without
2220 alternate chars. */
2221 left = (leftmost + rightmost - width) / 2;
2222 btm = - descent + boff;
2223 if (font_info && font_info->relative_compose
2224 && (! CHAR_TABLE_P (Vignore_relative_composition)
2225 || NILP (Faref (Vignore_relative_composition,
2226 make_number (ch)))))
2227 {
2228
2229 if (- descent >= font_info->relative_compose)
2230 /* One extra pixel between two glyphs. */
2231 btm = highest + 1;
2232 else if (ascent <= 0)
2233 /* One extra pixel between two glyphs. */
2234 btm = lowest - 1 - ascent - descent;
2235 }
2236 }
2237 else
2238 {
2239 /* A composition rule is specified by an integer
2240 value that encodes global and new reference
2241 points (GREF and NREF). GREF and NREF are
2242 specified by numbers as below:
2243
2244 0---1---2 -- ascent
2245 | |
2246 | |
2247 | |
2248 9--10--11 -- center
2249 | |
2250 ---3---4---5--- baseline
2251 | |
2252 6---7---8 -- descent
2253 */
2254 int rule = COMPOSITION_RULE (cmp, i);
2255 int gref, nref, grefx, grefy, nrefx, nrefy;
2256
2257 COMPOSITION_DECODE_RULE (rule, gref, nref);
2258 grefx = gref % 3, nrefx = nref % 3;
2259 grefy = gref / 3, nrefy = nref / 3;
2260
2261 left = (leftmost
2262 + grefx * (rightmost - leftmost) / 2
2263 - nrefx * width / 2);
2264 btm = ((grefy == 0 ? highest
2265 : grefy == 1 ? 0
2266 : grefy == 2 ? lowest
2267 : (highest + lowest) / 2)
2268 - (nrefy == 0 ? ascent + descent
2269 : nrefy == 1 ? descent - boff
2270 : nrefy == 2 ? 0
2271 : (ascent + descent) / 2));
2272 }
2273
2274 cmp->offsets[i * 2] = left;
2275 cmp->offsets[i * 2 + 1] = btm + descent;
2276
2277 /* Update the bounding box of the overall glyphs. */
2278 right = left + width;
2279 top = btm + descent + ascent;
2280 if (left < leftmost)
2281 leftmost = left;
2282 if (right > rightmost)
2283 rightmost = right;
2284 if (top > highest)
2285 highest = top;
2286 if (btm < lowest)
2287 lowest = btm;
2288 }
2289
2290 /* If there are glyphs whose x-offsets are negative,
2291 shift all glyphs to the right and make all x-offsets
2292 non-negative. */
2293 if (leftmost < 0)
2294 {
2295 for (i = 0; i < cmp->glyph_len; i++)
2296 cmp->offsets[i * 2] -= leftmost;
2297 rightmost -= leftmost;
2298 }
2299
2300 cmp->pixel_width = rightmost;
2301 cmp->ascent = highest;
2302 cmp->descent = - lowest;
2303 if (cmp->ascent < font_ascent)
2304 cmp->ascent = font_ascent;
2305 if (cmp->descent < font_descent)
2306 cmp->descent = font_descent;
2307 }
2308
2309 it->pixel_width = cmp->pixel_width;
2310 it->ascent = it->phys_ascent = cmp->ascent;
2311 it->descent = it->phys_descent = cmp->descent;
2312
2313 if (face->box != FACE_NO_BOX)
2314 {
2315 int thick = face->box_line_width;
2316
2317 if (thick > 0)
2318 {
2319 it->ascent += thick;
2320 it->descent += thick;
2321 }
2322 else
2323 thick = - thick;
2324
2325 if (it->start_of_box_run_p)
2326 it->pixel_width += thick;
2327 if (it->end_of_box_run_p)
2328 it->pixel_width += thick;
2329 }
2330
2331 /* If face has an overline, add the height of the overline
2332 (1 pixel) and a 1 pixel margin to the character height. */
2333 if (face->overline_p)
2334 it->ascent += 2;
2335
2336 take_vertical_position_into_account (it);
2337
2338 if (it->glyph_row)
2339 x_append_composite_glyph (it);
2340 }
2341 else if (it->what == IT_IMAGE)
2342 x_produce_image_glyph (it);
2343 else if (it->what == IT_STRETCH)
2344 x_produce_stretch_glyph (it);
2345
2346 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2347 because this isn't true for images with `:ascent 100'. */
2348 xassert (it->ascent >= 0 && it->descent >= 0);
2349 if (it->area == TEXT_AREA)
2350 it->current_x += it->pixel_width;
2351
2352 it->descent += it->extra_line_spacing;
2353
2354 it->max_ascent = max (it->max_ascent, it->ascent);
2355 it->max_descent = max (it->max_descent, it->descent);
2356 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2357 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2358 }
2359
2360
2361 /* Estimate the pixel height of the mode or top line on frame F.
2362 FACE_ID specifies what line's height to estimate. */
2363
2364 int
2365 x_estimate_mode_line_height (f, face_id)
2366 struct frame *f;
2367 enum face_id face_id;
2368 {
2369 int height = FONT_HEIGHT (FRAME_FONT (f));
2370
2371 /* This function is called so early when Emacs starts that the face
2372 cache and mode line face are not yet initialized. */
2373 if (FRAME_FACE_CACHE (f))
2374 {
2375 struct face *face = FACE_FROM_ID (f, face_id);
2376 if (face)
2377 {
2378 if (face->font)
2379 height = FONT_HEIGHT (face->font);
2380 if (face->box_line_width > 0)
2381 height += 2 * face->box_line_width;
2382 }
2383 }
2384
2385 return height;
2386 }
2387
2388 \f
2389 /***********************************************************************
2390 Glyph display
2391 ***********************************************************************/
2392
2393 /* A sequence of glyphs to be drawn in the same face.
2394
2395 This data structure is not really completely X specific, so it
2396 could possibly, at least partially, be useful for other systems. It
2397 is currently not part of the external redisplay interface because
2398 it's not clear what other systems will need. */
2399
2400 struct glyph_string
2401 {
2402 /* X-origin of the string. */
2403 int x;
2404
2405 /* Y-origin and y-position of the base line of this string. */
2406 int y, ybase;
2407
2408 /* The width of the string, not including a face extension. */
2409 int width;
2410
2411 /* The width of the string, including a face extension. */
2412 int background_width;
2413
2414 /* The height of this string. This is the height of the line this
2415 string is drawn in, and can be different from the height of the
2416 font the string is drawn in. */
2417 int height;
2418
2419 /* Number of pixels this string overwrites in front of its x-origin.
2420 This number is zero if the string has an lbearing >= 0; it is
2421 -lbearing, if the string has an lbearing < 0. */
2422 int left_overhang;
2423
2424 /* Number of pixels this string overwrites past its right-most
2425 nominal x-position, i.e. x + width. Zero if the string's
2426 rbearing is <= its nominal width, rbearing - width otherwise. */
2427 int right_overhang;
2428
2429 /* The frame on which the glyph string is drawn. */
2430 struct frame *f;
2431
2432 /* The window on which the glyph string is drawn. */
2433 struct window *w;
2434
2435 /* X display and window for convenience. */
2436 Display *display;
2437 Window window;
2438
2439 /* The glyph row for which this string was built. It determines the
2440 y-origin and height of the string. */
2441 struct glyph_row *row;
2442
2443 /* The area within row. */
2444 enum glyph_row_area area;
2445
2446 /* Characters to be drawn, and number of characters. */
2447 XChar2b *char2b;
2448 int nchars;
2449
2450 /* A face-override for drawing cursors, mouse face and similar. */
2451 enum draw_glyphs_face hl;
2452
2453 /* Face in which this string is to be drawn. */
2454 struct face *face;
2455
2456 /* Font in which this string is to be drawn. */
2457 XFontStruct *font;
2458
2459 /* Font info for this string. */
2460 struct font_info *font_info;
2461
2462 /* Non-null means this string describes (part of) a composition.
2463 All characters from char2b are drawn composed. */
2464 struct composition *cmp;
2465
2466 /* Index of this glyph string's first character in the glyph
2467 definition of CMP. If this is zero, this glyph string describes
2468 the first character of a composition. */
2469 int gidx;
2470
2471 /* 1 means this glyph strings face has to be drawn to the right end
2472 of the window's drawing area. */
2473 unsigned extends_to_end_of_line_p : 1;
2474
2475 /* 1 means the background of this string has been drawn. */
2476 unsigned background_filled_p : 1;
2477
2478 /* 1 means glyph string must be drawn with 16-bit functions. */
2479 unsigned two_byte_p : 1;
2480
2481 /* 1 means that the original font determined for drawing this glyph
2482 string could not be loaded. The member `font' has been set to
2483 the frame's default font in this case. */
2484 unsigned font_not_found_p : 1;
2485
2486 /* 1 means that the face in which this glyph string is drawn has a
2487 stipple pattern. */
2488 unsigned stippled_p : 1;
2489
2490 /* 1 means only the foreground of this glyph string must be drawn,
2491 and we should use the physical height of the line this glyph
2492 string appears in as clip rect. */
2493 unsigned for_overlaps_p : 1;
2494
2495 /* The GC to use for drawing this glyph string. */
2496 GC gc;
2497
2498 /* A pointer to the first glyph in the string. This glyph
2499 corresponds to char2b[0]. Needed to draw rectangles if
2500 font_not_found_p is 1. */
2501 struct glyph *first_glyph;
2502
2503 /* Image, if any. */
2504 struct image *img;
2505
2506 struct glyph_string *next, *prev;
2507 };
2508
2509
2510 #if GLYPH_DEBUG
2511
2512 static void
2513 x_dump_glyph_string (s)
2514 struct glyph_string *s;
2515 {
2516 fprintf (stderr, "glyph string\n");
2517 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2518 s->x, s->y, s->width, s->height);
2519 fprintf (stderr, " ybase = %d\n", s->ybase);
2520 fprintf (stderr, " hl = %d\n", s->hl);
2521 fprintf (stderr, " left overhang = %d, right = %d\n",
2522 s->left_overhang, s->right_overhang);
2523 fprintf (stderr, " nchars = %d\n", s->nchars);
2524 fprintf (stderr, " extends to end of line = %d\n",
2525 s->extends_to_end_of_line_p);
2526 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2527 fprintf (stderr, " bg width = %d\n", s->background_width);
2528 }
2529
2530 #endif /* GLYPH_DEBUG */
2531
2532
2533
2534 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2535 struct glyph_string **,
2536 struct glyph_string *,
2537 struct glyph_string *));
2538 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2539 struct glyph_string **,
2540 struct glyph_string *,
2541 struct glyph_string *));
2542 static void x_append_glyph_string P_ ((struct glyph_string **,
2543 struct glyph_string **,
2544 struct glyph_string *));
2545 static int x_left_overwritten P_ ((struct glyph_string *));
2546 static int x_left_overwriting P_ ((struct glyph_string *));
2547 static int x_right_overwritten P_ ((struct glyph_string *));
2548 static int x_right_overwriting P_ ((struct glyph_string *));
2549 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2550 int));
2551 static void x_init_glyph_string P_ ((struct glyph_string *,
2552 XChar2b *, struct window *,
2553 struct glyph_row *,
2554 enum glyph_row_area, int,
2555 enum draw_glyphs_face));
2556 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2557 enum glyph_row_area, int, int,
2558 enum draw_glyphs_face, int));
2559 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2560 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2561 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2562 int));
2563 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2564 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2565 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2566 static void x_draw_glyph_string P_ ((struct glyph_string *));
2567 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2568 static void x_set_cursor_gc P_ ((struct glyph_string *));
2569 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2570 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2571 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2572 int *, int *));
2573 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2574 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2575 unsigned long *, double, int));
2576 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2577 double, int, unsigned long));
2578 static void x_setup_relief_colors P_ ((struct glyph_string *));
2579 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2580 static void x_draw_image_relief P_ ((struct glyph_string *));
2581 static void x_draw_image_foreground P_ ((struct glyph_string *));
2582 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2583 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2584 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2585 int, int, int));
2586 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2587 int, int, int, int, XRectangle *));
2588 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2589 int, int, int, XRectangle *));
2590 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2591 enum glyph_row_area));
2592 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2593 struct glyph_row *,
2594 enum glyph_row_area, int, int));
2595
2596 #if GLYPH_DEBUG
2597 static void x_check_font P_ ((struct frame *, XFontStruct *));
2598 #endif
2599
2600
2601 /* Append the list of glyph strings with head H and tail T to the list
2602 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2603
2604 static INLINE void
2605 x_append_glyph_string_lists (head, tail, h, t)
2606 struct glyph_string **head, **tail;
2607 struct glyph_string *h, *t;
2608 {
2609 if (h)
2610 {
2611 if (*head)
2612 (*tail)->next = h;
2613 else
2614 *head = h;
2615 h->prev = *tail;
2616 *tail = t;
2617 }
2618 }
2619
2620
2621 /* Prepend the list of glyph strings with head H and tail T to the
2622 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2623 result. */
2624
2625 static INLINE void
2626 x_prepend_glyph_string_lists (head, tail, h, t)
2627 struct glyph_string **head, **tail;
2628 struct glyph_string *h, *t;
2629 {
2630 if (h)
2631 {
2632 if (*head)
2633 (*head)->prev = t;
2634 else
2635 *tail = t;
2636 t->next = *head;
2637 *head = h;
2638 }
2639 }
2640
2641
2642 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2643 Set *HEAD and *TAIL to the resulting list. */
2644
2645 static INLINE void
2646 x_append_glyph_string (head, tail, s)
2647 struct glyph_string **head, **tail;
2648 struct glyph_string *s;
2649 {
2650 s->next = s->prev = NULL;
2651 x_append_glyph_string_lists (head, tail, s, s);
2652 }
2653
2654
2655 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2656 face. */
2657
2658 static void
2659 x_set_cursor_gc (s)
2660 struct glyph_string *s;
2661 {
2662 if (s->font == FRAME_FONT (s->f)
2663 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2664 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2665 && !s->cmp)
2666 s->gc = s->f->output_data.x->cursor_gc;
2667 else
2668 {
2669 /* Cursor on non-default face: must merge. */
2670 XGCValues xgcv;
2671 unsigned long mask;
2672
2673 xgcv.background = s->f->output_data.x->cursor_pixel;
2674 xgcv.foreground = s->face->background;
2675
2676 /* If the glyph would be invisible, try a different foreground. */
2677 if (xgcv.foreground == xgcv.background)
2678 xgcv.foreground = s->face->foreground;
2679 if (xgcv.foreground == xgcv.background)
2680 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2681 if (xgcv.foreground == xgcv.background)
2682 xgcv.foreground = s->face->foreground;
2683
2684 /* Make sure the cursor is distinct from text in this face. */
2685 if (xgcv.background == s->face->background
2686 && xgcv.foreground == s->face->foreground)
2687 {
2688 xgcv.background = s->face->foreground;
2689 xgcv.foreground = s->face->background;
2690 }
2691
2692 IF_DEBUG (x_check_font (s->f, s->font));
2693 xgcv.font = s->font->fid;
2694 xgcv.graphics_exposures = False;
2695 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2696
2697 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2698 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2699 mask, &xgcv);
2700 else
2701 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2702 = XCreateGC (s->display, s->window, mask, &xgcv);
2703
2704 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2705 }
2706 }
2707
2708
2709 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2710
2711 static void
2712 x_set_mouse_face_gc (s)
2713 struct glyph_string *s;
2714 {
2715 int face_id;
2716 struct face *face;
2717
2718 /* What face has to be used last for the mouse face? */
2719 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2720 face = FACE_FROM_ID (s->f, face_id);
2721 if (face == NULL)
2722 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2723
2724 if (s->first_glyph->type == CHAR_GLYPH)
2725 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2726 else
2727 face_id = FACE_FOR_CHAR (s->f, face, 0);
2728 s->face = FACE_FROM_ID (s->f, face_id);
2729 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2730
2731 /* If font in this face is same as S->font, use it. */
2732 if (s->font == s->face->font)
2733 s->gc = s->face->gc;
2734 else
2735 {
2736 /* Otherwise construct scratch_cursor_gc with values from FACE
2737 but font FONT. */
2738 XGCValues xgcv;
2739 unsigned long mask;
2740
2741 xgcv.background = s->face->background;
2742 xgcv.foreground = s->face->foreground;
2743 IF_DEBUG (x_check_font (s->f, s->font));
2744 xgcv.font = s->font->fid;
2745 xgcv.graphics_exposures = False;
2746 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2747
2748 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2749 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2750 mask, &xgcv);
2751 else
2752 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2753 = XCreateGC (s->display, s->window, mask, &xgcv);
2754
2755 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2756 }
2757
2758 xassert (s->gc != 0);
2759 }
2760
2761
2762 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2763 Faces to use in the mode line have already been computed when the
2764 matrix was built, so there isn't much to do, here. */
2765
2766 static INLINE void
2767 x_set_mode_line_face_gc (s)
2768 struct glyph_string *s;
2769 {
2770 s->gc = s->face->gc;
2771 }
2772
2773
2774 /* Set S->gc of glyph string S for drawing that glyph string. Set
2775 S->stippled_p to a non-zero value if the face of S has a stipple
2776 pattern. */
2777
2778 static INLINE void
2779 x_set_glyph_string_gc (s)
2780 struct glyph_string *s;
2781 {
2782 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2783
2784 if (s->hl == DRAW_NORMAL_TEXT)
2785 {
2786 s->gc = s->face->gc;
2787 s->stippled_p = s->face->stipple != 0;
2788 }
2789 else if (s->hl == DRAW_INVERSE_VIDEO)
2790 {
2791 x_set_mode_line_face_gc (s);
2792 s->stippled_p = s->face->stipple != 0;
2793 }
2794 else if (s->hl == DRAW_CURSOR)
2795 {
2796 x_set_cursor_gc (s);
2797 s->stippled_p = 0;
2798 }
2799 else if (s->hl == DRAW_MOUSE_FACE)
2800 {
2801 x_set_mouse_face_gc (s);
2802 s->stippled_p = s->face->stipple != 0;
2803 }
2804 else if (s->hl == DRAW_IMAGE_RAISED
2805 || s->hl == DRAW_IMAGE_SUNKEN)
2806 {
2807 s->gc = s->face->gc;
2808 s->stippled_p = s->face->stipple != 0;
2809 }
2810 else
2811 {
2812 s->gc = s->face->gc;
2813 s->stippled_p = s->face->stipple != 0;
2814 }
2815
2816 /* GC must have been set. */
2817 xassert (s->gc != 0);
2818 }
2819
2820
2821 /* Return in *R the clipping rectangle for glyph string S. */
2822
2823 static void
2824 x_get_glyph_string_clip_rect (s, r)
2825 struct glyph_string *s;
2826 XRectangle *r;
2827 {
2828 if (s->row->full_width_p)
2829 {
2830 /* Draw full-width. X coordinates are relative to S->w->left. */
2831 int canon_x = CANON_X_UNIT (s->f);
2832
2833 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2834 r->width = XFASTINT (s->w->width) * canon_x;
2835
2836 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2837 {
2838 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2839 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2840 r->x -= width;
2841 }
2842
2843 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2844
2845 /* Unless displaying a mode or menu bar line, which are always
2846 fully visible, clip to the visible part of the row. */
2847 if (s->w->pseudo_window_p)
2848 r->height = s->row->visible_height;
2849 else
2850 r->height = s->height;
2851 }
2852 else
2853 {
2854 /* This is a text line that may be partially visible. */
2855 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2856 r->width = window_box_width (s->w, s->area);
2857 r->height = s->row->visible_height;
2858 }
2859
2860 /* If S draws overlapping rows, it's sufficient to use the top and
2861 bottom of the window for clipping because this glyph string
2862 intentionally draws over other lines. */
2863 if (s->for_overlaps_p)
2864 {
2865 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2866 r->height = window_text_bottom_y (s->w) - r->y;
2867 }
2868 else
2869 {
2870 /* Don't use S->y for clipping because it doesn't take partially
2871 visible lines into account. For example, it can be negative for
2872 partially visible lines at the top of a window. */
2873 if (!s->row->full_width_p
2874 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2875 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2876 else
2877 r->y = max (0, s->row->y);
2878
2879 /* If drawing a tool-bar window, draw it over the internal border
2880 at the top of the window. */
2881 if (s->w == XWINDOW (s->f->tool_bar_window))
2882 r->y -= s->f->output_data.x->internal_border_width;
2883 }
2884
2885 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2886 }
2887
2888
2889 /* Set clipping for output of glyph string S. S may be part of a mode
2890 line or menu if we don't have X toolkit support. */
2891
2892 static INLINE void
2893 x_set_glyph_string_clipping (s)
2894 struct glyph_string *s;
2895 {
2896 XRectangle r;
2897 x_get_glyph_string_clip_rect (s, &r);
2898 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2899 }
2900
2901
2902 /* Compute left and right overhang of glyph string S. If S is a glyph
2903 string for a composition, assume overhangs don't exist. */
2904
2905 static INLINE void
2906 x_compute_glyph_string_overhangs (s)
2907 struct glyph_string *s;
2908 {
2909 if (s->cmp == NULL
2910 && s->first_glyph->type == CHAR_GLYPH)
2911 {
2912 XCharStruct cs;
2913 int direction, font_ascent, font_descent;
2914 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2915 &font_ascent, &font_descent, &cs);
2916 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2917 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2918 }
2919 }
2920
2921
2922 /* Compute overhangs and x-positions for glyph string S and its
2923 predecessors, or successors. X is the starting x-position for S.
2924 BACKWARD_P non-zero means process predecessors. */
2925
2926 static void
2927 x_compute_overhangs_and_x (s, x, backward_p)
2928 struct glyph_string *s;
2929 int x;
2930 int backward_p;
2931 {
2932 if (backward_p)
2933 {
2934 while (s)
2935 {
2936 x_compute_glyph_string_overhangs (s);
2937 x -= s->width;
2938 s->x = x;
2939 s = s->prev;
2940 }
2941 }
2942 else
2943 {
2944 while (s)
2945 {
2946 x_compute_glyph_string_overhangs (s);
2947 s->x = x;
2948 x += s->width;
2949 s = s->next;
2950 }
2951 }
2952 }
2953
2954
2955 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2956 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2957 assumed to be zero. */
2958
2959 static void
2960 x_get_glyph_overhangs (glyph, f, left, right)
2961 struct glyph *glyph;
2962 struct frame *f;
2963 int *left, *right;
2964 {
2965 *left = *right = 0;
2966
2967 if (glyph->type == CHAR_GLYPH)
2968 {
2969 XFontStruct *font;
2970 struct face *face;
2971 struct font_info *font_info;
2972 XChar2b char2b;
2973 XCharStruct *pcm;
2974
2975 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2976 font = face->font;
2977 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2978 if (font
2979 && (pcm = x_per_char_metric (font, &char2b)))
2980 {
2981 if (pcm->rbearing > pcm->width)
2982 *right = pcm->rbearing - pcm->width;
2983 if (pcm->lbearing < 0)
2984 *left = -pcm->lbearing;
2985 }
2986 }
2987 }
2988
2989
2990 /* Return the index of the first glyph preceding glyph string S that
2991 is overwritten by S because of S's left overhang. Value is -1
2992 if no glyphs are overwritten. */
2993
2994 static int
2995 x_left_overwritten (s)
2996 struct glyph_string *s;
2997 {
2998 int k;
2999
3000 if (s->left_overhang)
3001 {
3002 int x = 0, i;
3003 struct glyph *glyphs = s->row->glyphs[s->area];
3004 int first = s->first_glyph - glyphs;
3005
3006 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3007 x -= glyphs[i].pixel_width;
3008
3009 k = i + 1;
3010 }
3011 else
3012 k = -1;
3013
3014 return k;
3015 }
3016
3017
3018 /* Return the index of the first glyph preceding glyph string S that
3019 is overwriting S because of its right overhang. Value is -1 if no
3020 glyph in front of S overwrites S. */
3021
3022 static int
3023 x_left_overwriting (s)
3024 struct glyph_string *s;
3025 {
3026 int i, k, x;
3027 struct glyph *glyphs = s->row->glyphs[s->area];
3028 int first = s->first_glyph - glyphs;
3029
3030 k = -1;
3031 x = 0;
3032 for (i = first - 1; i >= 0; --i)
3033 {
3034 int left, right;
3035 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3036 if (x + right > 0)
3037 k = i;
3038 x -= glyphs[i].pixel_width;
3039 }
3040
3041 return k;
3042 }
3043
3044
3045 /* Return the index of the last glyph following glyph string S that is
3046 not overwritten by S because of S's right overhang. Value is -1 if
3047 no such glyph is found. */
3048
3049 static int
3050 x_right_overwritten (s)
3051 struct glyph_string *s;
3052 {
3053 int k = -1;
3054
3055 if (s->right_overhang)
3056 {
3057 int x = 0, i;
3058 struct glyph *glyphs = s->row->glyphs[s->area];
3059 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3060 int end = s->row->used[s->area];
3061
3062 for (i = first; i < end && s->right_overhang > x; ++i)
3063 x += glyphs[i].pixel_width;
3064
3065 k = i;
3066 }
3067
3068 return k;
3069 }
3070
3071
3072 /* Return the index of the last glyph following glyph string S that
3073 overwrites S because of its left overhang. Value is negative
3074 if no such glyph is found. */
3075
3076 static int
3077 x_right_overwriting (s)
3078 struct glyph_string *s;
3079 {
3080 int i, k, x;
3081 int end = s->row->used[s->area];
3082 struct glyph *glyphs = s->row->glyphs[s->area];
3083 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3084
3085 k = -1;
3086 x = 0;
3087 for (i = first; i < end; ++i)
3088 {
3089 int left, right;
3090 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3091 if (x - left < 0)
3092 k = i;
3093 x += glyphs[i].pixel_width;
3094 }
3095
3096 return k;
3097 }
3098
3099
3100 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3101
3102 static INLINE void
3103 x_clear_glyph_string_rect (s, x, y, w, h)
3104 struct glyph_string *s;
3105 int x, y, w, h;
3106 {
3107 XGCValues xgcv;
3108 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3109 XSetForeground (s->display, s->gc, xgcv.background);
3110 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3111 XSetForeground (s->display, s->gc, xgcv.foreground);
3112 }
3113
3114
3115 /* Draw the background of glyph_string S. If S->background_filled_p
3116 is non-zero don't draw it. FORCE_P non-zero means draw the
3117 background even if it wouldn't be drawn normally. This is used
3118 when a string preceding S draws into the background of S, or S
3119 contains the first component of a composition. */
3120
3121 static void
3122 x_draw_glyph_string_background (s, force_p)
3123 struct glyph_string *s;
3124 int force_p;
3125 {
3126 /* Nothing to do if background has already been drawn or if it
3127 shouldn't be drawn in the first place. */
3128 if (!s->background_filled_p)
3129 {
3130 int box_line_width = max (s->face->box_line_width, 0);
3131
3132 if (s->stippled_p)
3133 {
3134 /* Fill background with a stipple pattern. */
3135 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3136 XFillRectangle (s->display, s->window, s->gc, s->x,
3137 s->y + box_line_width,
3138 s->background_width,
3139 s->height - 2 * box_line_width);
3140 XSetFillStyle (s->display, s->gc, FillSolid);
3141 s->background_filled_p = 1;
3142 }
3143 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3144 || s->font_not_found_p
3145 || s->extends_to_end_of_line_p
3146 || force_p)
3147 {
3148 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3149 s->background_width,
3150 s->height - 2 * box_line_width);
3151 s->background_filled_p = 1;
3152 }
3153 }
3154 }
3155
3156
3157 /* Draw the foreground of glyph string S. */
3158
3159 static void
3160 x_draw_glyph_string_foreground (s)
3161 struct glyph_string *s;
3162 {
3163 int i, x;
3164
3165 /* If first glyph of S has a left box line, start drawing the text
3166 of S to the right of that box line. */
3167 if (s->face->box != FACE_NO_BOX
3168 && s->first_glyph->left_box_line_p)
3169 x = s->x + abs (s->face->box_line_width);
3170 else
3171 x = s->x;
3172
3173 /* Draw characters of S as rectangles if S's font could not be
3174 loaded. */
3175 if (s->font_not_found_p)
3176 {
3177 for (i = 0; i < s->nchars; ++i)
3178 {
3179 struct glyph *g = s->first_glyph + i;
3180 XDrawRectangle (s->display, s->window,
3181 s->gc, x, s->y, g->pixel_width - 1,
3182 s->height - 1);
3183 x += g->pixel_width;
3184 }
3185 }
3186 else
3187 {
3188 char *char1b = (char *) s->char2b;
3189 int boff = s->font_info->baseline_offset;
3190
3191 if (s->font_info->vertical_centering)
3192 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3193
3194 /* If we can use 8-bit functions, condense S->char2b. */
3195 if (!s->two_byte_p)
3196 for (i = 0; i < s->nchars; ++i)
3197 char1b[i] = s->char2b[i].byte2;
3198
3199 /* Draw text with XDrawString if background has already been
3200 filled. Otherwise, use XDrawImageString. (Note that
3201 XDrawImageString is usually faster than XDrawString.) Always
3202 use XDrawImageString when drawing the cursor so that there is
3203 no chance that characters under a box cursor are invisible. */
3204 if (s->for_overlaps_p
3205 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3206 {
3207 /* Draw characters with 16-bit or 8-bit functions. */
3208 if (s->two_byte_p)
3209 XDrawString16 (s->display, s->window, s->gc, x,
3210 s->ybase - boff, s->char2b, s->nchars);
3211 else
3212 XDrawString (s->display, s->window, s->gc, x,
3213 s->ybase - boff, char1b, s->nchars);
3214 }
3215 else
3216 {
3217 if (s->two_byte_p)
3218 XDrawImageString16 (s->display, s->window, s->gc, x,
3219 s->ybase - boff, s->char2b, s->nchars);
3220 else
3221 XDrawImageString (s->display, s->window, s->gc, x,
3222 s->ybase - boff, char1b, s->nchars);
3223 }
3224 }
3225 }
3226
3227 /* Draw the foreground of composite glyph string S. */
3228
3229 static void
3230 x_draw_composite_glyph_string_foreground (s)
3231 struct glyph_string *s;
3232 {
3233 int i, x;
3234
3235 /* If first glyph of S has a left box line, start drawing the text
3236 of S to the right of that box line. */
3237 if (s->face->box != FACE_NO_BOX
3238 && s->first_glyph->left_box_line_p)
3239 x = s->x + abs (s->face->box_line_width);
3240 else
3241 x = s->x;
3242
3243 /* S is a glyph string for a composition. S->gidx is the index of
3244 the first character drawn for glyphs of this composition.
3245 S->gidx == 0 means we are drawing the very first character of
3246 this composition. */
3247
3248 /* Draw a rectangle for the composition if the font for the very
3249 first character of the composition could not be loaded. */
3250 if (s->font_not_found_p)
3251 {
3252 if (s->gidx == 0)
3253 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3254 s->width - 1, s->height - 1);
3255 }
3256 else
3257 {
3258 for (i = 0; i < s->nchars; i++, ++s->gidx)
3259 XDrawString16 (s->display, s->window, s->gc,
3260 x + s->cmp->offsets[s->gidx * 2],
3261 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3262 s->char2b + i, 1);
3263 }
3264 }
3265
3266
3267 #ifdef USE_X_TOOLKIT
3268
3269 static struct frame *x_frame_of_widget P_ ((Widget));
3270 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3271 XrmValue *, XrmValue *, XtPointer *));
3272 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3273 XrmValue *, Cardinal *));
3274
3275
3276 /* Return the frame on which widget WIDGET is used.. Abort if frame
3277 cannot be determined. */
3278
3279 static struct frame *
3280 x_frame_of_widget (widget)
3281 Widget widget;
3282 {
3283 struct x_display_info *dpyinfo;
3284 Lisp_Object tail;
3285 struct frame *f;
3286
3287 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3288
3289 /* Find the top-level shell of the widget. Note that this function
3290 can be called when the widget is not yet realized, so XtWindow
3291 (widget) == 0. That's the reason we can't simply use
3292 x_any_window_to_frame. */
3293 while (!XtIsTopLevelShell (widget))
3294 widget = XtParent (widget);
3295
3296 /* Look for a frame with that top-level widget. Allocate the color
3297 on that frame to get the right gamma correction value. */
3298 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3299 if (GC_FRAMEP (XCAR (tail))
3300 && (f = XFRAME (XCAR (tail)),
3301 (f->output_data.nothing != 1
3302 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3303 && f->output_data.x->widget == widget)
3304 return f;
3305
3306 abort ();
3307 }
3308
3309
3310 /* Allocate the color COLOR->pixel on the screen and display of
3311 widget WIDGET in colormap CMAP. If an exact match cannot be
3312 allocated, try the nearest color available. Value is non-zero
3313 if successful. This is called from lwlib. */
3314
3315 int
3316 x_alloc_nearest_color_for_widget (widget, cmap, color)
3317 Widget widget;
3318 Colormap cmap;
3319 XColor *color;
3320 {
3321 struct frame *f = x_frame_of_widget (widget);
3322 return x_alloc_nearest_color (f, cmap, color);
3323 }
3324
3325
3326 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3327 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3328 If this produces the same color as PIXEL, try a color where all RGB
3329 values have DELTA added. Return the allocated color in *PIXEL.
3330 DISPLAY is the X display, CMAP is the colormap to operate on.
3331 Value is non-zero if successful. */
3332
3333 int
3334 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3335 Widget widget;
3336 Display *display;
3337 Colormap cmap;
3338 unsigned long *pixel;
3339 double factor;
3340 int delta;
3341 {
3342 struct frame *f = x_frame_of_widget (widget);
3343 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3344 }
3345
3346
3347 /* Structure specifying which arguments should be passed by Xt to
3348 cvt_string_to_pixel. We want the widget's screen and colormap. */
3349
3350 static XtConvertArgRec cvt_string_to_pixel_args[] =
3351 {
3352 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3353 sizeof (Screen *)},
3354 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3355 sizeof (Colormap)}
3356 };
3357
3358
3359 /* The address of this variable is returned by
3360 cvt_string_to_pixel. */
3361
3362 static Pixel cvt_string_to_pixel_value;
3363
3364
3365 /* Convert a color name to a pixel color.
3366
3367 DPY is the display we are working on.
3368
3369 ARGS is an array of *NARGS XrmValue structures holding additional
3370 information about the widget for which the conversion takes place.
3371 The contents of this array are determined by the specification
3372 in cvt_string_to_pixel_args.
3373
3374 FROM is a pointer to an XrmValue which points to the color name to
3375 convert. TO is an XrmValue in which to return the pixel color.
3376
3377 CLOSURE_RET is a pointer to user-data, in which we record if
3378 we allocated the color or not.
3379
3380 Value is True if successful, False otherwise. */
3381
3382 static Boolean
3383 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3384 Display *dpy;
3385 XrmValue *args;
3386 Cardinal *nargs;
3387 XrmValue *from, *to;
3388 XtPointer *closure_ret;
3389 {
3390 Screen *screen;
3391 Colormap cmap;
3392 Pixel pixel;
3393 String color_name;
3394 XColor color;
3395
3396 if (*nargs != 2)
3397 {
3398 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3399 "wrongParameters", "cvt_string_to_pixel",
3400 "XtToolkitError",
3401 "Screen and colormap args required", NULL, NULL);
3402 return False;
3403 }
3404
3405 screen = *(Screen **) args[0].addr;
3406 cmap = *(Colormap *) args[1].addr;
3407 color_name = (String) from->addr;
3408
3409 if (strcmp (color_name, XtDefaultBackground) == 0)
3410 {
3411 *closure_ret = (XtPointer) False;
3412 pixel = WhitePixelOfScreen (screen);
3413 }
3414 else if (strcmp (color_name, XtDefaultForeground) == 0)
3415 {
3416 *closure_ret = (XtPointer) False;
3417 pixel = BlackPixelOfScreen (screen);
3418 }
3419 else if (XParseColor (dpy, cmap, color_name, &color)
3420 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3421 {
3422 pixel = color.pixel;
3423 *closure_ret = (XtPointer) True;
3424 }
3425 else
3426 {
3427 String params[1];
3428 Cardinal nparams = 1;
3429
3430 params[0] = color_name;
3431 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3432 "badValue", "cvt_string_to_pixel",
3433 "XtToolkitError", "Invalid color `%s'",
3434 params, &nparams);
3435 return False;
3436 }
3437
3438 if (to->addr != NULL)
3439 {
3440 if (to->size < sizeof (Pixel))
3441 {
3442 to->size = sizeof (Pixel);
3443 return False;
3444 }
3445
3446 *(Pixel *) to->addr = pixel;
3447 }
3448 else
3449 {
3450 cvt_string_to_pixel_value = pixel;
3451 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3452 }
3453
3454 to->size = sizeof (Pixel);
3455 return True;
3456 }
3457
3458
3459 /* Free a pixel color which was previously allocated via
3460 cvt_string_to_pixel. This is registered as the destructor
3461 for this type of resource via XtSetTypeConverter.
3462
3463 APP is the application context in which we work.
3464
3465 TO is a pointer to an XrmValue holding the color to free.
3466 CLOSURE is the value we stored in CLOSURE_RET for this color
3467 in cvt_string_to_pixel.
3468
3469 ARGS and NARGS are like for cvt_string_to_pixel. */
3470
3471 static void
3472 cvt_pixel_dtor (app, to, closure, args, nargs)
3473 XtAppContext app;
3474 XrmValuePtr to;
3475 XtPointer closure;
3476 XrmValuePtr args;
3477 Cardinal *nargs;
3478 {
3479 if (*nargs != 2)
3480 {
3481 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3482 "XtToolkitError",
3483 "Screen and colormap arguments required",
3484 NULL, NULL);
3485 }
3486 else if (closure != NULL)
3487 {
3488 /* We did allocate the pixel, so free it. */
3489 Screen *screen = *(Screen **) args[0].addr;
3490 Colormap cmap = *(Colormap *) args[1].addr;
3491 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3492 (Pixel *) to->addr, 1);
3493 }
3494 }
3495
3496
3497 #endif /* USE_X_TOOLKIT */
3498
3499
3500 /* Value is an array of XColor structures for the contents of the
3501 color map of display DPY. Set *NCELLS to the size of the array.
3502 Note that this probably shouldn't be called for large color maps,
3503 say a 24-bit TrueColor map. */
3504
3505 static const XColor *
3506 x_color_cells (dpy, ncells)
3507 Display *dpy;
3508 int *ncells;
3509 {
3510 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3511
3512 if (dpyinfo->color_cells == NULL)
3513 {
3514 Screen *screen = dpyinfo->screen;
3515 int i;
3516
3517 dpyinfo->ncolor_cells
3518 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3519 dpyinfo->color_cells
3520 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3521 * sizeof *dpyinfo->color_cells);
3522
3523 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3524 dpyinfo->color_cells[i].pixel = i;
3525
3526 XQueryColors (dpy, dpyinfo->cmap,
3527 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3528 }
3529
3530 *ncells = dpyinfo->ncolor_cells;
3531 return dpyinfo->color_cells;
3532 }
3533
3534
3535 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3536 colors in COLORS. Use cached information, if available. */
3537
3538 void
3539 x_query_colors (f, colors, ncolors)
3540 struct frame *f;
3541 XColor *colors;
3542 int ncolors;
3543 {
3544 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3545
3546 if (dpyinfo->color_cells)
3547 {
3548 int i;
3549 for (i = 0; i < ncolors; ++i)
3550 {
3551 unsigned long pixel = colors[i].pixel;
3552 xassert (pixel < dpyinfo->ncolor_cells);
3553 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3554 colors[i] = dpyinfo->color_cells[pixel];
3555 }
3556 }
3557 else
3558 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3559 }
3560
3561
3562 /* On frame F, translate pixel color to RGB values for the color in
3563 COLOR. Use cached information, if available. */
3564
3565 void
3566 x_query_color (f, color)
3567 struct frame *f;
3568 XColor *color;
3569 {
3570 x_query_colors (f, color, 1);
3571 }
3572
3573
3574 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3575 exact match can't be allocated, try the nearest color available.
3576 Value is non-zero if successful. Set *COLOR to the color
3577 allocated. */
3578
3579 static int
3580 x_alloc_nearest_color_1 (dpy, cmap, color)
3581 Display *dpy;
3582 Colormap cmap;
3583 XColor *color;
3584 {
3585 int rc;
3586
3587 rc = XAllocColor (dpy, cmap, color);
3588 if (rc == 0)
3589 {
3590 /* If we got to this point, the colormap is full, so we're going
3591 to try to get the next closest color. The algorithm used is
3592 a least-squares matching, which is what X uses for closest
3593 color matching with StaticColor visuals. */
3594 int nearest, i;
3595 unsigned long nearest_delta = ~0;
3596 int ncells;
3597 const XColor *cells = x_color_cells (dpy, &ncells);
3598
3599 for (nearest = i = 0; i < ncells; ++i)
3600 {
3601 long dred = (color->red >> 8) - (cells[i].red >> 8);
3602 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3603 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3604 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3605
3606 if (delta < nearest_delta)
3607 {
3608 nearest = i;
3609 nearest_delta = delta;
3610 }
3611 }
3612
3613 color->red = cells[nearest].red;
3614 color->green = cells[nearest].green;
3615 color->blue = cells[nearest].blue;
3616 rc = XAllocColor (dpy, cmap, color);
3617 }
3618 else
3619 {
3620 /* If allocation succeeded, and the allocated pixel color is not
3621 equal to a cached pixel color recorded earlier, there was a
3622 change in the colormap, so clear the color cache. */
3623 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3624 XColor *cached_color;
3625
3626 if (dpyinfo->color_cells
3627 && (cached_color = &dpyinfo->color_cells[color->pixel],
3628 (cached_color->red != color->red
3629 || cached_color->blue != color->blue
3630 || cached_color->green != color->green)))
3631 {
3632 xfree (dpyinfo->color_cells);
3633 dpyinfo->color_cells = NULL;
3634 dpyinfo->ncolor_cells = 0;
3635 }
3636 }
3637
3638 #ifdef DEBUG_X_COLORS
3639 if (rc)
3640 register_color (color->pixel);
3641 #endif /* DEBUG_X_COLORS */
3642
3643 return rc;
3644 }
3645
3646
3647 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3648 exact match can't be allocated, try the nearest color available.
3649 Value is non-zero if successful. Set *COLOR to the color
3650 allocated. */
3651
3652 int
3653 x_alloc_nearest_color (f, cmap, color)
3654 struct frame *f;
3655 Colormap cmap;
3656 XColor *color;
3657 {
3658 gamma_correct (f, color);
3659 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3660 }
3661
3662
3663 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3664 It's necessary to do this instead of just using PIXEL directly to
3665 get color reference counts right. */
3666
3667 unsigned long
3668 x_copy_color (f, pixel)
3669 struct frame *f;
3670 unsigned long pixel;
3671 {
3672 XColor color;
3673
3674 color.pixel = pixel;
3675 BLOCK_INPUT;
3676 x_query_color (f, &color);
3677 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3678 UNBLOCK_INPUT;
3679 #ifdef DEBUG_X_COLORS
3680 register_color (pixel);
3681 #endif
3682 return color.pixel;
3683 }
3684
3685
3686 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3687 It's necessary to do this instead of just using PIXEL directly to
3688 get color reference counts right. */
3689
3690 unsigned long
3691 x_copy_dpy_color (dpy, cmap, pixel)
3692 Display *dpy;
3693 Colormap cmap;
3694 unsigned long pixel;
3695 {
3696 XColor color;
3697
3698 color.pixel = pixel;
3699 BLOCK_INPUT;
3700 XQueryColor (dpy, cmap, &color);
3701 XAllocColor (dpy, cmap, &color);
3702 UNBLOCK_INPUT;
3703 #ifdef DEBUG_X_COLORS
3704 register_color (pixel);
3705 #endif
3706 return color.pixel;
3707 }
3708
3709
3710 /* Brightness beyond which a color won't have its highlight brightness
3711 boosted.
3712
3713 Nominally, highlight colors for `3d' faces are calculated by
3714 brightening an object's color by a constant scale factor, but this
3715 doesn't yield good results for dark colors, so for colors who's
3716 brightness is less than this value (on a scale of 0-65535) have an
3717 use an additional additive factor.
3718
3719 The value here is set so that the default menu-bar/mode-line color
3720 (grey75) will not have its highlights changed at all. */
3721 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3722
3723
3724 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3725 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3726 If this produces the same color as PIXEL, try a color where all RGB
3727 values have DELTA added. Return the allocated color in *PIXEL.
3728 DISPLAY is the X display, CMAP is the colormap to operate on.
3729 Value is non-zero if successful. */
3730
3731 static int
3732 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3733 struct frame *f;
3734 Display *display;
3735 Colormap cmap;
3736 unsigned long *pixel;
3737 double factor;
3738 int delta;
3739 {
3740 XColor color, new;
3741 long bright;
3742 int success_p;
3743
3744 /* Get RGB color values. */
3745 color.pixel = *pixel;
3746 x_query_color (f, &color);
3747
3748 /* Change RGB values by specified FACTOR. Avoid overflow! */
3749 xassert (factor >= 0);
3750 new.red = min (0xffff, factor * color.red);
3751 new.green = min (0xffff, factor * color.green);
3752 new.blue = min (0xffff, factor * color.blue);
3753
3754 /* Calculate brightness of COLOR. */
3755 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3756
3757 /* We only boost colors that are darker than
3758 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3759 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3760 /* Make an additive adjustment to NEW, because it's dark enough so
3761 that scaling by FACTOR alone isn't enough. */
3762 {
3763 /* How far below the limit this color is (0 - 1, 1 being darker). */
3764 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3765 /* The additive adjustment. */
3766 int min_delta = delta * dimness * factor / 2;
3767
3768 if (factor < 1)
3769 {
3770 new.red = max (0, new.red - min_delta);
3771 new.green = max (0, new.green - min_delta);
3772 new.blue = max (0, new.blue - min_delta);
3773 }
3774 else
3775 {
3776 new.red = min (0xffff, min_delta + new.red);
3777 new.green = min (0xffff, min_delta + new.green);
3778 new.blue = min (0xffff, min_delta + new.blue);
3779 }
3780 }
3781
3782 /* Try to allocate the color. */
3783 success_p = x_alloc_nearest_color (f, cmap, &new);
3784 if (success_p)
3785 {
3786 if (new.pixel == *pixel)
3787 {
3788 /* If we end up with the same color as before, try adding
3789 delta to the RGB values. */
3790 x_free_colors (f, &new.pixel, 1);
3791
3792 new.red = min (0xffff, delta + color.red);
3793 new.green = min (0xffff, delta + color.green);
3794 new.blue = min (0xffff, delta + color.blue);
3795 success_p = x_alloc_nearest_color (f, cmap, &new);
3796 }
3797 else
3798 success_p = 1;
3799 *pixel = new.pixel;
3800 }
3801
3802 return success_p;
3803 }
3804
3805
3806 /* Set up the foreground color for drawing relief lines of glyph
3807 string S. RELIEF is a pointer to a struct relief containing the GC
3808 with which lines will be drawn. Use a color that is FACTOR or
3809 DELTA lighter or darker than the relief's background which is found
3810 in S->f->output_data.x->relief_background. If such a color cannot
3811 be allocated, use DEFAULT_PIXEL, instead. */
3812
3813 static void
3814 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3815 struct frame *f;
3816 struct relief *relief;
3817 double factor;
3818 int delta;
3819 unsigned long default_pixel;
3820 {
3821 XGCValues xgcv;
3822 struct x_output *di = f->output_data.x;
3823 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3824 unsigned long pixel;
3825 unsigned long background = di->relief_background;
3826 Colormap cmap = FRAME_X_COLORMAP (f);
3827 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3828 Display *dpy = FRAME_X_DISPLAY (f);
3829
3830 xgcv.graphics_exposures = False;
3831 xgcv.line_width = 1;
3832
3833 /* Free previously allocated color. The color cell will be reused
3834 when it has been freed as many times as it was allocated, so this
3835 doesn't affect faces using the same colors. */
3836 if (relief->gc
3837 && relief->allocated_p)
3838 {
3839 x_free_colors (f, &relief->pixel, 1);
3840 relief->allocated_p = 0;
3841 }
3842
3843 /* Allocate new color. */
3844 xgcv.foreground = default_pixel;
3845 pixel = background;
3846 if (dpyinfo->n_planes != 1
3847 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3848 {
3849 relief->allocated_p = 1;
3850 xgcv.foreground = relief->pixel = pixel;
3851 }
3852
3853 if (relief->gc == 0)
3854 {
3855 xgcv.stipple = dpyinfo->gray;
3856 mask |= GCStipple;
3857 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3858 }
3859 else
3860 XChangeGC (dpy, relief->gc, mask, &xgcv);
3861 }
3862
3863
3864 /* Set up colors for the relief lines around glyph string S. */
3865
3866 static void
3867 x_setup_relief_colors (s)
3868 struct glyph_string *s;
3869 {
3870 struct x_output *di = s->f->output_data.x;
3871 unsigned long color;
3872
3873 if (s->face->use_box_color_for_shadows_p)
3874 color = s->face->box_color;
3875 else if (s->first_glyph->type == IMAGE_GLYPH
3876 && s->img->pixmap
3877 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3878 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3879 else
3880 {
3881 XGCValues xgcv;
3882
3883 /* Get the background color of the face. */
3884 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3885 color = xgcv.background;
3886 }
3887
3888 if (di->white_relief.gc == 0
3889 || color != di->relief_background)
3890 {
3891 di->relief_background = color;
3892 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3893 WHITE_PIX_DEFAULT (s->f));
3894 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3895 BLACK_PIX_DEFAULT (s->f));
3896 }
3897 }
3898
3899
3900 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3901 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3902 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3903 relief. LEFT_P non-zero means draw a relief on the left side of
3904 the rectangle. RIGHT_P non-zero means draw a relief on the right
3905 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3906 when drawing. */
3907
3908 static void
3909 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3910 raised_p, left_p, right_p, clip_rect)
3911 struct frame *f;
3912 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3913 XRectangle *clip_rect;
3914 {
3915 Display *dpy = FRAME_X_DISPLAY (f);
3916 Window window = FRAME_X_WINDOW (f);
3917 int i;
3918 GC gc;
3919
3920 if (raised_p)
3921 gc = f->output_data.x->white_relief.gc;
3922 else
3923 gc = f->output_data.x->black_relief.gc;
3924 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3925
3926 /* Top. */
3927 for (i = 0; i < width; ++i)
3928 XDrawLine (dpy, window, gc,
3929 left_x + i * left_p, top_y + i,
3930 right_x + 1 - i * right_p, top_y + i);
3931
3932 /* Left. */
3933 if (left_p)
3934 for (i = 0; i < width; ++i)
3935 XDrawLine (dpy, window, gc,
3936 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3937
3938 XSetClipMask (dpy, gc, None);
3939 if (raised_p)
3940 gc = f->output_data.x->black_relief.gc;
3941 else
3942 gc = f->output_data.x->white_relief.gc;
3943 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3944
3945 /* Bottom. */
3946 for (i = 0; i < width; ++i)
3947 XDrawLine (dpy, window, gc,
3948 left_x + i * left_p, bottom_y - i,
3949 right_x + 1 - i * right_p, bottom_y - i);
3950
3951 /* Right. */
3952 if (right_p)
3953 for (i = 0; i < width; ++i)
3954 XDrawLine (dpy, window, gc,
3955 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3956
3957 XSetClipMask (dpy, gc, None);
3958 }
3959
3960
3961 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3962 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3963 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3964 left side of the rectangle. RIGHT_P non-zero means draw a line
3965 on the right side of the rectangle. CLIP_RECT is the clipping
3966 rectangle to use when drawing. */
3967
3968 static void
3969 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3970 left_p, right_p, clip_rect)
3971 struct glyph_string *s;
3972 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3973 XRectangle *clip_rect;
3974 {
3975 XGCValues xgcv;
3976
3977 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3978 XSetForeground (s->display, s->gc, s->face->box_color);
3979 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3980
3981 /* Top. */
3982 XFillRectangle (s->display, s->window, s->gc,
3983 left_x, top_y, right_x - left_x + 1, width);
3984
3985 /* Left. */
3986 if (left_p)
3987 XFillRectangle (s->display, s->window, s->gc,
3988 left_x, top_y, width, bottom_y - top_y + 1);
3989
3990 /* Bottom. */
3991 XFillRectangle (s->display, s->window, s->gc,
3992 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3993
3994 /* Right. */
3995 if (right_p)
3996 XFillRectangle (s->display, s->window, s->gc,
3997 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3998
3999 XSetForeground (s->display, s->gc, xgcv.foreground);
4000 XSetClipMask (s->display, s->gc, None);
4001 }
4002
4003
4004 /* Draw a box around glyph string S. */
4005
4006 static void
4007 x_draw_glyph_string_box (s)
4008 struct glyph_string *s;
4009 {
4010 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4011 int left_p, right_p;
4012 struct glyph *last_glyph;
4013 XRectangle clip_rect;
4014
4015 last_x = window_box_right (s->w, s->area);
4016 if (s->row->full_width_p
4017 && !s->w->pseudo_window_p)
4018 {
4019 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4020 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4021 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4022 }
4023
4024 /* The glyph that may have a right box line. */
4025 last_glyph = (s->cmp || s->img
4026 ? s->first_glyph
4027 : s->first_glyph + s->nchars - 1);
4028
4029 width = abs (s->face->box_line_width);
4030 raised_p = s->face->box == FACE_RAISED_BOX;
4031 left_x = s->x;
4032 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
4033 ? last_x - 1
4034 : min (last_x, s->x + s->background_width) - 1);
4035 top_y = s->y;
4036 bottom_y = top_y + s->height - 1;
4037
4038 left_p = (s->first_glyph->left_box_line_p
4039 || (s->hl == DRAW_MOUSE_FACE
4040 && (s->prev == NULL
4041 || s->prev->hl != s->hl)));
4042 right_p = (last_glyph->right_box_line_p
4043 || (s->hl == DRAW_MOUSE_FACE
4044 && (s->next == NULL
4045 || s->next->hl != s->hl)));
4046
4047 x_get_glyph_string_clip_rect (s, &clip_rect);
4048
4049 if (s->face->box == FACE_SIMPLE_BOX)
4050 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4051 left_p, right_p, &clip_rect);
4052 else
4053 {
4054 x_setup_relief_colors (s);
4055 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4056 width, raised_p, left_p, right_p, &clip_rect);
4057 }
4058 }
4059
4060
4061 /* Draw foreground of image glyph string S. */
4062
4063 static void
4064 x_draw_image_foreground (s)
4065 struct glyph_string *s;
4066 {
4067 int x;
4068 int y = s->ybase - image_ascent (s->img, s->face);
4069
4070 /* If first glyph of S has a left box line, start drawing it to the
4071 right of that line. */
4072 if (s->face->box != FACE_NO_BOX
4073 && s->first_glyph->left_box_line_p)
4074 x = s->x + abs (s->face->box_line_width);
4075 else
4076 x = s->x;
4077
4078 /* If there is a margin around the image, adjust x- and y-position
4079 by that margin. */
4080 x += s->img->hmargin;
4081 y += s->img->vmargin;
4082
4083 if (s->img->pixmap)
4084 {
4085 if (s->img->mask)
4086 {
4087 /* We can't set both a clip mask and use XSetClipRectangles
4088 because the latter also sets a clip mask. We also can't
4089 trust on the shape extension to be available
4090 (XShapeCombineRegion). So, compute the rectangle to draw
4091 manually. */
4092 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4093 | GCFunction);
4094 XGCValues xgcv;
4095 XRectangle clip_rect, image_rect, r;
4096
4097 xgcv.clip_mask = s->img->mask;
4098 xgcv.clip_x_origin = x;
4099 xgcv.clip_y_origin = y;
4100 xgcv.function = GXcopy;
4101 XChangeGC (s->display, s->gc, mask, &xgcv);
4102
4103 x_get_glyph_string_clip_rect (s, &clip_rect);
4104 image_rect.x = x;
4105 image_rect.y = y;
4106 image_rect.width = s->img->width;
4107 image_rect.height = s->img->height;
4108 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4109 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4110 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4111 }
4112 else
4113 {
4114 XRectangle clip_rect, image_rect, r;
4115
4116 x_get_glyph_string_clip_rect (s, &clip_rect);
4117 image_rect.x = x;
4118 image_rect.y = y;
4119 image_rect.width = s->img->width;
4120 image_rect.height = s->img->height;
4121 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4122 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4123 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4124
4125 /* When the image has a mask, we can expect that at
4126 least part of a mouse highlight or a block cursor will
4127 be visible. If the image doesn't have a mask, make
4128 a block cursor visible by drawing a rectangle around
4129 the image. I believe it's looking better if we do
4130 nothing here for mouse-face. */
4131 if (s->hl == DRAW_CURSOR)
4132 {
4133 int r = s->img->relief;
4134 if (r < 0) r = -r;
4135 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
4136 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4137 }
4138 }
4139 }
4140 else
4141 /* Draw a rectangle if image could not be loaded. */
4142 XDrawRectangle (s->display, s->window, s->gc, x, y,
4143 s->img->width - 1, s->img->height - 1);
4144 }
4145
4146
4147 /* Draw a relief around the image glyph string S. */
4148
4149 static void
4150 x_draw_image_relief (s)
4151 struct glyph_string *s;
4152 {
4153 int x0, y0, x1, y1, thick, raised_p;
4154 XRectangle r;
4155 int x;
4156 int y = s->ybase - image_ascent (s->img, s->face);
4157
4158 /* If first glyph of S has a left box line, start drawing it to the
4159 right of that line. */
4160 if (s->face->box != FACE_NO_BOX
4161 && s->first_glyph->left_box_line_p)
4162 x = s->x + abs (s->face->box_line_width);
4163 else
4164 x = s->x;
4165
4166 /* If there is a margin around the image, adjust x- and y-position
4167 by that margin. */
4168 x += s->img->hmargin;
4169 y += s->img->vmargin;
4170
4171 if (s->hl == DRAW_IMAGE_SUNKEN
4172 || s->hl == DRAW_IMAGE_RAISED)
4173 {
4174 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4175 raised_p = s->hl == DRAW_IMAGE_RAISED;
4176 }
4177 else
4178 {
4179 thick = abs (s->img->relief);
4180 raised_p = s->img->relief > 0;
4181 }
4182
4183 x0 = x - thick;
4184 y0 = y - thick;
4185 x1 = x + s->img->width + thick - 1;
4186 y1 = y + s->img->height + thick - 1;
4187
4188 x_setup_relief_colors (s);
4189 x_get_glyph_string_clip_rect (s, &r);
4190 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4191 }
4192
4193
4194 /* Draw the foreground of image glyph string S to PIXMAP. */
4195
4196 static void
4197 x_draw_image_foreground_1 (s, pixmap)
4198 struct glyph_string *s;
4199 Pixmap pixmap;
4200 {
4201 int x;
4202 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4203
4204 /* If first glyph of S has a left box line, start drawing it to the
4205 right of that line. */
4206 if (s->face->box != FACE_NO_BOX
4207 && s->first_glyph->left_box_line_p)
4208 x = abs (s->face->box_line_width);
4209 else
4210 x = 0;
4211
4212 /* If there is a margin around the image, adjust x- and y-position
4213 by that margin. */
4214 x += s->img->hmargin;
4215 y += s->img->vmargin;
4216
4217 if (s->img->pixmap)
4218 {
4219 if (s->img->mask)
4220 {
4221 /* We can't set both a clip mask and use XSetClipRectangles
4222 because the latter also sets a clip mask. We also can't
4223 trust on the shape extension to be available
4224 (XShapeCombineRegion). So, compute the rectangle to draw
4225 manually. */
4226 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4227 | GCFunction);
4228 XGCValues xgcv;
4229
4230 xgcv.clip_mask = s->img->mask;
4231 xgcv.clip_x_origin = x;
4232 xgcv.clip_y_origin = y;
4233 xgcv.function = GXcopy;
4234 XChangeGC (s->display, s->gc, mask, &xgcv);
4235
4236 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4237 0, 0, s->img->width, s->img->height, x, y);
4238 XSetClipMask (s->display, s->gc, None);
4239 }
4240 else
4241 {
4242 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4243 0, 0, s->img->width, s->img->height, x, y);
4244
4245 /* When the image has a mask, we can expect that at
4246 least part of a mouse highlight or a block cursor will
4247 be visible. If the image doesn't have a mask, make
4248 a block cursor visible by drawing a rectangle around
4249 the image. I believe it's looking better if we do
4250 nothing here for mouse-face. */
4251 if (s->hl == DRAW_CURSOR)
4252 {
4253 int r = s->img->relief;
4254 if (r < 0) r = -r;
4255 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
4256 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4257 }
4258 }
4259 }
4260 else
4261 /* Draw a rectangle if image could not be loaded. */
4262 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4263 s->img->width - 1, s->img->height - 1);
4264 }
4265
4266
4267 /* Draw part of the background of glyph string S. X, Y, W, and H
4268 give the rectangle to draw. */
4269
4270 static void
4271 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4272 struct glyph_string *s;
4273 int x, y, w, h;
4274 {
4275 if (s->stippled_p)
4276 {
4277 /* Fill background with a stipple pattern. */
4278 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4279 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4280 XSetFillStyle (s->display, s->gc, FillSolid);
4281 }
4282 else
4283 x_clear_glyph_string_rect (s, x, y, w, h);
4284 }
4285
4286
4287 /* Draw image glyph string S.
4288
4289 s->y
4290 s->x +-------------------------
4291 | s->face->box
4292 |
4293 | +-------------------------
4294 | | s->img->margin
4295 | |
4296 | | +-------------------
4297 | | | the image
4298
4299 */
4300
4301 static void
4302 x_draw_image_glyph_string (s)
4303 struct glyph_string *s;
4304 {
4305 int x, y;
4306 int box_line_hwidth = abs (s->face->box_line_width);
4307 int box_line_vwidth = max (s->face->box_line_width, 0);
4308 int height;
4309 Pixmap pixmap = None;
4310
4311 height = s->height - 2 * box_line_vwidth;
4312
4313 /* Fill background with face under the image. Do it only if row is
4314 taller than image or if image has a clip mask to reduce
4315 flickering. */
4316 s->stippled_p = s->face->stipple != 0;
4317 if (height > s->img->height
4318 || s->img->hmargin
4319 || s->img->vmargin
4320 || s->img->mask
4321 || s->img->pixmap == 0
4322 || s->width != s->background_width)
4323 {
4324 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4325 x = s->x + box_line_hwidth;
4326 else
4327 x = s->x;
4328
4329 y = s->y + box_line_vwidth;
4330
4331 if (s->img->mask)
4332 {
4333 /* Create a pixmap as large as the glyph string. Fill it
4334 with the background color. Copy the image to it, using
4335 its mask. Copy the temporary pixmap to the display. */
4336 Screen *screen = FRAME_X_SCREEN (s->f);
4337 int depth = DefaultDepthOfScreen (screen);
4338
4339 /* Create a pixmap as large as the glyph string. */
4340 pixmap = XCreatePixmap (s->display, s->window,
4341 s->background_width,
4342 s->height, depth);
4343
4344 /* Don't clip in the following because we're working on the
4345 pixmap. */
4346 XSetClipMask (s->display, s->gc, None);
4347
4348 /* Fill the pixmap with the background color/stipple. */
4349 if (s->stippled_p)
4350 {
4351 /* Fill background with a stipple pattern. */
4352 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4353 XFillRectangle (s->display, pixmap, s->gc,
4354 0, 0, s->background_width, s->height);
4355 XSetFillStyle (s->display, s->gc, FillSolid);
4356 }
4357 else
4358 {
4359 XGCValues xgcv;
4360 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4361 &xgcv);
4362 XSetForeground (s->display, s->gc, xgcv.background);
4363 XFillRectangle (s->display, pixmap, s->gc,
4364 0, 0, s->background_width, s->height);
4365 XSetForeground (s->display, s->gc, xgcv.foreground);
4366 }
4367 }
4368 else
4369 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4370
4371 s->background_filled_p = 1;
4372 }
4373
4374 /* Draw the foreground. */
4375 if (pixmap != None)
4376 {
4377 x_draw_image_foreground_1 (s, pixmap);
4378 x_set_glyph_string_clipping (s);
4379 XCopyArea (s->display, pixmap, s->window, s->gc,
4380 0, 0, s->background_width, s->height, s->x, s->y);
4381 XFreePixmap (s->display, pixmap);
4382 }
4383 else
4384 x_draw_image_foreground (s);
4385
4386 /* If we must draw a relief around the image, do it. */
4387 if (s->img->relief
4388 || s->hl == DRAW_IMAGE_RAISED
4389 || s->hl == DRAW_IMAGE_SUNKEN)
4390 x_draw_image_relief (s);
4391 }
4392
4393
4394 /* Draw stretch glyph string S. */
4395
4396 static void
4397 x_draw_stretch_glyph_string (s)
4398 struct glyph_string *s;
4399 {
4400 xassert (s->first_glyph->type == STRETCH_GLYPH);
4401 s->stippled_p = s->face->stipple != 0;
4402
4403 if (s->hl == DRAW_CURSOR
4404 && !x_stretch_cursor_p)
4405 {
4406 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4407 as wide as the stretch glyph. */
4408 int width = min (CANON_X_UNIT (s->f), s->background_width);
4409
4410 /* Draw cursor. */
4411 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4412
4413 /* Clear rest using the GC of the original non-cursor face. */
4414 if (width < s->background_width)
4415 {
4416 int x = s->x + width, y = s->y;
4417 int w = s->background_width - width, h = s->height;
4418 XRectangle r;
4419 GC gc;
4420
4421 if (s->row->mouse_face_p
4422 && cursor_in_mouse_face_p (s->w))
4423 {
4424 x_set_mouse_face_gc (s);
4425 gc = s->gc;
4426 }
4427 else
4428 gc = s->face->gc;
4429
4430 x_get_glyph_string_clip_rect (s, &r);
4431 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4432
4433 if (s->face->stipple)
4434 {
4435 /* Fill background with a stipple pattern. */
4436 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4437 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4438 XSetFillStyle (s->display, gc, FillSolid);
4439 }
4440 else
4441 {
4442 XGCValues xgcv;
4443 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4444 XSetForeground (s->display, gc, xgcv.background);
4445 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4446 XSetForeground (s->display, gc, xgcv.foreground);
4447 }
4448 }
4449 }
4450 else if (!s->background_filled_p)
4451 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4452 s->height);
4453
4454 s->background_filled_p = 1;
4455 }
4456
4457
4458 /* Draw glyph string S. */
4459
4460 static void
4461 x_draw_glyph_string (s)
4462 struct glyph_string *s;
4463 {
4464 int relief_drawn_p = 0;
4465
4466 /* If S draws into the background of its successor, draw the
4467 background of the successor first so that S can draw into it.
4468 This makes S->next use XDrawString instead of XDrawImageString. */
4469 if (s->next && s->right_overhang && !s->for_overlaps_p)
4470 {
4471 xassert (s->next->img == NULL);
4472 x_set_glyph_string_gc (s->next);
4473 x_set_glyph_string_clipping (s->next);
4474 x_draw_glyph_string_background (s->next, 1);
4475 }
4476
4477 /* Set up S->gc, set clipping and draw S. */
4478 x_set_glyph_string_gc (s);
4479
4480 /* Draw relief (if any) in advance for char/composition so that the
4481 glyph string can be drawn over it. */
4482 if (!s->for_overlaps_p
4483 && s->face->box != FACE_NO_BOX
4484 && (s->first_glyph->type == CHAR_GLYPH
4485 || s->first_glyph->type == COMPOSITE_GLYPH))
4486
4487 {
4488 x_set_glyph_string_clipping (s);
4489 x_draw_glyph_string_background (s, 1);
4490 x_draw_glyph_string_box (s);
4491 x_set_glyph_string_clipping (s);
4492 relief_drawn_p = 1;
4493 }
4494 else
4495 x_set_glyph_string_clipping (s);
4496
4497 switch (s->first_glyph->type)
4498 {
4499 case IMAGE_GLYPH:
4500 x_draw_image_glyph_string (s);
4501 break;
4502
4503 case STRETCH_GLYPH:
4504 x_draw_stretch_glyph_string (s);
4505 break;
4506
4507 case CHAR_GLYPH:
4508 if (s->for_overlaps_p)
4509 s->background_filled_p = 1;
4510 else
4511 x_draw_glyph_string_background (s, 0);
4512 x_draw_glyph_string_foreground (s);
4513 break;
4514
4515 case COMPOSITE_GLYPH:
4516 if (s->for_overlaps_p || s->gidx > 0)
4517 s->background_filled_p = 1;
4518 else
4519 x_draw_glyph_string_background (s, 1);
4520 x_draw_composite_glyph_string_foreground (s);
4521 break;
4522
4523 default:
4524 abort ();
4525 }
4526
4527 if (!s->for_overlaps_p)
4528 {
4529 /* Draw underline. */
4530 if (s->face->underline_p)
4531 {
4532 unsigned long tem, h;
4533 int y;
4534
4535 /* Get the underline thickness. Default is 1 pixel. */
4536 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4537 h = 1;
4538
4539 /* Get the underline position. This is the recommended
4540 vertical offset in pixels from the baseline to the top of
4541 the underline. This is a signed value according to the
4542 specs, and its default is
4543
4544 ROUND ((maximum descent) / 2), with
4545 ROUND(x) = floor (x + 0.5) */
4546
4547 if (x_use_underline_position_properties
4548 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4549 y = s->ybase + (long) tem;
4550 else if (s->face->font)
4551 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4552 else
4553 y = s->y + s->height - h;
4554
4555 if (s->face->underline_defaulted_p)
4556 XFillRectangle (s->display, s->window, s->gc,
4557 s->x, y, s->width, h);
4558 else
4559 {
4560 XGCValues xgcv;
4561 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4562 XSetForeground (s->display, s->gc, s->face->underline_color);
4563 XFillRectangle (s->display, s->window, s->gc,
4564 s->x, y, s->width, h);
4565 XSetForeground (s->display, s->gc, xgcv.foreground);
4566 }
4567 }
4568
4569 /* Draw overline. */
4570 if (s->face->overline_p)
4571 {
4572 unsigned long dy = 0, h = 1;
4573
4574 if (s->face->overline_color_defaulted_p)
4575 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4576 s->width, h);
4577 else
4578 {
4579 XGCValues xgcv;
4580 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4581 XSetForeground (s->display, s->gc, s->face->overline_color);
4582 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4583 s->width, h);
4584 XSetForeground (s->display, s->gc, xgcv.foreground);
4585 }
4586 }
4587
4588 /* Draw strike-through. */
4589 if (s->face->strike_through_p)
4590 {
4591 unsigned long h = 1;
4592 unsigned long dy = (s->height - h) / 2;
4593
4594 if (s->face->strike_through_color_defaulted_p)
4595 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4596 s->width, h);
4597 else
4598 {
4599 XGCValues xgcv;
4600 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4601 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4602 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4603 s->width, h);
4604 XSetForeground (s->display, s->gc, xgcv.foreground);
4605 }
4606 }
4607
4608 /* Draw relief if not yet drawn. */
4609 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4610 x_draw_glyph_string_box (s);
4611 }
4612
4613 /* Reset clipping. */
4614 XSetClipMask (s->display, s->gc, None);
4615 }
4616
4617
4618 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4619 struct face **, int));
4620
4621
4622 /* Fill glyph string S with composition components specified by S->cmp.
4623
4624 FACES is an array of faces for all components of this composition.
4625 S->gidx is the index of the first component for S.
4626 OVERLAPS_P non-zero means S should draw the foreground only, and
4627 use its physical height for clipping.
4628
4629 Value is the index of a component not in S. */
4630
4631 static int
4632 x_fill_composite_glyph_string (s, faces, overlaps_p)
4633 struct glyph_string *s;
4634 struct face **faces;
4635 int overlaps_p;
4636 {
4637 int i;
4638
4639 xassert (s);
4640
4641 s->for_overlaps_p = overlaps_p;
4642
4643 s->face = faces[s->gidx];
4644 s->font = s->face->font;
4645 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4646
4647 /* For all glyphs of this composition, starting at the offset
4648 S->gidx, until we reach the end of the definition or encounter a
4649 glyph that requires the different face, add it to S. */
4650 ++s->nchars;
4651 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4652 ++s->nchars;
4653
4654 /* All glyph strings for the same composition has the same width,
4655 i.e. the width set for the first component of the composition. */
4656
4657 s->width = s->first_glyph->pixel_width;
4658
4659 /* If the specified font could not be loaded, use the frame's
4660 default font, but record the fact that we couldn't load it in
4661 the glyph string so that we can draw rectangles for the
4662 characters of the glyph string. */
4663 if (s->font == NULL)
4664 {
4665 s->font_not_found_p = 1;
4666 s->font = FRAME_FONT (s->f);
4667 }
4668
4669 /* Adjust base line for subscript/superscript text. */
4670 s->ybase += s->first_glyph->voffset;
4671
4672 xassert (s->face && s->face->gc);
4673
4674 /* This glyph string must always be drawn with 16-bit functions. */
4675 s->two_byte_p = 1;
4676
4677 return s->gidx + s->nchars;
4678 }
4679
4680
4681 /* Fill glyph string S from a sequence of character glyphs.
4682
4683 FACE_ID is the face id of the string. START is the index of the
4684 first glyph to consider, END is the index of the last + 1.
4685 OVERLAPS_P non-zero means S should draw the foreground only, and
4686 use its physical height for clipping.
4687
4688 Value is the index of the first glyph not in S. */
4689
4690 static int
4691 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4692 struct glyph_string *s;
4693 int face_id;
4694 int start, end, overlaps_p;
4695 {
4696 struct glyph *glyph, *last;
4697 int voffset;
4698 int glyph_not_available_p;
4699
4700 xassert (s->f == XFRAME (s->w->frame));
4701 xassert (s->nchars == 0);
4702 xassert (start >= 0 && end > start);
4703
4704 s->for_overlaps_p = overlaps_p,
4705 glyph = s->row->glyphs[s->area] + start;
4706 last = s->row->glyphs[s->area] + end;
4707 voffset = glyph->voffset;
4708
4709 glyph_not_available_p = glyph->glyph_not_available_p;
4710
4711 while (glyph < last
4712 && glyph->type == CHAR_GLYPH
4713 && glyph->voffset == voffset
4714 /* Same face id implies same font, nowadays. */
4715 && glyph->face_id == face_id
4716 && glyph->glyph_not_available_p == glyph_not_available_p)
4717 {
4718 int two_byte_p;
4719
4720 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4721 s->char2b + s->nchars,
4722 &two_byte_p);
4723 s->two_byte_p = two_byte_p;
4724 ++s->nchars;
4725 xassert (s->nchars <= end - start);
4726 s->width += glyph->pixel_width;
4727 ++glyph;
4728 }
4729
4730 s->font = s->face->font;
4731 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4732
4733 /* If the specified font could not be loaded, use the frame's font,
4734 but record the fact that we couldn't load it in
4735 S->font_not_found_p so that we can draw rectangles for the
4736 characters of the glyph string. */
4737 if (s->font == NULL || glyph_not_available_p)
4738 {
4739 s->font_not_found_p = 1;
4740 s->font = FRAME_FONT (s->f);
4741 }
4742
4743 /* Adjust base line for subscript/superscript text. */
4744 s->ybase += voffset;
4745
4746 xassert (s->face && s->face->gc);
4747 return glyph - s->row->glyphs[s->area];
4748 }
4749
4750
4751 /* Fill glyph string S from image glyph S->first_glyph. */
4752
4753 static void
4754 x_fill_image_glyph_string (s)
4755 struct glyph_string *s;
4756 {
4757 xassert (s->first_glyph->type == IMAGE_GLYPH);
4758 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4759 xassert (s->img);
4760 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4761 s->font = s->face->font;
4762 s->width = s->first_glyph->pixel_width;
4763
4764 /* Adjust base line for subscript/superscript text. */
4765 s->ybase += s->first_glyph->voffset;
4766 }
4767
4768
4769 /* Fill glyph string S from a sequence of stretch glyphs.
4770
4771 ROW is the glyph row in which the glyphs are found, AREA is the
4772 area within the row. START is the index of the first glyph to
4773 consider, END is the index of the last + 1.
4774
4775 Value is the index of the first glyph not in S. */
4776
4777 static int
4778 x_fill_stretch_glyph_string (s, row, area, start, end)
4779 struct glyph_string *s;
4780 struct glyph_row *row;
4781 enum glyph_row_area area;
4782 int start, end;
4783 {
4784 struct glyph *glyph, *last;
4785 int voffset, face_id;
4786
4787 xassert (s->first_glyph->type == STRETCH_GLYPH);
4788
4789 glyph = s->row->glyphs[s->area] + start;
4790 last = s->row->glyphs[s->area] + end;
4791 face_id = glyph->face_id;
4792 s->face = FACE_FROM_ID (s->f, face_id);
4793 s->font = s->face->font;
4794 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4795 s->width = glyph->pixel_width;
4796 voffset = glyph->voffset;
4797
4798 for (++glyph;
4799 (glyph < last
4800 && glyph->type == STRETCH_GLYPH
4801 && glyph->voffset == voffset
4802 && glyph->face_id == face_id);
4803 ++glyph)
4804 s->width += glyph->pixel_width;
4805
4806 /* Adjust base line for subscript/superscript text. */
4807 s->ybase += voffset;
4808
4809 /* The case that face->gc == 0 is handled when drawing the glyph
4810 string by calling PREPARE_FACE_FOR_DISPLAY. */
4811 xassert (s->face);
4812 return glyph - s->row->glyphs[s->area];
4813 }
4814
4815
4816 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4817 of XChar2b structures for S; it can't be allocated in
4818 x_init_glyph_string because it must be allocated via `alloca'. W
4819 is the window on which S is drawn. ROW and AREA are the glyph row
4820 and area within the row from which S is constructed. START is the
4821 index of the first glyph structure covered by S. HL is a
4822 face-override for drawing S. */
4823
4824 static void
4825 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4826 struct glyph_string *s;
4827 XChar2b *char2b;
4828 struct window *w;
4829 struct glyph_row *row;
4830 enum glyph_row_area area;
4831 int start;
4832 enum draw_glyphs_face hl;
4833 {
4834 bzero (s, sizeof *s);
4835 s->w = w;
4836 s->f = XFRAME (w->frame);
4837 s->display = FRAME_X_DISPLAY (s->f);
4838 s->window = FRAME_X_WINDOW (s->f);
4839 s->char2b = char2b;
4840 s->hl = hl;
4841 s->row = row;
4842 s->area = area;
4843 s->first_glyph = row->glyphs[area] + start;
4844 s->height = row->height;
4845 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4846
4847 /* Display the internal border below the tool-bar window. */
4848 if (s->w == XWINDOW (s->f->tool_bar_window))
4849 s->y -= s->f->output_data.x->internal_border_width;
4850
4851 s->ybase = s->y + row->ascent;
4852 }
4853
4854
4855 /* Set background width of glyph string S. START is the index of the
4856 first glyph following S. LAST_X is the right-most x-position + 1
4857 in the drawing area. */
4858
4859 static INLINE void
4860 x_set_glyph_string_background_width (s, start, last_x)
4861 struct glyph_string *s;
4862 int start;
4863 int last_x;
4864 {
4865 /* If the face of this glyph string has to be drawn to the end of
4866 the drawing area, set S->extends_to_end_of_line_p. */
4867 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4868
4869 if (start == s->row->used[s->area]
4870 && s->area == TEXT_AREA
4871 && ((s->hl == DRAW_NORMAL_TEXT
4872 && (s->row->fill_line_p
4873 || s->face->background != default_face->background
4874 || s->face->stipple != default_face->stipple
4875 || s->row->mouse_face_p))
4876 || s->hl == DRAW_MOUSE_FACE
4877 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4878 && s->row->fill_line_p)))
4879 s->extends_to_end_of_line_p = 1;
4880
4881 /* If S extends its face to the end of the line, set its
4882 background_width to the distance to the right edge of the drawing
4883 area. */
4884 if (s->extends_to_end_of_line_p)
4885 s->background_width = last_x - s->x + 1;
4886 else
4887 s->background_width = s->width;
4888 }
4889
4890
4891 /* Add a glyph string for a stretch glyph to the list of strings
4892 between HEAD and TAIL. START is the index of the stretch glyph in
4893 row area AREA of glyph row ROW. END is the index of the last glyph
4894 in that glyph row area. X is the current output position assigned
4895 to the new glyph string constructed. HL overrides that face of the
4896 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4897 is the right-most x-position of the drawing area. */
4898
4899 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4900 and below -- keep them on one line. */
4901 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4902 do \
4903 { \
4904 s = (struct glyph_string *) alloca (sizeof *s); \
4905 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4906 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4907 x_append_glyph_string (&HEAD, &TAIL, s); \
4908 s->x = (X); \
4909 } \
4910 while (0)
4911
4912
4913 /* Add a glyph string for an image glyph to the list of strings
4914 between HEAD and TAIL. START is the index of the image glyph in
4915 row area AREA of glyph row ROW. END is the index of the last glyph
4916 in that glyph row area. X is the current output position assigned
4917 to the new glyph string constructed. HL overrides that face of the
4918 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4919 is the right-most x-position of the drawing area. */
4920
4921 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4922 do \
4923 { \
4924 s = (struct glyph_string *) alloca (sizeof *s); \
4925 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4926 x_fill_image_glyph_string (s); \
4927 x_append_glyph_string (&HEAD, &TAIL, s); \
4928 ++START; \
4929 s->x = (X); \
4930 } \
4931 while (0)
4932
4933
4934 /* Add a glyph string for a sequence of character glyphs to the list
4935 of strings between HEAD and TAIL. START is the index of the first
4936 glyph in row area AREA of glyph row ROW that is part of the new
4937 glyph string. END is the index of the last glyph in that glyph row
4938 area. X is the current output position assigned to the new glyph
4939 string constructed. HL overrides that face of the glyph; e.g. it
4940 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4941 right-most x-position of the drawing area. */
4942
4943 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4944 do \
4945 { \
4946 int c, face_id; \
4947 XChar2b *char2b; \
4948 \
4949 c = (ROW)->glyphs[AREA][START].u.ch; \
4950 face_id = (ROW)->glyphs[AREA][START].face_id; \
4951 \
4952 s = (struct glyph_string *) alloca (sizeof *s); \
4953 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4954 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4955 x_append_glyph_string (&HEAD, &TAIL, s); \
4956 s->x = (X); \
4957 START = x_fill_glyph_string (s, face_id, START, END, \
4958 OVERLAPS_P); \
4959 } \
4960 while (0)
4961
4962
4963 /* Add a glyph string for a composite sequence to the list of strings
4964 between HEAD and TAIL. START is the index of the first glyph in
4965 row area AREA of glyph row ROW that is part of the new glyph
4966 string. END is the index of the last glyph in that glyph row area.
4967 X is the current output position assigned to the new glyph string
4968 constructed. HL overrides that face of the glyph; e.g. it is
4969 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4970 x-position of the drawing area. */
4971
4972 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4973 do { \
4974 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4975 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4976 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4977 struct composition *cmp = composition_table[cmp_id]; \
4978 int glyph_len = cmp->glyph_len; \
4979 XChar2b *char2b; \
4980 struct face **faces; \
4981 struct glyph_string *first_s = NULL; \
4982 int n; \
4983 \
4984 base_face = base_face->ascii_face; \
4985 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4986 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4987 /* At first, fill in `char2b' and `faces'. */ \
4988 for (n = 0; n < glyph_len; n++) \
4989 { \
4990 int c = COMPOSITION_GLYPH (cmp, n); \
4991 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4992 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4993 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4994 this_face_id, char2b + n, 1, 1); \
4995 } \
4996 \
4997 /* Make glyph_strings for each glyph sequence that is drawable by \
4998 the same face, and append them to HEAD/TAIL. */ \
4999 for (n = 0; n < cmp->glyph_len;) \
5000 { \
5001 s = (struct glyph_string *) alloca (sizeof *s); \
5002 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5003 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5004 s->cmp = cmp; \
5005 s->gidx = n; \
5006 s->x = (X); \
5007 \
5008 if (n == 0) \
5009 first_s = s; \
5010 \
5011 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5012 } \
5013 \
5014 ++START; \
5015 s = first_s; \
5016 } while (0)
5017
5018
5019 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5020 of AREA of glyph row ROW on window W between indices START and END.
5021 HL overrides the face for drawing glyph strings, e.g. it is
5022 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5023 x-positions of the drawing area.
5024
5025 This is an ugly monster macro construct because we must use alloca
5026 to allocate glyph strings (because x_draw_glyphs can be called
5027 asynchronously). */
5028
5029 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5030 do \
5031 { \
5032 HEAD = TAIL = NULL; \
5033 while (START < END) \
5034 { \
5035 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5036 switch (first_glyph->type) \
5037 { \
5038 case CHAR_GLYPH: \
5039 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5040 TAIL, HL, X, LAST_X, \
5041 OVERLAPS_P); \
5042 break; \
5043 \
5044 case COMPOSITE_GLYPH: \
5045 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5046 HEAD, TAIL, HL, X, LAST_X,\
5047 OVERLAPS_P); \
5048 break; \
5049 \
5050 case STRETCH_GLYPH: \
5051 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5052 HEAD, TAIL, HL, X, LAST_X); \
5053 break; \
5054 \
5055 case IMAGE_GLYPH: \
5056 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5057 TAIL, HL, X, LAST_X); \
5058 break; \
5059 \
5060 default: \
5061 abort (); \
5062 } \
5063 \
5064 x_set_glyph_string_background_width (s, START, LAST_X); \
5065 (X) += s->width; \
5066 } \
5067 } \
5068 while (0)
5069
5070
5071 /* Draw glyphs between START and END in AREA of ROW on window W,
5072 starting at x-position X. X is relative to AREA in W. HL is a
5073 face-override with the following meaning:
5074
5075 DRAW_NORMAL_TEXT draw normally
5076 DRAW_CURSOR draw in cursor face
5077 DRAW_MOUSE_FACE draw in mouse face.
5078 DRAW_INVERSE_VIDEO draw in mode line face
5079 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5080 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5081
5082 If OVERLAPS_P is non-zero, draw only the foreground of characters
5083 and clip to the physical height of ROW.
5084
5085 Value is the x-position reached, relative to AREA of W. */
5086
5087 static int
5088 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5089 struct window *w;
5090 int x;
5091 struct glyph_row *row;
5092 enum glyph_row_area area;
5093 int start, end;
5094 enum draw_glyphs_face hl;
5095 int overlaps_p;
5096 {
5097 struct glyph_string *head, *tail;
5098 struct glyph_string *s;
5099 int last_x, area_width;
5100 int x_reached;
5101 int i, j;
5102
5103 /* Let's rather be paranoid than getting a SEGV. */
5104 end = min (end, row->used[area]);
5105 start = max (0, start);
5106 start = min (end, start);
5107
5108 /* Translate X to frame coordinates. Set last_x to the right
5109 end of the drawing area. */
5110 if (row->full_width_p)
5111 {
5112 /* X is relative to the left edge of W, without scroll bars
5113 or fringes. */
5114 struct frame *f = XFRAME (w->frame);
5115 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5116
5117 x += window_left_x;
5118 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5119 last_x = window_left_x + area_width;
5120
5121 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5122 {
5123 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5124 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5125 last_x += width;
5126 else
5127 x -= width;
5128 }
5129
5130 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5131 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
5132 }
5133 else
5134 {
5135 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5136 area_width = window_box_width (w, area);
5137 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5138 }
5139
5140 /* Build a doubly-linked list of glyph_string structures between
5141 head and tail from what we have to draw. Note that the macro
5142 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5143 the reason we use a separate variable `i'. */
5144 i = start;
5145 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5146 overlaps_p);
5147 if (tail)
5148 x_reached = tail->x + tail->background_width;
5149 else
5150 x_reached = x;
5151
5152 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5153 the row, redraw some glyphs in front or following the glyph
5154 strings built above. */
5155 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5156 {
5157 int dummy_x = 0;
5158 struct glyph_string *h, *t;
5159
5160 /* Compute overhangs for all glyph strings. */
5161 for (s = head; s; s = s->next)
5162 x_compute_glyph_string_overhangs (s);
5163
5164 /* Prepend glyph strings for glyphs in front of the first glyph
5165 string that are overwritten because of the first glyph
5166 string's left overhang. The background of all strings
5167 prepended must be drawn because the first glyph string
5168 draws over it. */
5169 i = x_left_overwritten (head);
5170 if (i >= 0)
5171 {
5172 j = i;
5173 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5174 DRAW_NORMAL_TEXT, dummy_x, last_x,
5175 overlaps_p);
5176 start = i;
5177 x_compute_overhangs_and_x (t, head->x, 1);
5178 x_prepend_glyph_string_lists (&head, &tail, h, t);
5179 }
5180
5181 /* Prepend glyph strings for glyphs in front of the first glyph
5182 string that overwrite that glyph string because of their
5183 right overhang. For these strings, only the foreground must
5184 be drawn, because it draws over the glyph string at `head'.
5185 The background must not be drawn because this would overwrite
5186 right overhangs of preceding glyphs for which no glyph
5187 strings exist. */
5188 i = x_left_overwriting (head);
5189 if (i >= 0)
5190 {
5191 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5192 DRAW_NORMAL_TEXT, dummy_x, last_x,
5193 overlaps_p);
5194 for (s = h; s; s = s->next)
5195 s->background_filled_p = 1;
5196 x_compute_overhangs_and_x (t, head->x, 1);
5197 x_prepend_glyph_string_lists (&head, &tail, h, t);
5198 }
5199
5200 /* Append glyphs strings for glyphs following the last glyph
5201 string tail that are overwritten by tail. The background of
5202 these strings has to be drawn because tail's foreground draws
5203 over it. */
5204 i = x_right_overwritten (tail);
5205 if (i >= 0)
5206 {
5207 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5208 DRAW_NORMAL_TEXT, x, last_x,
5209 overlaps_p);
5210 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5211 x_append_glyph_string_lists (&head, &tail, h, t);
5212 }
5213
5214 /* Append glyph strings for glyphs following the last glyph
5215 string tail that overwrite tail. The foreground of such
5216 glyphs has to be drawn because it writes into the background
5217 of tail. The background must not be drawn because it could
5218 paint over the foreground of following glyphs. */
5219 i = x_right_overwriting (tail);
5220 if (i >= 0)
5221 {
5222 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5223 DRAW_NORMAL_TEXT, x, last_x,
5224 overlaps_p);
5225 for (s = h; s; s = s->next)
5226 s->background_filled_p = 1;
5227 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5228 x_append_glyph_string_lists (&head, &tail, h, t);
5229 }
5230 }
5231
5232 /* Draw all strings. */
5233 for (s = head; s; s = s->next)
5234 x_draw_glyph_string (s);
5235
5236 if (area == TEXT_AREA
5237 && !row->full_width_p
5238 /* When drawing overlapping rows, only the glyph strings'
5239 foreground is drawn, which doesn't erase a cursor
5240 completely. */
5241 && !overlaps_p)
5242 {
5243 int x0 = head ? head->x : x;
5244 int x1 = tail ? tail->x + tail->background_width : x;
5245
5246 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5247 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5248
5249 if (XFASTINT (w->left_margin_width) != 0)
5250 {
5251 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5252 x0 -= left_area_width;
5253 x1 -= left_area_width;
5254 }
5255
5256 notice_overwritten_cursor (w, area, x0, x1,
5257 row->y, MATRIX_ROW_BOTTOM_Y (row));
5258 }
5259
5260 /* Value is the x-position up to which drawn, relative to AREA of W.
5261 This doesn't include parts drawn because of overhangs. */
5262 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5263 if (!row->full_width_p)
5264 {
5265 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
5266 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5267 if (area > TEXT_AREA)
5268 x_reached -= window_box_width (w, TEXT_AREA);
5269 }
5270
5271 return x_reached;
5272 }
5273
5274
5275 /* Fix the display of area AREA of overlapping row ROW in window W. */
5276
5277 static void
5278 x_fix_overlapping_area (w, row, area)
5279 struct window *w;
5280 struct glyph_row *row;
5281 enum glyph_row_area area;
5282 {
5283 int i, x;
5284
5285 BLOCK_INPUT;
5286
5287 if (area == LEFT_MARGIN_AREA)
5288 x = 0;
5289 else if (area == TEXT_AREA)
5290 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5291 else
5292 x = (window_box_width (w, LEFT_MARGIN_AREA)
5293 + window_box_width (w, TEXT_AREA));
5294
5295 for (i = 0; i < row->used[area];)
5296 {
5297 if (row->glyphs[area][i].overlaps_vertically_p)
5298 {
5299 int start = i, start_x = x;
5300
5301 do
5302 {
5303 x += row->glyphs[area][i].pixel_width;
5304 ++i;
5305 }
5306 while (i < row->used[area]
5307 && row->glyphs[area][i].overlaps_vertically_p);
5308
5309 x_draw_glyphs (w, start_x, row, area, start, i,
5310 DRAW_NORMAL_TEXT, 1);
5311 }
5312 else
5313 {
5314 x += row->glyphs[area][i].pixel_width;
5315 ++i;
5316 }
5317 }
5318
5319 UNBLOCK_INPUT;
5320 }
5321
5322
5323 /* Output LEN glyphs starting at START at the nominal cursor position.
5324 Advance the nominal cursor over the text. The global variable
5325 updated_window contains the window being updated, updated_row is
5326 the glyph row being updated, and updated_area is the area of that
5327 row being updated. */
5328
5329 static void
5330 x_write_glyphs (start, len)
5331 struct glyph *start;
5332 int len;
5333 {
5334 int x, hpos;
5335
5336 xassert (updated_window && updated_row);
5337 BLOCK_INPUT;
5338
5339 /* Write glyphs. */
5340
5341 hpos = start - updated_row->glyphs[updated_area];
5342 x = x_draw_glyphs (updated_window, output_cursor.x,
5343 updated_row, updated_area,
5344 hpos, hpos + len,
5345 DRAW_NORMAL_TEXT, 0);
5346
5347 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
5348 if (updated_area == TEXT_AREA
5349 && updated_window->phys_cursor_on_p
5350 && updated_window->phys_cursor.vpos == output_cursor.vpos
5351 && updated_window->phys_cursor.hpos >= hpos
5352 && updated_window->phys_cursor.hpos < hpos + len)
5353 updated_window->phys_cursor_on_p = 0;
5354
5355 UNBLOCK_INPUT;
5356
5357 /* Advance the output cursor. */
5358 output_cursor.hpos += len;
5359 output_cursor.x = x;
5360 }
5361
5362
5363 /* Insert LEN glyphs from START at the nominal cursor position. */
5364
5365 static void
5366 x_insert_glyphs (start, len)
5367 struct glyph *start;
5368 register int len;
5369 {
5370 struct frame *f;
5371 struct window *w;
5372 int line_height, shift_by_width, shifted_region_width;
5373 struct glyph_row *row;
5374 struct glyph *glyph;
5375 int frame_x, frame_y, hpos;
5376
5377 xassert (updated_window && updated_row);
5378 BLOCK_INPUT;
5379 w = updated_window;
5380 f = XFRAME (WINDOW_FRAME (w));
5381
5382 /* Get the height of the line we are in. */
5383 row = updated_row;
5384 line_height = row->height;
5385
5386 /* Get the width of the glyphs to insert. */
5387 shift_by_width = 0;
5388 for (glyph = start; glyph < start + len; ++glyph)
5389 shift_by_width += glyph->pixel_width;
5390
5391 /* Get the width of the region to shift right. */
5392 shifted_region_width = (window_box_width (w, updated_area)
5393 - output_cursor.x
5394 - shift_by_width);
5395
5396 /* Shift right. */
5397 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5398 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5399 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5400 f->output_data.x->normal_gc,
5401 frame_x, frame_y,
5402 shifted_region_width, line_height,
5403 frame_x + shift_by_width, frame_y);
5404
5405 /* Write the glyphs. */
5406 hpos = start - row->glyphs[updated_area];
5407 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5408 DRAW_NORMAL_TEXT, 0);
5409
5410 /* Advance the output cursor. */
5411 output_cursor.hpos += len;
5412 output_cursor.x += shift_by_width;
5413 UNBLOCK_INPUT;
5414 }
5415
5416
5417 /* Delete N glyphs at the nominal cursor position. Not implemented
5418 for X frames. */
5419
5420 static void
5421 x_delete_glyphs (n)
5422 register int n;
5423 {
5424 abort ();
5425 }
5426
5427
5428 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5429 If they are <= 0, this is probably an error. */
5430
5431 void
5432 x_clear_area (dpy, window, x, y, width, height, exposures)
5433 Display *dpy;
5434 Window window;
5435 int x, y;
5436 int width, height;
5437 int exposures;
5438 {
5439 xassert (width > 0 && height > 0);
5440 XClearArea (dpy, window, x, y, width, height, exposures);
5441 }
5442
5443
5444 /* Erase the current text line from the nominal cursor position
5445 (inclusive) to pixel column TO_X (exclusive). The idea is that
5446 everything from TO_X onward is already erased.
5447
5448 TO_X is a pixel position relative to updated_area of
5449 updated_window. TO_X == -1 means clear to the end of this area. */
5450
5451 static void
5452 x_clear_end_of_line (to_x)
5453 int to_x;
5454 {
5455 struct frame *f;
5456 struct window *w = updated_window;
5457 int max_x, min_y, max_y;
5458 int from_x, from_y, to_y;
5459
5460 xassert (updated_window && updated_row);
5461 f = XFRAME (w->frame);
5462
5463 if (updated_row->full_width_p)
5464 {
5465 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5466 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5467 && !w->pseudo_window_p)
5468 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5469 }
5470 else
5471 max_x = window_box_width (w, updated_area);
5472 max_y = window_text_bottom_y (w);
5473
5474 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5475 of window. For TO_X > 0, truncate to end of drawing area. */
5476 if (to_x == 0)
5477 return;
5478 else if (to_x < 0)
5479 to_x = max_x;
5480 else
5481 to_x = min (to_x, max_x);
5482
5483 to_y = min (max_y, output_cursor.y + updated_row->height);
5484
5485 /* Notice if the cursor will be cleared by this operation. */
5486 if (!updated_row->full_width_p)
5487 notice_overwritten_cursor (w, updated_area,
5488 output_cursor.x, -1,
5489 updated_row->y,
5490 MATRIX_ROW_BOTTOM_Y (updated_row));
5491
5492 from_x = output_cursor.x;
5493
5494 /* Translate to frame coordinates. */
5495 if (updated_row->full_width_p)
5496 {
5497 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5498 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5499 }
5500 else
5501 {
5502 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5503 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5504 }
5505
5506 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5507 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5508 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5509
5510 /* Prevent inadvertently clearing to end of the X window. */
5511 if (to_x > from_x && to_y > from_y)
5512 {
5513 BLOCK_INPUT;
5514 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5515 from_x, from_y, to_x - from_x, to_y - from_y,
5516 False);
5517 UNBLOCK_INPUT;
5518 }
5519 }
5520
5521
5522 /* Clear entire frame. If updating_frame is non-null, clear that
5523 frame. Otherwise clear the selected frame. */
5524
5525 static void
5526 x_clear_frame ()
5527 {
5528 struct frame *f;
5529
5530 if (updating_frame)
5531 f = updating_frame;
5532 else
5533 f = SELECTED_FRAME ();
5534
5535 /* Clearing the frame will erase any cursor, so mark them all as no
5536 longer visible. */
5537 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5538 output_cursor.hpos = output_cursor.vpos = 0;
5539 output_cursor.x = -1;
5540
5541 /* We don't set the output cursor here because there will always
5542 follow an explicit cursor_to. */
5543 BLOCK_INPUT;
5544 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5545
5546 /* We have to clear the scroll bars, too. If we have changed
5547 colors or something like that, then they should be notified. */
5548 x_scroll_bar_clear (f);
5549
5550 XFlush (FRAME_X_DISPLAY (f));
5551 UNBLOCK_INPUT;
5552 }
5553
5554
5555 \f
5556 /* Invert the middle quarter of the frame for .15 sec. */
5557
5558 /* We use the select system call to do the waiting, so we have to make
5559 sure it's available. If it isn't, we just won't do visual bells. */
5560
5561 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5562
5563
5564 /* Subtract the `struct timeval' values X and Y, storing the result in
5565 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5566
5567 static int
5568 timeval_subtract (result, x, y)
5569 struct timeval *result, x, y;
5570 {
5571 /* Perform the carry for the later subtraction by updating y. This
5572 is safer because on some systems the tv_sec member is unsigned. */
5573 if (x.tv_usec < y.tv_usec)
5574 {
5575 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5576 y.tv_usec -= 1000000 * nsec;
5577 y.tv_sec += nsec;
5578 }
5579
5580 if (x.tv_usec - y.tv_usec > 1000000)
5581 {
5582 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5583 y.tv_usec += 1000000 * nsec;
5584 y.tv_sec -= nsec;
5585 }
5586
5587 /* Compute the time remaining to wait. tv_usec is certainly
5588 positive. */
5589 result->tv_sec = x.tv_sec - y.tv_sec;
5590 result->tv_usec = x.tv_usec - y.tv_usec;
5591
5592 /* Return indication of whether the result should be considered
5593 negative. */
5594 return x.tv_sec < y.tv_sec;
5595 }
5596
5597 void
5598 XTflash (f)
5599 struct frame *f;
5600 {
5601 BLOCK_INPUT;
5602
5603 {
5604 GC gc;
5605
5606 /* Create a GC that will use the GXxor function to flip foreground
5607 pixels into background pixels. */
5608 {
5609 XGCValues values;
5610
5611 values.function = GXxor;
5612 values.foreground = (f->output_data.x->foreground_pixel
5613 ^ f->output_data.x->background_pixel);
5614
5615 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5616 GCFunction | GCForeground, &values);
5617 }
5618
5619 {
5620 /* Get the height not including a menu bar widget. */
5621 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5622 /* Height of each line to flash. */
5623 int flash_height = FRAME_LINE_HEIGHT (f);
5624 /* These will be the left and right margins of the rectangles. */
5625 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5626 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5627
5628 int width;
5629
5630 /* Don't flash the area between a scroll bar and the frame
5631 edge it is next to. */
5632 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5633 {
5634 case vertical_scroll_bar_left:
5635 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5636 break;
5637
5638 case vertical_scroll_bar_right:
5639 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5640 break;
5641
5642 default:
5643 break;
5644 }
5645
5646 width = flash_right - flash_left;
5647
5648 /* If window is tall, flash top and bottom line. */
5649 if (height > 3 * FRAME_LINE_HEIGHT (f))
5650 {
5651 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5652 flash_left,
5653 (FRAME_INTERNAL_BORDER_WIDTH (f)
5654 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5655 width, flash_height);
5656 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5657 flash_left,
5658 (height - flash_height
5659 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5660 width, flash_height);
5661 }
5662 else
5663 /* If it is short, flash it all. */
5664 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5665 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5666 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5667
5668 x_flush (f);
5669
5670 {
5671 struct timeval wakeup;
5672
5673 EMACS_GET_TIME (wakeup);
5674
5675 /* Compute time to wait until, propagating carry from usecs. */
5676 wakeup.tv_usec += 150000;
5677 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5678 wakeup.tv_usec %= 1000000;
5679
5680 /* Keep waiting until past the time wakeup or any input gets
5681 available. */
5682 while (! detect_input_pending ())
5683 {
5684 struct timeval current;
5685 struct timeval timeout;
5686
5687 EMACS_GET_TIME (current);
5688
5689 /* Break if result would be negative. */
5690 if (timeval_subtract (&current, wakeup, current))
5691 break;
5692
5693 /* How long `select' should wait. */
5694 timeout.tv_sec = 0;
5695 timeout.tv_usec = 10000;
5696
5697 /* Try to wait that long--but we might wake up sooner. */
5698 select (0, NULL, NULL, NULL, &timeout);
5699 }
5700 }
5701
5702 /* If window is tall, flash top and bottom line. */
5703 if (height > 3 * FRAME_LINE_HEIGHT (f))
5704 {
5705 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5706 flash_left,
5707 (FRAME_INTERNAL_BORDER_WIDTH (f)
5708 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5709 width, flash_height);
5710 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5711 flash_left,
5712 (height - flash_height
5713 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5714 width, flash_height);
5715 }
5716 else
5717 /* If it is short, flash it all. */
5718 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5719 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5720 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5721
5722 XFreeGC (FRAME_X_DISPLAY (f), gc);
5723 x_flush (f);
5724 }
5725 }
5726
5727 UNBLOCK_INPUT;
5728 }
5729
5730 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5731
5732
5733 /* Make audible bell. */
5734
5735 void
5736 XTring_bell ()
5737 {
5738 struct frame *f = SELECTED_FRAME ();
5739
5740 if (FRAME_X_DISPLAY (f))
5741 {
5742 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5743 if (visible_bell)
5744 XTflash (f);
5745 else
5746 #endif
5747 {
5748 BLOCK_INPUT;
5749 XBell (FRAME_X_DISPLAY (f), 0);
5750 XFlush (FRAME_X_DISPLAY (f));
5751 UNBLOCK_INPUT;
5752 }
5753 }
5754 }
5755
5756 \f
5757 /* Specify how many text lines, from the top of the window,
5758 should be affected by insert-lines and delete-lines operations.
5759 This, and those operations, are used only within an update
5760 that is bounded by calls to x_update_begin and x_update_end. */
5761
5762 static void
5763 XTset_terminal_window (n)
5764 register int n;
5765 {
5766 /* This function intentionally left blank. */
5767 }
5768
5769
5770 \f
5771 /***********************************************************************
5772 Line Dance
5773 ***********************************************************************/
5774
5775 /* Perform an insert-lines or delete-lines operation, inserting N
5776 lines or deleting -N lines at vertical position VPOS. */
5777
5778 static void
5779 x_ins_del_lines (vpos, n)
5780 int vpos, n;
5781 {
5782 abort ();
5783 }
5784
5785
5786 /* Scroll part of the display as described by RUN. */
5787
5788 static void
5789 x_scroll_run (w, run)
5790 struct window *w;
5791 struct run *run;
5792 {
5793 struct frame *f = XFRAME (w->frame);
5794 int x, y, width, height, from_y, to_y, bottom_y;
5795
5796 /* Get frame-relative bounding box of the text display area of W,
5797 without mode lines. Include in this box the left and right
5798 fringe of W. */
5799 window_box (w, -1, &x, &y, &width, &height);
5800 width += FRAME_X_FRINGE_WIDTH (f);
5801 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5802
5803 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5804 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5805 bottom_y = y + height;
5806
5807 if (to_y < from_y)
5808 {
5809 /* Scrolling up. Make sure we don't copy part of the mode
5810 line at the bottom. */
5811 if (from_y + run->height > bottom_y)
5812 height = bottom_y - from_y;
5813 else
5814 height = run->height;
5815 }
5816 else
5817 {
5818 /* Scolling down. Make sure we don't copy over the mode line.
5819 at the bottom. */
5820 if (to_y + run->height > bottom_y)
5821 height = bottom_y - to_y;
5822 else
5823 height = run->height;
5824 }
5825
5826 BLOCK_INPUT;
5827
5828 /* Cursor off. Will be switched on again in x_update_window_end. */
5829 updated_window = w;
5830 x_clear_cursor (w);
5831
5832 XCopyArea (FRAME_X_DISPLAY (f),
5833 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5834 f->output_data.x->normal_gc,
5835 x, from_y,
5836 width, height,
5837 x, to_y);
5838
5839 UNBLOCK_INPUT;
5840 }
5841
5842
5843 \f
5844 /***********************************************************************
5845 Exposure Events
5846 ***********************************************************************/
5847
5848 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5849 corner of the exposed rectangle. W and H are width and height of
5850 the exposed area. All are pixel values. W or H zero means redraw
5851 the entire frame. */
5852
5853 static void
5854 expose_frame (f, x, y, w, h)
5855 struct frame *f;
5856 int x, y, w, h;
5857 {
5858 XRectangle r;
5859 int mouse_face_overwritten_p = 0;
5860
5861 TRACE ((stderr, "expose_frame "));
5862
5863 /* No need to redraw if frame will be redrawn soon. */
5864 if (FRAME_GARBAGED_P (f))
5865 {
5866 TRACE ((stderr, " garbaged\n"));
5867 return;
5868 }
5869
5870 /* If basic faces haven't been realized yet, there is no point in
5871 trying to redraw anything. This can happen when we get an expose
5872 event while Emacs is starting, e.g. by moving another window. */
5873 if (FRAME_FACE_CACHE (f) == NULL
5874 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5875 {
5876 TRACE ((stderr, " no faces\n"));
5877 return;
5878 }
5879
5880 if (w == 0 || h == 0)
5881 {
5882 r.x = r.y = 0;
5883 r.width = CANON_X_UNIT (f) * f->width;
5884 r.height = CANON_Y_UNIT (f) * f->height;
5885 }
5886 else
5887 {
5888 r.x = x;
5889 r.y = y;
5890 r.width = w;
5891 r.height = h;
5892 }
5893
5894 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5895 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5896
5897 if (WINDOWP (f->tool_bar_window))
5898 mouse_face_overwritten_p
5899 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5900
5901 #ifndef USE_X_TOOLKIT
5902 if (WINDOWP (f->menu_bar_window))
5903 mouse_face_overwritten_p
5904 |= expose_window (XWINDOW (f->menu_bar_window), &r);
5905 #endif /* not USE_X_TOOLKIT */
5906
5907 /* Some window managers support a focus-follows-mouse style with
5908 delayed raising of frames. Imagine a partially obscured frame,
5909 and moving the mouse into partially obscured mouse-face on that
5910 frame. The visible part of the mouse-face will be highlighted,
5911 then the WM raises the obscured frame. With at least one WM, KDE
5912 2.1, Emacs is not getting any event for the raising of the frame
5913 (even tried with SubstructureRedirectMask), only Expose events.
5914 These expose events will draw text normally, i.e. not
5915 highlighted. Which means we must redo the highlight here.
5916 Subsume it under ``we love X''. --gerd 2001-08-15 */
5917 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5918 {
5919 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5920 if (f == dpyinfo->mouse_face_mouse_frame)
5921 {
5922 int x = dpyinfo->mouse_face_mouse_x;
5923 int y = dpyinfo->mouse_face_mouse_y;
5924 clear_mouse_face (dpyinfo);
5925 note_mouse_highlight (f, x, y);
5926 }
5927 }
5928 }
5929
5930
5931 /* Redraw (parts) of all windows in the window tree rooted at W that
5932 intersect R. R contains frame pixel coordinates. Value is
5933 non-zero if the exposure overwrites mouse-face. */
5934
5935 static int
5936 expose_window_tree (w, r)
5937 struct window *w;
5938 XRectangle *r;
5939 {
5940 struct frame *f = XFRAME (w->frame);
5941 int mouse_face_overwritten_p = 0;
5942
5943 while (w && !FRAME_GARBAGED_P (f))
5944 {
5945 if (!NILP (w->hchild))
5946 mouse_face_overwritten_p
5947 |= expose_window_tree (XWINDOW (w->hchild), r);
5948 else if (!NILP (w->vchild))
5949 mouse_face_overwritten_p
5950 |= expose_window_tree (XWINDOW (w->vchild), r);
5951 else
5952 mouse_face_overwritten_p |= expose_window (w, r);
5953
5954 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5955 }
5956
5957 return mouse_face_overwritten_p;
5958 }
5959
5960
5961 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5962 which intersects rectangle R. R is in window-relative coordinates. */
5963
5964 static void
5965 expose_area (w, row, r, area)
5966 struct window *w;
5967 struct glyph_row *row;
5968 XRectangle *r;
5969 enum glyph_row_area area;
5970 {
5971 struct glyph *first = row->glyphs[area];
5972 struct glyph *end = row->glyphs[area] + row->used[area];
5973 struct glyph *last;
5974 int first_x, start_x, x;
5975
5976 if (area == TEXT_AREA && row->fill_line_p)
5977 /* If row extends face to end of line write the whole line. */
5978 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
5979 DRAW_NORMAL_TEXT, 0);
5980 else
5981 {
5982 /* Set START_X to the window-relative start position for drawing glyphs of
5983 AREA. The first glyph of the text area can be partially visible.
5984 The first glyphs of other areas cannot. */
5985 if (area == LEFT_MARGIN_AREA)
5986 start_x = 0;
5987 else if (area == TEXT_AREA)
5988 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5989 else
5990 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5991 + window_box_width (w, TEXT_AREA));
5992 x = start_x;
5993
5994 /* Find the first glyph that must be redrawn. */
5995 while (first < end
5996 && x + first->pixel_width < r->x)
5997 {
5998 x += first->pixel_width;
5999 ++first;
6000 }
6001
6002 /* Find the last one. */
6003 last = first;
6004 first_x = x;
6005 while (last < end
6006 && x < r->x + r->width)
6007 {
6008 x += last->pixel_width;
6009 ++last;
6010 }
6011
6012 /* Repaint. */
6013 if (last > first)
6014 x_draw_glyphs (w, first_x - start_x, row, area,
6015 first - row->glyphs[area],
6016 last - row->glyphs[area],
6017 DRAW_NORMAL_TEXT, 0);
6018 }
6019 }
6020
6021
6022 /* Redraw the parts of the glyph row ROW on window W intersecting
6023 rectangle R. R is in window-relative coordinates. Value is
6024 non-zero if mouse-face was overwritten. */
6025
6026 static int
6027 expose_line (w, row, r)
6028 struct window *w;
6029 struct glyph_row *row;
6030 XRectangle *r;
6031 {
6032 xassert (row->enabled_p);
6033
6034 if (row->mode_line_p || w->pseudo_window_p)
6035 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6036 DRAW_NORMAL_TEXT, 0);
6037 else
6038 {
6039 if (row->used[LEFT_MARGIN_AREA])
6040 expose_area (w, row, r, LEFT_MARGIN_AREA);
6041 if (row->used[TEXT_AREA])
6042 expose_area (w, row, r, TEXT_AREA);
6043 if (row->used[RIGHT_MARGIN_AREA])
6044 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6045 x_draw_row_fringe_bitmaps (w, row);
6046 }
6047
6048 return row->mouse_face_p;
6049 }
6050
6051
6052 /* Return non-zero if W's cursor intersects rectangle R. */
6053
6054 static int
6055 x_phys_cursor_in_rect_p (w, r)
6056 struct window *w;
6057 XRectangle *r;
6058 {
6059 XRectangle cr, result;
6060 struct glyph *cursor_glyph;
6061
6062 cursor_glyph = get_phys_cursor_glyph (w);
6063 if (cursor_glyph)
6064 {
6065 cr.x = w->phys_cursor.x;
6066 cr.y = w->phys_cursor.y;
6067 cr.width = cursor_glyph->pixel_width;
6068 cr.height = w->phys_cursor_height;
6069 return x_intersect_rectangles (&cr, r, &result);
6070 }
6071 else
6072 return 0;
6073 }
6074
6075
6076 /* Redraw those parts of glyphs rows during expose event handling that
6077 overlap other rows. Redrawing of an exposed line writes over parts
6078 of lines overlapping that exposed line; this function fixes that.
6079
6080 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6081 row in W's current matrix that is exposed and overlaps other rows.
6082 LAST_OVERLAPPING_ROW is the last such row. */
6083
6084 static void
6085 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6086 struct window *w;
6087 struct glyph_row *first_overlapping_row;
6088 struct glyph_row *last_overlapping_row;
6089 {
6090 struct glyph_row *row;
6091
6092 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
6093 if (row->overlapping_p)
6094 {
6095 xassert (row->enabled_p && !row->mode_line_p);
6096
6097 if (row->used[LEFT_MARGIN_AREA])
6098 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
6099
6100 if (row->used[TEXT_AREA])
6101 x_fix_overlapping_area (w, row, TEXT_AREA);
6102
6103 if (row->used[RIGHT_MARGIN_AREA])
6104 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
6105 }
6106 }
6107
6108
6109 /* Redraw the part of window W intersection rectangle FR. Pixel
6110 coordinates in FR are frame-relative. Call this function with
6111 input blocked. Value is non-zero if the exposure overwrites
6112 mouse-face. */
6113
6114 static int
6115 expose_window (w, fr)
6116 struct window *w;
6117 XRectangle *fr;
6118 {
6119 struct frame *f = XFRAME (w->frame);
6120 XRectangle wr, r;
6121 int mouse_face_overwritten_p = 0;
6122
6123 /* If window is not yet fully initialized, do nothing. This can
6124 happen when toolkit scroll bars are used and a window is split.
6125 Reconfiguring the scroll bar will generate an expose for a newly
6126 created window. */
6127 if (w->current_matrix == NULL)
6128 return 0;
6129
6130 /* When we're currently updating the window, display and current
6131 matrix usually don't agree. Arrange for a thorough display
6132 later. */
6133 if (w == updated_window)
6134 {
6135 SET_FRAME_GARBAGED (f);
6136 return 0;
6137 }
6138
6139 /* Frame-relative pixel rectangle of W. */
6140 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6141 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6142 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6143 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6144
6145 if (x_intersect_rectangles (fr, &wr, &r))
6146 {
6147 int yb = window_text_bottom_y (w);
6148 struct glyph_row *row;
6149 int cursor_cleared_p;
6150 struct glyph_row *first_overlapping_row, *last_overlapping_row;
6151
6152 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6153 r.x, r.y, r.width, r.height));
6154
6155 /* Convert to window coordinates. */
6156 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6157 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6158
6159 /* Turn off the cursor. */
6160 if (!w->pseudo_window_p
6161 && x_phys_cursor_in_rect_p (w, &r))
6162 {
6163 x_clear_cursor (w);
6164 cursor_cleared_p = 1;
6165 }
6166 else
6167 cursor_cleared_p = 0;
6168
6169 /* Update lines intersecting rectangle R. */
6170 first_overlapping_row = last_overlapping_row = NULL;
6171 for (row = w->current_matrix->rows;
6172 row->enabled_p;
6173 ++row)
6174 {
6175 int y0 = row->y;
6176 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6177
6178 if ((y0 >= r.y && y0 < r.y + r.height)
6179 || (y1 > r.y && y1 < r.y + r.height)
6180 || (r.y >= y0 && r.y < y1)
6181 || (r.y + r.height > y0 && r.y + r.height < y1))
6182 {
6183 if (row->overlapping_p)
6184 {
6185 if (first_overlapping_row == NULL)
6186 first_overlapping_row = row;
6187 last_overlapping_row = row;
6188 }
6189
6190 if (expose_line (w, row, &r))
6191 mouse_face_overwritten_p = 1;
6192 }
6193
6194 if (y1 >= yb)
6195 break;
6196 }
6197
6198 /* Display the mode line if there is one. */
6199 if (WINDOW_WANTS_MODELINE_P (w)
6200 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6201 row->enabled_p)
6202 && row->y < r.y + r.height)
6203 {
6204 if (expose_line (w, row, &r))
6205 mouse_face_overwritten_p = 1;
6206 }
6207
6208 if (!w->pseudo_window_p)
6209 {
6210 /* Fix the display of overlapping rows. */
6211 if (first_overlapping_row)
6212 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
6213
6214 /* Draw border between windows. */
6215 x_draw_vertical_border (w);
6216
6217 /* Turn the cursor on again. */
6218 if (cursor_cleared_p)
6219 x_update_window_cursor (w, 1);
6220 }
6221 }
6222
6223 return mouse_face_overwritten_p;
6224 }
6225
6226
6227 /* Determine the intersection of two rectangles R1 and R2. Return
6228 the intersection in *RESULT. Value is non-zero if RESULT is not
6229 empty. */
6230
6231 static int
6232 x_intersect_rectangles (r1, r2, result)
6233 XRectangle *r1, *r2, *result;
6234 {
6235 XRectangle *left, *right;
6236 XRectangle *upper, *lower;
6237 int intersection_p = 0;
6238
6239 /* Rearrange so that R1 is the left-most rectangle. */
6240 if (r1->x < r2->x)
6241 left = r1, right = r2;
6242 else
6243 left = r2, right = r1;
6244
6245 /* X0 of the intersection is right.x0, if this is inside R1,
6246 otherwise there is no intersection. */
6247 if (right->x <= left->x + left->width)
6248 {
6249 result->x = right->x;
6250
6251 /* The right end of the intersection is the minimum of the
6252 the right ends of left and right. */
6253 result->width = (min (left->x + left->width, right->x + right->width)
6254 - result->x);
6255
6256 /* Same game for Y. */
6257 if (r1->y < r2->y)
6258 upper = r1, lower = r2;
6259 else
6260 upper = r2, lower = r1;
6261
6262 /* The upper end of the intersection is lower.y0, if this is inside
6263 of upper. Otherwise, there is no intersection. */
6264 if (lower->y <= upper->y + upper->height)
6265 {
6266 result->y = lower->y;
6267
6268 /* The lower end of the intersection is the minimum of the lower
6269 ends of upper and lower. */
6270 result->height = (min (lower->y + lower->height,
6271 upper->y + upper->height)
6272 - result->y);
6273 intersection_p = 1;
6274 }
6275 }
6276
6277 return intersection_p;
6278 }
6279
6280
6281
6282
6283 \f
6284 static void
6285 frame_highlight (f)
6286 struct frame *f;
6287 {
6288 /* We used to only do this if Vx_no_window_manager was non-nil, but
6289 the ICCCM (section 4.1.6) says that the window's border pixmap
6290 and border pixel are window attributes which are "private to the
6291 client", so we can always change it to whatever we want. */
6292 BLOCK_INPUT;
6293 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6294 f->output_data.x->border_pixel);
6295 UNBLOCK_INPUT;
6296 x_update_cursor (f, 1);
6297 }
6298
6299 static void
6300 frame_unhighlight (f)
6301 struct frame *f;
6302 {
6303 /* We used to only do this if Vx_no_window_manager was non-nil, but
6304 the ICCCM (section 4.1.6) says that the window's border pixmap
6305 and border pixel are window attributes which are "private to the
6306 client", so we can always change it to whatever we want. */
6307 BLOCK_INPUT;
6308 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6309 f->output_data.x->border_tile);
6310 UNBLOCK_INPUT;
6311 x_update_cursor (f, 1);
6312 }
6313
6314 /* The focus has changed. Update the frames as necessary to reflect
6315 the new situation. Note that we can't change the selected frame
6316 here, because the Lisp code we are interrupting might become confused.
6317 Each event gets marked with the frame in which it occurred, so the
6318 Lisp code can tell when the switch took place by examining the events. */
6319
6320 static void
6321 x_new_focus_frame (dpyinfo, frame)
6322 struct x_display_info *dpyinfo;
6323 struct frame *frame;
6324 {
6325 struct frame *old_focus = dpyinfo->x_focus_frame;
6326
6327 if (frame != dpyinfo->x_focus_frame)
6328 {
6329 /* Set this before calling other routines, so that they see
6330 the correct value of x_focus_frame. */
6331 dpyinfo->x_focus_frame = frame;
6332
6333 if (old_focus && old_focus->auto_lower)
6334 x_lower_frame (old_focus);
6335
6336 #if 0
6337 selected_frame = frame;
6338 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6339 selected_frame);
6340 Fselect_window (selected_frame->selected_window);
6341 choose_minibuf_frame ();
6342 #endif /* ! 0 */
6343
6344 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6345 pending_autoraise_frame = dpyinfo->x_focus_frame;
6346 else
6347 pending_autoraise_frame = 0;
6348 }
6349
6350 x_frame_rehighlight (dpyinfo);
6351 }
6352
6353 /* Handle FocusIn and FocusOut state changes for FRAME.
6354 If FRAME has focus and there exists more than one frame, puts
6355 a FOCUS_IN_EVENT into BUFP.
6356 Returns number of events inserted into BUFP. */
6357
6358 static int
6359 x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
6360 int type;
6361 int state;
6362 struct x_display_info *dpyinfo;
6363 struct frame *frame;
6364 struct input_event *bufp;
6365 int numchars;
6366 {
6367 int nr_events = 0;
6368
6369 if (type == FocusIn)
6370 {
6371 if (dpyinfo->x_focus_event_frame != frame)
6372 {
6373 x_new_focus_frame (dpyinfo, frame);
6374 dpyinfo->x_focus_event_frame = frame;
6375
6376 /* Don't stop displaying the initial startup message
6377 for a switch-frame event we don't need. */
6378 if (numchars > 0
6379 && GC_NILP (Vterminal_frame)
6380 && GC_CONSP (Vframe_list)
6381 && !GC_NILP (XCDR (Vframe_list)))
6382 {
6383 bufp->kind = FOCUS_IN_EVENT;
6384 XSETFRAME (bufp->frame_or_window, frame);
6385 bufp->arg = Qnil;
6386 ++bufp;
6387 numchars--;
6388 ++nr_events;
6389 }
6390 }
6391
6392 frame->output_data.x->focus_state |= state;
6393
6394 #ifdef HAVE_X_I18N
6395 if (FRAME_XIC (frame))
6396 XSetICFocus (FRAME_XIC (frame));
6397 #endif
6398 }
6399 else if (type == FocusOut)
6400 {
6401 frame->output_data.x->focus_state &= ~state;
6402
6403 if (dpyinfo->x_focus_event_frame == frame)
6404 {
6405 dpyinfo->x_focus_event_frame = 0;
6406 x_new_focus_frame (dpyinfo, 0);
6407 }
6408
6409 #ifdef HAVE_X_I18N
6410 if (FRAME_XIC (frame))
6411 XUnsetICFocus (FRAME_XIC (frame));
6412 #endif
6413 }
6414
6415 return nr_events;
6416 }
6417
6418 /* The focus may have changed. Figure out if it is a real focus change,
6419 by checking both FocusIn/Out and Enter/LeaveNotify events.
6420
6421 Returns number of events inserted into BUFP. */
6422
6423 static int
6424 x_detect_focus_change (dpyinfo, event, bufp, numchars)
6425 struct x_display_info *dpyinfo;
6426 XEvent *event;
6427 struct input_event *bufp;
6428 int numchars;
6429 {
6430 struct frame *frame;
6431 int nr_events = 0;
6432
6433 frame = x_top_window_to_frame (dpyinfo, event->xany.window);
6434 if (! frame) return nr_events;
6435
6436 switch (event->type)
6437 {
6438 case EnterNotify:
6439 case LeaveNotify:
6440 if (event->xcrossing.detail != NotifyInferior
6441 && event->xcrossing.focus
6442 && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
6443 nr_events = x_focus_changed ((event->type == EnterNotify
6444 ? FocusIn : FocusOut),
6445 FOCUS_IMPLICIT,
6446 dpyinfo,
6447 frame,
6448 bufp,
6449 numchars);
6450 break;
6451
6452 case FocusIn:
6453 case FocusOut:
6454 nr_events = x_focus_changed (event->type,
6455 (event->xfocus.detail == NotifyPointer
6456 ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
6457 dpyinfo,
6458 frame,
6459 bufp,
6460 numchars);
6461 break;
6462 }
6463
6464 return nr_events;
6465 }
6466
6467
6468 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6469
6470 void
6471 x_mouse_leave (dpyinfo)
6472 struct x_display_info *dpyinfo;
6473 {
6474 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6475 }
6476
6477 /* The focus has changed, or we have redirected a frame's focus to
6478 another frame (this happens when a frame uses a surrogate
6479 mini-buffer frame). Shift the highlight as appropriate.
6480
6481 The FRAME argument doesn't necessarily have anything to do with which
6482 frame is being highlighted or un-highlighted; we only use it to find
6483 the appropriate X display info. */
6484
6485 static void
6486 XTframe_rehighlight (frame)
6487 struct frame *frame;
6488 {
6489 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6490 }
6491
6492 static void
6493 x_frame_rehighlight (dpyinfo)
6494 struct x_display_info *dpyinfo;
6495 {
6496 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6497
6498 if (dpyinfo->x_focus_frame)
6499 {
6500 dpyinfo->x_highlight_frame
6501 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6502 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6503 : dpyinfo->x_focus_frame);
6504 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6505 {
6506 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6507 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6508 }
6509 }
6510 else
6511 dpyinfo->x_highlight_frame = 0;
6512
6513 if (dpyinfo->x_highlight_frame != old_highlight)
6514 {
6515 if (old_highlight)
6516 frame_unhighlight (old_highlight);
6517 if (dpyinfo->x_highlight_frame)
6518 frame_highlight (dpyinfo->x_highlight_frame);
6519 }
6520 }
6521
6522
6523 \f
6524 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6525
6526 /* Initialize mode_switch_bit and modifier_meaning. */
6527 static void
6528 x_find_modifier_meanings (dpyinfo)
6529 struct x_display_info *dpyinfo;
6530 {
6531 int min_code, max_code;
6532 KeySym *syms;
6533 int syms_per_code;
6534 XModifierKeymap *mods;
6535
6536 dpyinfo->meta_mod_mask = 0;
6537 dpyinfo->shift_lock_mask = 0;
6538 dpyinfo->alt_mod_mask = 0;
6539 dpyinfo->super_mod_mask = 0;
6540 dpyinfo->hyper_mod_mask = 0;
6541
6542 #ifdef HAVE_X11R4
6543 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6544 #else
6545 min_code = dpyinfo->display->min_keycode;
6546 max_code = dpyinfo->display->max_keycode;
6547 #endif
6548
6549 syms = XGetKeyboardMapping (dpyinfo->display,
6550 min_code, max_code - min_code + 1,
6551 &syms_per_code);
6552 mods = XGetModifierMapping (dpyinfo->display);
6553
6554 /* Scan the modifier table to see which modifier bits the Meta and
6555 Alt keysyms are on. */
6556 {
6557 int row, col; /* The row and column in the modifier table. */
6558
6559 for (row = 3; row < 8; row++)
6560 for (col = 0; col < mods->max_keypermod; col++)
6561 {
6562 KeyCode code
6563 = mods->modifiermap[(row * mods->max_keypermod) + col];
6564
6565 /* Zeroes are used for filler. Skip them. */
6566 if (code == 0)
6567 continue;
6568
6569 /* Are any of this keycode's keysyms a meta key? */
6570 {
6571 int code_col;
6572
6573 for (code_col = 0; code_col < syms_per_code; code_col++)
6574 {
6575 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6576
6577 switch (sym)
6578 {
6579 case XK_Meta_L:
6580 case XK_Meta_R:
6581 dpyinfo->meta_mod_mask |= (1 << row);
6582 break;
6583
6584 case XK_Alt_L:
6585 case XK_Alt_R:
6586 dpyinfo->alt_mod_mask |= (1 << row);
6587 break;
6588
6589 case XK_Hyper_L:
6590 case XK_Hyper_R:
6591 dpyinfo->hyper_mod_mask |= (1 << row);
6592 break;
6593
6594 case XK_Super_L:
6595 case XK_Super_R:
6596 dpyinfo->super_mod_mask |= (1 << row);
6597 break;
6598
6599 case XK_Shift_Lock:
6600 /* Ignore this if it's not on the lock modifier. */
6601 if ((1 << row) == LockMask)
6602 dpyinfo->shift_lock_mask = LockMask;
6603 break;
6604 }
6605 }
6606 }
6607 }
6608 }
6609
6610 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6611 if (! dpyinfo->meta_mod_mask)
6612 {
6613 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6614 dpyinfo->alt_mod_mask = 0;
6615 }
6616
6617 /* If some keys are both alt and meta,
6618 make them just meta, not alt. */
6619 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6620 {
6621 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6622 }
6623
6624 XFree ((char *) syms);
6625 XFreeModifiermap (mods);
6626 }
6627
6628 /* Convert between the modifier bits X uses and the modifier bits
6629 Emacs uses. */
6630
6631 static unsigned int
6632 x_x_to_emacs_modifiers (dpyinfo, state)
6633 struct x_display_info *dpyinfo;
6634 unsigned int state;
6635 {
6636 EMACS_UINT mod_meta = meta_modifier;
6637 EMACS_UINT mod_alt = alt_modifier;
6638 EMACS_UINT mod_hyper = hyper_modifier;
6639 EMACS_UINT mod_super = super_modifier;
6640 Lisp_Object tem;
6641
6642 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6643 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6644 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6645 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6646 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6647 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6648 tem = Fget (Vx_super_keysym, Qmodifier_value);
6649 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6650
6651
6652 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6653 | ((state & ControlMask) ? ctrl_modifier : 0)
6654 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
6655 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
6656 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
6657 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
6658 }
6659
6660 static unsigned int
6661 x_emacs_to_x_modifiers (dpyinfo, state)
6662 struct x_display_info *dpyinfo;
6663 unsigned int state;
6664 {
6665 EMACS_UINT mod_meta = meta_modifier;
6666 EMACS_UINT mod_alt = alt_modifier;
6667 EMACS_UINT mod_hyper = hyper_modifier;
6668 EMACS_UINT mod_super = super_modifier;
6669
6670 Lisp_Object tem;
6671
6672 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6673 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6674 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6675 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6676 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6677 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6678 tem = Fget (Vx_super_keysym, Qmodifier_value);
6679 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6680
6681
6682 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
6683 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
6684 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
6685 | ((state & shift_modifier) ? ShiftMask : 0)
6686 | ((state & ctrl_modifier) ? ControlMask : 0)
6687 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
6688 }
6689
6690 /* Convert a keysym to its name. */
6691
6692 char *
6693 x_get_keysym_name (keysym)
6694 KeySym keysym;
6695 {
6696 char *value;
6697
6698 BLOCK_INPUT;
6699 value = XKeysymToString (keysym);
6700 UNBLOCK_INPUT;
6701
6702 return value;
6703 }
6704
6705
6706 \f
6707 /* Mouse clicks and mouse movement. Rah. */
6708
6709 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6710 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6711 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6712 not force the value into range. */
6713
6714 void
6715 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6716 FRAME_PTR f;
6717 register int pix_x, pix_y;
6718 register int *x, *y;
6719 XRectangle *bounds;
6720 int noclip;
6721 {
6722 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6723 even for negative values. */
6724 if (pix_x < 0)
6725 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6726 if (pix_y < 0)
6727 pix_y -= (f)->output_data.x->line_height - 1;
6728
6729 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6730 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6731
6732 if (bounds)
6733 {
6734 bounds->width = FONT_WIDTH (f->output_data.x->font);
6735 bounds->height = f->output_data.x->line_height;
6736 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6737 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6738 }
6739
6740 if (!noclip)
6741 {
6742 if (pix_x < 0)
6743 pix_x = 0;
6744 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6745 pix_x = FRAME_WINDOW_WIDTH (f);
6746
6747 if (pix_y < 0)
6748 pix_y = 0;
6749 else if (pix_y > f->height)
6750 pix_y = f->height;
6751 }
6752
6753 *x = pix_x;
6754 *y = pix_y;
6755 }
6756
6757
6758 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6759 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6760 can't tell the positions because W's display is not up to date,
6761 return 0. */
6762
6763 int
6764 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6765 struct window *w;
6766 int hpos, vpos;
6767 int *frame_x, *frame_y;
6768 {
6769 int success_p;
6770
6771 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6772 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6773
6774 if (display_completed)
6775 {
6776 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6777 struct glyph *glyph = row->glyphs[TEXT_AREA];
6778 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6779
6780 *frame_y = row->y;
6781 *frame_x = row->x;
6782 while (glyph < end)
6783 {
6784 *frame_x += glyph->pixel_width;
6785 ++glyph;
6786 }
6787
6788 success_p = 1;
6789 }
6790 else
6791 {
6792 *frame_y = *frame_x = 0;
6793 success_p = 0;
6794 }
6795
6796 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6797 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6798 return success_p;
6799 }
6800
6801
6802 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6803
6804 If the event is a button press, then note that we have grabbed
6805 the mouse. */
6806
6807 static Lisp_Object
6808 construct_mouse_click (result, event, f)
6809 struct input_event *result;
6810 XButtonEvent *event;
6811 struct frame *f;
6812 {
6813 /* Make the event type NO_EVENT; we'll change that when we decide
6814 otherwise. */
6815 result->kind = MOUSE_CLICK_EVENT;
6816 result->code = event->button - Button1;
6817 result->timestamp = event->time;
6818 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6819 event->state)
6820 | (event->type == ButtonRelease
6821 ? up_modifier
6822 : down_modifier));
6823
6824 XSETINT (result->x, event->x);
6825 XSETINT (result->y, event->y);
6826 XSETFRAME (result->frame_or_window, f);
6827 result->arg = Qnil;
6828 return Qnil;
6829 }
6830
6831 \f
6832 /* Function to report a mouse movement to the mainstream Emacs code.
6833 The input handler calls this.
6834
6835 We have received a mouse movement event, which is given in *event.
6836 If the mouse is over a different glyph than it was last time, tell
6837 the mainstream emacs code by setting mouse_moved. If not, ask for
6838 another motion event, so we can check again the next time it moves. */
6839
6840 static XMotionEvent last_mouse_motion_event;
6841 static Lisp_Object last_mouse_motion_frame;
6842
6843 static void
6844 note_mouse_movement (frame, event)
6845 FRAME_PTR frame;
6846 XMotionEvent *event;
6847 {
6848 last_mouse_movement_time = event->time;
6849 last_mouse_motion_event = *event;
6850 XSETFRAME (last_mouse_motion_frame, frame);
6851
6852 if (event->window != FRAME_X_WINDOW (frame))
6853 {
6854 frame->mouse_moved = 1;
6855 last_mouse_scroll_bar = Qnil;
6856 note_mouse_highlight (frame, -1, -1);
6857 }
6858
6859 /* Has the mouse moved off the glyph it was on at the last sighting? */
6860 else if (event->x < last_mouse_glyph.x
6861 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6862 || event->y < last_mouse_glyph.y
6863 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6864 {
6865 frame->mouse_moved = 1;
6866 last_mouse_scroll_bar = Qnil;
6867 note_mouse_highlight (frame, event->x, event->y);
6868 }
6869 }
6870
6871 \f
6872 /************************************************************************
6873 Mouse Face
6874 ************************************************************************/
6875
6876 /* Find the glyph under window-relative coordinates X/Y in window W.
6877 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6878 strings. Return in *HPOS and *VPOS the row and column number of
6879 the glyph found. Return in *AREA the glyph area containing X.
6880 Value is a pointer to the glyph found or null if X/Y is not on
6881 text, or we can't tell because W's current matrix is not up to
6882 date. */
6883
6884 static struct glyph *
6885 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6886 struct window *w;
6887 int x, y;
6888 int *hpos, *vpos, *area;
6889 int buffer_only_p;
6890 {
6891 struct glyph *glyph, *end;
6892 struct glyph_row *row = NULL;
6893 int x0, i, left_area_width;
6894
6895 /* Find row containing Y. Give up if some row is not enabled. */
6896 for (i = 0; i < w->current_matrix->nrows; ++i)
6897 {
6898 row = MATRIX_ROW (w->current_matrix, i);
6899 if (!row->enabled_p)
6900 return NULL;
6901 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6902 break;
6903 }
6904
6905 *vpos = i;
6906 *hpos = 0;
6907
6908 /* Give up if Y is not in the window. */
6909 if (i == w->current_matrix->nrows)
6910 return NULL;
6911
6912 /* Get the glyph area containing X. */
6913 if (w->pseudo_window_p)
6914 {
6915 *area = TEXT_AREA;
6916 x0 = 0;
6917 }
6918 else
6919 {
6920 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6921 if (x < left_area_width)
6922 {
6923 *area = LEFT_MARGIN_AREA;
6924 x0 = 0;
6925 }
6926 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6927 {
6928 *area = TEXT_AREA;
6929 x0 = row->x + left_area_width;
6930 }
6931 else
6932 {
6933 *area = RIGHT_MARGIN_AREA;
6934 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6935 }
6936 }
6937
6938 /* Find glyph containing X. */
6939 glyph = row->glyphs[*area];
6940 end = glyph + row->used[*area];
6941 while (glyph < end)
6942 {
6943 if (x < x0 + glyph->pixel_width)
6944 {
6945 if (w->pseudo_window_p)
6946 break;
6947 else if (!buffer_only_p || BUFFERP (glyph->object))
6948 break;
6949 }
6950
6951 x0 += glyph->pixel_width;
6952 ++glyph;
6953 }
6954
6955 if (glyph == end)
6956 return NULL;
6957
6958 *hpos = glyph - row->glyphs[*area];
6959 return glyph;
6960 }
6961
6962
6963 /* Convert frame-relative x/y to coordinates relative to window W.
6964 Takes pseudo-windows into account. */
6965
6966 static void
6967 frame_to_window_pixel_xy (w, x, y)
6968 struct window *w;
6969 int *x, *y;
6970 {
6971 if (w->pseudo_window_p)
6972 {
6973 /* A pseudo-window is always full-width, and starts at the
6974 left edge of the frame, plus a frame border. */
6975 struct frame *f = XFRAME (w->frame);
6976 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6977 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6978 }
6979 else
6980 {
6981 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6982 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6983 }
6984 }
6985
6986
6987 /* Take proper action when mouse has moved to the mode or header line
6988 or marginal area of window W, x-position X and y-position Y. Area
6989 is 1, 3, 6 or 7 for the mode line, header line, left and right
6990 marginal area respectively. X is relative to the start of the text
6991 display area of W, so the width of bitmap areas and scroll bars
6992 must be subtracted to get a position relative to the start of the
6993 mode line. */
6994
6995 static void
6996 note_mode_line_or_margin_highlight (w, x, y, portion)
6997 struct window *w;
6998 int x, y, portion;
6999 {
7000 struct frame *f = XFRAME (w->frame);
7001 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7002 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
7003 int charpos;
7004 Lisp_Object string, help, map, pos;
7005
7006 if (portion == 1 || portion == 3)
7007 string = mode_line_string (w, x, y, portion == 1, &charpos);
7008 else
7009 string = marginal_area_string (w, x, y, portion, &charpos);
7010
7011 if (STRINGP (string))
7012 {
7013 pos = make_number (charpos);
7014
7015 /* If we're on a string with `help-echo' text property, arrange
7016 for the help to be displayed. This is done by setting the
7017 global variable help_echo to the help string. */
7018 help = Fget_text_property (pos, Qhelp_echo, string);
7019 if (!NILP (help))
7020 {
7021 help_echo = help;
7022 XSETWINDOW (help_echo_window, w);
7023 help_echo_object = string;
7024 help_echo_pos = charpos;
7025 }
7026
7027 /* Change the mouse pointer according to what is under X/Y. */
7028 map = Fget_text_property (pos, Qlocal_map, string);
7029 if (!KEYMAPP (map))
7030 map = Fget_text_property (pos, Qkeymap, string);
7031 if (KEYMAPP (map))
7032 cursor = f->output_data.x->nontext_cursor;
7033 }
7034
7035 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7036 }
7037
7038
7039 /* Take proper action when the mouse has moved to position X, Y on
7040 frame F as regards highlighting characters that have mouse-face
7041 properties. Also de-highlighting chars where the mouse was before.
7042 X and Y can be negative or out of range. */
7043
7044 static void
7045 note_mouse_highlight (f, x, y)
7046 struct frame *f;
7047 int x, y;
7048 {
7049 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7050 int portion;
7051 Lisp_Object window;
7052 struct window *w;
7053 Cursor cursor = None;
7054 struct buffer *b;
7055
7056 /* When a menu is active, don't highlight because this looks odd. */
7057 #ifdef USE_X_TOOLKIT
7058 if (popup_activated ())
7059 return;
7060 #endif
7061
7062 if (NILP (Vmouse_highlight)
7063 || !f->glyphs_initialized_p)
7064 return;
7065
7066 dpyinfo->mouse_face_mouse_x = x;
7067 dpyinfo->mouse_face_mouse_y = y;
7068 dpyinfo->mouse_face_mouse_frame = f;
7069
7070 if (dpyinfo->mouse_face_defer)
7071 return;
7072
7073 if (gc_in_progress)
7074 {
7075 dpyinfo->mouse_face_deferred_gc = 1;
7076 return;
7077 }
7078
7079 /* Which window is that in? */
7080 window = window_from_coordinates (f, x, y, &portion, 1);
7081
7082 /* If we were displaying active text in another window, clear that. */
7083 if (! EQ (window, dpyinfo->mouse_face_window))
7084 clear_mouse_face (dpyinfo);
7085
7086 /* Not on a window -> return. */
7087 if (!WINDOWP (window))
7088 return;
7089
7090 /* Convert to window-relative pixel coordinates. */
7091 w = XWINDOW (window);
7092 frame_to_window_pixel_xy (w, &x, &y);
7093
7094 /* Handle tool-bar window differently since it doesn't display a
7095 buffer. */
7096 if (EQ (window, f->tool_bar_window))
7097 {
7098 note_tool_bar_highlight (f, x, y);
7099 return;
7100 }
7101
7102 /* Mouse is on the mode, header line or margin? */
7103 if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
7104 {
7105 note_mode_line_or_margin_highlight (w, x, y, portion);
7106 return;
7107 }
7108
7109 if (portion == 2)
7110 cursor = f->output_data.x->horizontal_drag_cursor;
7111 else
7112 cursor = f->output_data.x->text_cursor;
7113
7114 /* Are we in a window whose display is up to date?
7115 And verify the buffer's text has not changed. */
7116 b = XBUFFER (w->buffer);
7117 if (/* Within text portion of the window. */
7118 portion == 0
7119 && EQ (w->window_end_valid, w->buffer)
7120 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7121 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7122 {
7123 int hpos, vpos, pos, i, area;
7124 struct glyph *glyph;
7125 Lisp_Object object;
7126 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7127 Lisp_Object *overlay_vec = NULL;
7128 int len, noverlays;
7129 struct buffer *obuf;
7130 int obegv, ozv, same_region;
7131
7132 /* Find the glyph under X/Y. */
7133 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7134
7135 /* Clear mouse face if X/Y not over text. */
7136 if (glyph == NULL
7137 || area != TEXT_AREA
7138 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7139 {
7140 if (clear_mouse_face (dpyinfo))
7141 cursor = None;
7142 goto set_cursor;
7143 }
7144
7145 pos = glyph->charpos;
7146 object = glyph->object;
7147 if (!STRINGP (object) && !BUFFERP (object))
7148 goto set_cursor;
7149
7150 /* If we get an out-of-range value, return now; avoid an error. */
7151 if (BUFFERP (object) && pos > BUF_Z (b))
7152 goto set_cursor;
7153
7154 /* Make the window's buffer temporarily current for
7155 overlays_at and compute_char_face. */
7156 obuf = current_buffer;
7157 current_buffer = b;
7158 obegv = BEGV;
7159 ozv = ZV;
7160 BEGV = BEG;
7161 ZV = Z;
7162
7163 /* Is this char mouse-active or does it have help-echo? */
7164 position = make_number (pos);
7165
7166 if (BUFFERP (object))
7167 {
7168 /* Put all the overlays we want in a vector in overlay_vec.
7169 Store the length in len. If there are more than 10, make
7170 enough space for all, and try again. */
7171 len = 10;
7172 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7173 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7174 if (noverlays > len)
7175 {
7176 len = noverlays;
7177 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7178 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7179 }
7180
7181 /* Sort overlays into increasing priority order. */
7182 noverlays = sort_overlays (overlay_vec, noverlays, w);
7183 }
7184 else
7185 noverlays = 0;
7186
7187 same_region = (EQ (window, dpyinfo->mouse_face_window)
7188 && vpos >= dpyinfo->mouse_face_beg_row
7189 && vpos <= dpyinfo->mouse_face_end_row
7190 && (vpos > dpyinfo->mouse_face_beg_row
7191 || hpos >= dpyinfo->mouse_face_beg_col)
7192 && (vpos < dpyinfo->mouse_face_end_row
7193 || hpos < dpyinfo->mouse_face_end_col
7194 || dpyinfo->mouse_face_past_end));
7195
7196 if (same_region)
7197 cursor = None;
7198
7199 /* Check mouse-face highlighting. */
7200 if (! same_region
7201 /* If there exists an overlay with mouse-face overlapping
7202 the one we are currently highlighting, we have to
7203 check if we enter the overlapping overlay, and then
7204 highlight only that. */
7205 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7206 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7207 {
7208 /* Find the highest priority overlay that has a mouse-face
7209 property. */
7210 overlay = Qnil;
7211 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7212 {
7213 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7214 if (!NILP (mouse_face))
7215 overlay = overlay_vec[i];
7216 }
7217
7218 /* If we're actually highlighting the same overlay as
7219 before, there's no need to do that again. */
7220 if (!NILP (overlay)
7221 && EQ (overlay, dpyinfo->mouse_face_overlay))
7222 goto check_help_echo;
7223
7224 dpyinfo->mouse_face_overlay = overlay;
7225
7226 /* Clear the display of the old active region, if any. */
7227 if (clear_mouse_face (dpyinfo))
7228 cursor = None;
7229
7230 /* If no overlay applies, get a text property. */
7231 if (NILP (overlay))
7232 mouse_face = Fget_text_property (position, Qmouse_face, object);
7233
7234 /* Handle the overlay case. */
7235 if (!NILP (overlay))
7236 {
7237 /* Find the range of text around this char that
7238 should be active. */
7239 Lisp_Object before, after;
7240 int ignore;
7241
7242 before = Foverlay_start (overlay);
7243 after = Foverlay_end (overlay);
7244 /* Record this as the current active region. */
7245 fast_find_position (w, XFASTINT (before),
7246 &dpyinfo->mouse_face_beg_col,
7247 &dpyinfo->mouse_face_beg_row,
7248 &dpyinfo->mouse_face_beg_x,
7249 &dpyinfo->mouse_face_beg_y, Qnil);
7250
7251 dpyinfo->mouse_face_past_end
7252 = !fast_find_position (w, XFASTINT (after),
7253 &dpyinfo->mouse_face_end_col,
7254 &dpyinfo->mouse_face_end_row,
7255 &dpyinfo->mouse_face_end_x,
7256 &dpyinfo->mouse_face_end_y, Qnil);
7257 dpyinfo->mouse_face_window = window;
7258 dpyinfo->mouse_face_face_id
7259 = face_at_buffer_position (w, pos, 0, 0,
7260 &ignore, pos + 1,
7261 !dpyinfo->mouse_face_hidden);
7262
7263 /* Display it as active. */
7264 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7265 cursor = None;
7266 }
7267 /* Handle the text property case. */
7268 else if (!NILP (mouse_face) && BUFFERP (object))
7269 {
7270 /* Find the range of text around this char that
7271 should be active. */
7272 Lisp_Object before, after, beginning, end;
7273 int ignore;
7274
7275 beginning = Fmarker_position (w->start);
7276 end = make_number (BUF_Z (XBUFFER (object))
7277 - XFASTINT (w->window_end_pos));
7278 before
7279 = Fprevious_single_property_change (make_number (pos + 1),
7280 Qmouse_face,
7281 object, beginning);
7282 after
7283 = Fnext_single_property_change (position, Qmouse_face,
7284 object, end);
7285
7286 /* Record this as the current active region. */
7287 fast_find_position (w, XFASTINT (before),
7288 &dpyinfo->mouse_face_beg_col,
7289 &dpyinfo->mouse_face_beg_row,
7290 &dpyinfo->mouse_face_beg_x,
7291 &dpyinfo->mouse_face_beg_y, Qnil);
7292 dpyinfo->mouse_face_past_end
7293 = !fast_find_position (w, XFASTINT (after),
7294 &dpyinfo->mouse_face_end_col,
7295 &dpyinfo->mouse_face_end_row,
7296 &dpyinfo->mouse_face_end_x,
7297 &dpyinfo->mouse_face_end_y, Qnil);
7298 dpyinfo->mouse_face_window = window;
7299
7300 if (BUFFERP (object))
7301 dpyinfo->mouse_face_face_id
7302 = face_at_buffer_position (w, pos, 0, 0,
7303 &ignore, pos + 1,
7304 !dpyinfo->mouse_face_hidden);
7305
7306 /* Display it as active. */
7307 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7308 cursor = None;
7309 }
7310 else if (!NILP (mouse_face) && STRINGP (object))
7311 {
7312 Lisp_Object b, e;
7313 int ignore;
7314
7315 b = Fprevious_single_property_change (make_number (pos + 1),
7316 Qmouse_face,
7317 object, Qnil);
7318 e = Fnext_single_property_change (position, Qmouse_face,
7319 object, Qnil);
7320 if (NILP (b))
7321 b = make_number (0);
7322 if (NILP (e))
7323 e = make_number (SCHARS (object) - 1);
7324 fast_find_string_pos (w, XINT (b), object,
7325 &dpyinfo->mouse_face_beg_col,
7326 &dpyinfo->mouse_face_beg_row,
7327 &dpyinfo->mouse_face_beg_x,
7328 &dpyinfo->mouse_face_beg_y, 0);
7329 fast_find_string_pos (w, XINT (e), object,
7330 &dpyinfo->mouse_face_end_col,
7331 &dpyinfo->mouse_face_end_row,
7332 &dpyinfo->mouse_face_end_x,
7333 &dpyinfo->mouse_face_end_y, 1);
7334 dpyinfo->mouse_face_past_end = 0;
7335 dpyinfo->mouse_face_window = window;
7336 dpyinfo->mouse_face_face_id
7337 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7338 glyph->face_id, 1);
7339 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7340 cursor = None;
7341 }
7342 else if (STRINGP (object) && NILP (mouse_face))
7343 {
7344 /* A string which doesn't have mouse-face, but
7345 the text ``under'' it might have. */
7346 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7347 int start = MATRIX_ROW_START_CHARPOS (r);
7348
7349 pos = string_buffer_position (w, object, start);
7350 if (pos > 0)
7351 mouse_face = get_char_property_and_overlay (make_number (pos),
7352 Qmouse_face,
7353 w->buffer,
7354 &overlay);
7355 if (!NILP (mouse_face) && !NILP (overlay))
7356 {
7357 Lisp_Object before = Foverlay_start (overlay);
7358 Lisp_Object after = Foverlay_end (overlay);
7359 int ignore;
7360
7361 /* Note that we might not be able to find position
7362 BEFORE in the glyph matrix if the overlay is
7363 entirely covered by a `display' property. In
7364 this case, we overshoot. So let's stop in
7365 the glyph matrix before glyphs for OBJECT. */
7366 fast_find_position (w, XFASTINT (before),
7367 &dpyinfo->mouse_face_beg_col,
7368 &dpyinfo->mouse_face_beg_row,
7369 &dpyinfo->mouse_face_beg_x,
7370 &dpyinfo->mouse_face_beg_y,
7371 object);
7372
7373 dpyinfo->mouse_face_past_end
7374 = !fast_find_position (w, XFASTINT (after),
7375 &dpyinfo->mouse_face_end_col,
7376 &dpyinfo->mouse_face_end_row,
7377 &dpyinfo->mouse_face_end_x,
7378 &dpyinfo->mouse_face_end_y,
7379 Qnil);
7380 dpyinfo->mouse_face_window = window;
7381 dpyinfo->mouse_face_face_id
7382 = face_at_buffer_position (w, pos, 0, 0,
7383 &ignore, pos + 1,
7384 !dpyinfo->mouse_face_hidden);
7385
7386 /* Display it as active. */
7387 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7388 cursor = None;
7389 }
7390 }
7391 }
7392
7393 check_help_echo:
7394
7395 /* Look for a `help-echo' property. */
7396 {
7397 Lisp_Object help, overlay;
7398
7399 /* Check overlays first. */
7400 help = overlay = Qnil;
7401 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7402 {
7403 overlay = overlay_vec[i];
7404 help = Foverlay_get (overlay, Qhelp_echo);
7405 }
7406
7407 if (!NILP (help))
7408 {
7409 help_echo = help;
7410 help_echo_window = window;
7411 help_echo_object = overlay;
7412 help_echo_pos = pos;
7413 }
7414 else
7415 {
7416 Lisp_Object object = glyph->object;
7417 int charpos = glyph->charpos;
7418
7419 /* Try text properties. */
7420 if (STRINGP (object)
7421 && charpos >= 0
7422 && charpos < SCHARS (object))
7423 {
7424 help = Fget_text_property (make_number (charpos),
7425 Qhelp_echo, object);
7426 if (NILP (help))
7427 {
7428 /* If the string itself doesn't specify a help-echo,
7429 see if the buffer text ``under'' it does. */
7430 struct glyph_row *r
7431 = MATRIX_ROW (w->current_matrix, vpos);
7432 int start = MATRIX_ROW_START_CHARPOS (r);
7433 int pos = string_buffer_position (w, object, start);
7434 if (pos > 0)
7435 {
7436 help = Fget_char_property (make_number (pos),
7437 Qhelp_echo, w->buffer);
7438 if (!NILP (help))
7439 {
7440 charpos = pos;
7441 object = w->buffer;
7442 }
7443 }
7444 }
7445 }
7446 else if (BUFFERP (object)
7447 && charpos >= BEGV
7448 && charpos < ZV)
7449 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7450 object);
7451
7452 if (!NILP (help))
7453 {
7454 help_echo = help;
7455 help_echo_window = window;
7456 help_echo_object = object;
7457 help_echo_pos = charpos;
7458 }
7459 }
7460 }
7461
7462 BEGV = obegv;
7463 ZV = ozv;
7464 current_buffer = obuf;
7465 }
7466
7467 set_cursor:
7468
7469 if (cursor != None)
7470 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7471 }
7472
7473 static void
7474 redo_mouse_highlight ()
7475 {
7476 if (!NILP (last_mouse_motion_frame)
7477 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7478 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7479 last_mouse_motion_event.x,
7480 last_mouse_motion_event.y);
7481 }
7482
7483
7484 \f
7485 /***********************************************************************
7486 Tool-bars
7487 ***********************************************************************/
7488
7489 static int x_tool_bar_item P_ ((struct frame *, int, int,
7490 struct glyph **, int *, int *, int *));
7491
7492 /* Tool-bar item index of the item on which a mouse button was pressed
7493 or -1. */
7494
7495 static int last_tool_bar_item;
7496
7497
7498 /* Get information about the tool-bar item at position X/Y on frame F.
7499 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7500 the current matrix of the tool-bar window of F, or NULL if not
7501 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7502 item in F->tool_bar_items. Value is
7503
7504 -1 if X/Y is not on a tool-bar item
7505 0 if X/Y is on the same item that was highlighted before.
7506 1 otherwise. */
7507
7508 static int
7509 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7510 struct frame *f;
7511 int x, y;
7512 struct glyph **glyph;
7513 int *hpos, *vpos, *prop_idx;
7514 {
7515 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7516 struct window *w = XWINDOW (f->tool_bar_window);
7517 int area;
7518
7519 /* Find the glyph under X/Y. */
7520 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7521 if (*glyph == NULL)
7522 return -1;
7523
7524 /* Get the start of this tool-bar item's properties in
7525 f->tool_bar_items. */
7526 if (!tool_bar_item_info (f, *glyph, prop_idx))
7527 return -1;
7528
7529 /* Is mouse on the highlighted item? */
7530 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7531 && *vpos >= dpyinfo->mouse_face_beg_row
7532 && *vpos <= dpyinfo->mouse_face_end_row
7533 && (*vpos > dpyinfo->mouse_face_beg_row
7534 || *hpos >= dpyinfo->mouse_face_beg_col)
7535 && (*vpos < dpyinfo->mouse_face_end_row
7536 || *hpos < dpyinfo->mouse_face_end_col
7537 || dpyinfo->mouse_face_past_end))
7538 return 0;
7539
7540 return 1;
7541 }
7542
7543
7544 /* Handle mouse button event on the tool-bar of frame F, at
7545 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7546 or ButtonRelase. */
7547
7548 static void
7549 x_handle_tool_bar_click (f, button_event)
7550 struct frame *f;
7551 XButtonEvent *button_event;
7552 {
7553 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7554 struct window *w = XWINDOW (f->tool_bar_window);
7555 int hpos, vpos, prop_idx;
7556 struct glyph *glyph;
7557 Lisp_Object enabled_p;
7558 int x = button_event->x;
7559 int y = button_event->y;
7560
7561 /* If not on the highlighted tool-bar item, return. */
7562 frame_to_window_pixel_xy (w, &x, &y);
7563 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7564 return;
7565
7566 /* If item is disabled, do nothing. */
7567 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7568 if (NILP (enabled_p))
7569 return;
7570
7571 if (button_event->type == ButtonPress)
7572 {
7573 /* Show item in pressed state. */
7574 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7575 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7576 last_tool_bar_item = prop_idx;
7577 }
7578 else
7579 {
7580 Lisp_Object key, frame;
7581 struct input_event event;
7582
7583 /* Show item in released state. */
7584 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7585 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7586
7587 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7588
7589 XSETFRAME (frame, f);
7590 event.kind = TOOL_BAR_EVENT;
7591 event.frame_or_window = frame;
7592 event.arg = frame;
7593 kbd_buffer_store_event (&event);
7594
7595 event.kind = TOOL_BAR_EVENT;
7596 event.frame_or_window = frame;
7597 event.arg = key;
7598 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7599 button_event->state);
7600 kbd_buffer_store_event (&event);
7601 last_tool_bar_item = -1;
7602 }
7603 }
7604
7605
7606 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7607 tool-bar window-relative coordinates X/Y. Called from
7608 note_mouse_highlight. */
7609
7610 static void
7611 note_tool_bar_highlight (f, x, y)
7612 struct frame *f;
7613 int x, y;
7614 {
7615 Lisp_Object window = f->tool_bar_window;
7616 struct window *w = XWINDOW (window);
7617 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7618 int hpos, vpos;
7619 struct glyph *glyph;
7620 struct glyph_row *row;
7621 int i;
7622 Lisp_Object enabled_p;
7623 int prop_idx;
7624 enum draw_glyphs_face draw;
7625 int mouse_down_p, rc;
7626
7627 /* Function note_mouse_highlight is called with negative x(y
7628 values when mouse moves outside of the frame. */
7629 if (x <= 0 || y <= 0)
7630 {
7631 clear_mouse_face (dpyinfo);
7632 return;
7633 }
7634
7635 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7636 if (rc < 0)
7637 {
7638 /* Not on tool-bar item. */
7639 clear_mouse_face (dpyinfo);
7640 return;
7641 }
7642 else if (rc == 0)
7643 goto set_help_echo;
7644
7645 clear_mouse_face (dpyinfo);
7646
7647 /* Mouse is down, but on different tool-bar item? */
7648 mouse_down_p = (dpyinfo->grabbed
7649 && f == last_mouse_frame
7650 && FRAME_LIVE_P (f));
7651 if (mouse_down_p
7652 && last_tool_bar_item != prop_idx)
7653 return;
7654
7655 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7656 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7657
7658 /* If tool-bar item is not enabled, don't highlight it. */
7659 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7660 if (!NILP (enabled_p))
7661 {
7662 /* Compute the x-position of the glyph. In front and past the
7663 image is a space. We include this is the highlighted area. */
7664 row = MATRIX_ROW (w->current_matrix, vpos);
7665 for (i = x = 0; i < hpos; ++i)
7666 x += row->glyphs[TEXT_AREA][i].pixel_width;
7667
7668 /* Record this as the current active region. */
7669 dpyinfo->mouse_face_beg_col = hpos;
7670 dpyinfo->mouse_face_beg_row = vpos;
7671 dpyinfo->mouse_face_beg_x = x;
7672 dpyinfo->mouse_face_beg_y = row->y;
7673 dpyinfo->mouse_face_past_end = 0;
7674
7675 dpyinfo->mouse_face_end_col = hpos + 1;
7676 dpyinfo->mouse_face_end_row = vpos;
7677 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7678 dpyinfo->mouse_face_end_y = row->y;
7679 dpyinfo->mouse_face_window = window;
7680 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7681
7682 /* Display it as active. */
7683 show_mouse_face (dpyinfo, draw);
7684 dpyinfo->mouse_face_image_state = draw;
7685 }
7686
7687 set_help_echo:
7688
7689 /* Set help_echo to a help string to display for this tool-bar item.
7690 XTread_socket does the rest. */
7691 help_echo_object = help_echo_window = Qnil;
7692 help_echo_pos = -1;
7693 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7694 if (NILP (help_echo))
7695 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7696 }
7697
7698
7699 \f
7700 /* Find the glyph matrix position of buffer position CHARPOS in window
7701 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7702 current glyphs must be up to date. If CHARPOS is above window
7703 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7704 of last line in W. In the row containing CHARPOS, stop before glyphs
7705 having STOP as object. */
7706
7707 #if 0 /* This is a version of fast_find_position that's more correct
7708 in the presence of hscrolling, for example. I didn't install
7709 it right away because the problem fixed is minor, it failed
7710 in 20.x as well, and I think it's too risky to install
7711 so near the release of 21.1. 2001-09-25 gerd. */
7712
7713 static int
7714 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7715 struct window *w;
7716 int charpos;
7717 int *hpos, *vpos, *x, *y;
7718 Lisp_Object stop;
7719 {
7720 struct glyph_row *row, *first;
7721 struct glyph *glyph, *end;
7722 int i, past_end = 0;
7723
7724 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7725 row = row_containing_pos (w, charpos, first, NULL, 0);
7726 if (row == NULL)
7727 {
7728 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7729 {
7730 *x = *y = *hpos = *vpos = 0;
7731 return 0;
7732 }
7733 else
7734 {
7735 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7736 past_end = 1;
7737 }
7738 }
7739
7740 *x = row->x;
7741 *y = row->y;
7742 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7743
7744 glyph = row->glyphs[TEXT_AREA];
7745 end = glyph + row->used[TEXT_AREA];
7746
7747 /* Skip over glyphs not having an object at the start of the row.
7748 These are special glyphs like truncation marks on terminal
7749 frames. */
7750 if (row->displays_text_p)
7751 while (glyph < end
7752 && INTEGERP (glyph->object)
7753 && !EQ (stop, glyph->object)
7754 && glyph->charpos < 0)
7755 {
7756 *x += glyph->pixel_width;
7757 ++glyph;
7758 }
7759
7760 while (glyph < end
7761 && !INTEGERP (glyph->object)
7762 && !EQ (stop, glyph->object)
7763 && (!BUFFERP (glyph->object)
7764 || glyph->charpos < charpos))
7765 {
7766 *x += glyph->pixel_width;
7767 ++glyph;
7768 }
7769
7770 *hpos = glyph - row->glyphs[TEXT_AREA];
7771 return past_end;
7772 }
7773
7774 #else /* not 0 */
7775
7776 static int
7777 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7778 struct window *w;
7779 int pos;
7780 int *hpos, *vpos, *x, *y;
7781 Lisp_Object stop;
7782 {
7783 int i;
7784 int lastcol;
7785 int maybe_next_line_p = 0;
7786 int line_start_position;
7787 int yb = window_text_bottom_y (w);
7788 struct glyph_row *row, *best_row;
7789 int row_vpos, best_row_vpos;
7790 int current_x;
7791
7792 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7793 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7794
7795 while (row->y < yb)
7796 {
7797 if (row->used[TEXT_AREA])
7798 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7799 else
7800 line_start_position = 0;
7801
7802 if (line_start_position > pos)
7803 break;
7804 /* If the position sought is the end of the buffer,
7805 don't include the blank lines at the bottom of the window. */
7806 else if (line_start_position == pos
7807 && pos == BUF_ZV (XBUFFER (w->buffer)))
7808 {
7809 maybe_next_line_p = 1;
7810 break;
7811 }
7812 else if (line_start_position > 0)
7813 {
7814 best_row = row;
7815 best_row_vpos = row_vpos;
7816 }
7817
7818 if (row->y + row->height >= yb)
7819 break;
7820
7821 ++row;
7822 ++row_vpos;
7823 }
7824
7825 /* Find the right column within BEST_ROW. */
7826 lastcol = 0;
7827 current_x = best_row->x;
7828 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7829 {
7830 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7831 int charpos = glyph->charpos;
7832
7833 if (BUFFERP (glyph->object))
7834 {
7835 if (charpos == pos)
7836 {
7837 *hpos = i;
7838 *vpos = best_row_vpos;
7839 *x = current_x;
7840 *y = best_row->y;
7841 return 1;
7842 }
7843 else if (charpos > pos)
7844 break;
7845 }
7846 else if (EQ (glyph->object, stop))
7847 break;
7848
7849 if (charpos > 0)
7850 lastcol = i;
7851 current_x += glyph->pixel_width;
7852 }
7853
7854 /* If we're looking for the end of the buffer,
7855 and we didn't find it in the line we scanned,
7856 use the start of the following line. */
7857 if (maybe_next_line_p)
7858 {
7859 ++best_row;
7860 ++best_row_vpos;
7861 lastcol = 0;
7862 current_x = best_row->x;
7863 }
7864
7865 *vpos = best_row_vpos;
7866 *hpos = lastcol + 1;
7867 *x = current_x;
7868 *y = best_row->y;
7869 return 0;
7870 }
7871
7872 #endif /* not 0 */
7873
7874
7875 /* Find the position of the glyph for position POS in OBJECT in
7876 window W's current matrix, and return in *X, *Y the pixel
7877 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
7878
7879 RIGHT_P non-zero means return the position of the right edge of the
7880 glyph, RIGHT_P zero means return the left edge position.
7881
7882 If no glyph for POS exists in the matrix, return the position of
7883 the glyph with the next smaller position that is in the matrix, if
7884 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7885 exists in the matrix, return the position of the glyph with the
7886 next larger position in OBJECT.
7887
7888 Value is non-zero if a glyph was found. */
7889
7890 static int
7891 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7892 struct window *w;
7893 int pos;
7894 Lisp_Object object;
7895 int *hpos, *vpos, *x, *y;
7896 int right_p;
7897 {
7898 int yb = window_text_bottom_y (w);
7899 struct glyph_row *r;
7900 struct glyph *best_glyph = NULL;
7901 struct glyph_row *best_row = NULL;
7902 int best_x = 0;
7903
7904 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7905 r->enabled_p && r->y < yb;
7906 ++r)
7907 {
7908 struct glyph *g = r->glyphs[TEXT_AREA];
7909 struct glyph *e = g + r->used[TEXT_AREA];
7910 int gx;
7911
7912 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7913 if (EQ (g->object, object))
7914 {
7915 if (g->charpos == pos)
7916 {
7917 best_glyph = g;
7918 best_x = gx;
7919 best_row = r;
7920 goto found;
7921 }
7922 else if (best_glyph == NULL
7923 || ((abs (g->charpos - pos)
7924 < abs (best_glyph->charpos - pos))
7925 && (right_p
7926 ? g->charpos < pos
7927 : g->charpos > pos)))
7928 {
7929 best_glyph = g;
7930 best_x = gx;
7931 best_row = r;
7932 }
7933 }
7934 }
7935
7936 found:
7937
7938 if (best_glyph)
7939 {
7940 *x = best_x;
7941 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7942
7943 if (right_p)
7944 {
7945 *x += best_glyph->pixel_width;
7946 ++*hpos;
7947 }
7948
7949 *y = best_row->y;
7950 *vpos = best_row - w->current_matrix->rows;
7951 }
7952
7953 return best_glyph != NULL;
7954 }
7955
7956
7957 /* Display the active region described by mouse_face_*
7958 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7959
7960 static void
7961 show_mouse_face (dpyinfo, draw)
7962 struct x_display_info *dpyinfo;
7963 enum draw_glyphs_face draw;
7964 {
7965 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7966 struct frame *f = XFRAME (WINDOW_FRAME (w));
7967
7968 if (/* If window is in the process of being destroyed, don't bother
7969 to do anything. */
7970 w->current_matrix != NULL
7971 /* Don't update mouse highlight if hidden */
7972 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7973 /* Recognize when we are called to operate on rows that don't exist
7974 anymore. This can happen when a window is split. */
7975 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7976 {
7977 int phys_cursor_on_p = w->phys_cursor_on_p;
7978 struct glyph_row *row, *first, *last;
7979
7980 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7981 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7982
7983 for (row = first; row <= last && row->enabled_p; ++row)
7984 {
7985 int start_hpos, end_hpos, start_x;
7986
7987 /* For all but the first row, the highlight starts at column 0. */
7988 if (row == first)
7989 {
7990 start_hpos = dpyinfo->mouse_face_beg_col;
7991 start_x = dpyinfo->mouse_face_beg_x;
7992 }
7993 else
7994 {
7995 start_hpos = 0;
7996 start_x = 0;
7997 }
7998
7999 if (row == last)
8000 end_hpos = dpyinfo->mouse_face_end_col;
8001 else
8002 end_hpos = row->used[TEXT_AREA];
8003
8004 if (end_hpos > start_hpos)
8005 {
8006 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8007 start_hpos, end_hpos, draw, 0);
8008
8009 row->mouse_face_p
8010 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8011 }
8012 }
8013
8014 /* When we've written over the cursor, arrange for it to
8015 be displayed again. */
8016 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8017 x_display_cursor (w, 1,
8018 w->phys_cursor.hpos, w->phys_cursor.vpos,
8019 w->phys_cursor.x, w->phys_cursor.y);
8020 }
8021
8022 /* Change the mouse cursor. */
8023 if (draw == DRAW_NORMAL_TEXT)
8024 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8025 f->output_data.x->text_cursor);
8026 else if (draw == DRAW_MOUSE_FACE)
8027 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8028 f->output_data.x->cross_cursor);
8029 else
8030 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8031 f->output_data.x->nontext_cursor);
8032 }
8033
8034 /* Clear out the mouse-highlighted active region.
8035 Redraw it un-highlighted first. Value is non-zero if mouse
8036 face was actually drawn unhighlighted. */
8037
8038 static int
8039 clear_mouse_face (dpyinfo)
8040 struct x_display_info *dpyinfo;
8041 {
8042 int cleared = 0;
8043
8044 if (!NILP (dpyinfo->mouse_face_window))
8045 {
8046 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8047 cleared = 1;
8048 }
8049
8050 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8051 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8052 dpyinfo->mouse_face_window = Qnil;
8053 dpyinfo->mouse_face_overlay = Qnil;
8054 return cleared;
8055 }
8056
8057
8058 /* Clear any mouse-face on window W. This function is part of the
8059 redisplay interface, and is called from try_window_id and similar
8060 functions to ensure the mouse-highlight is off. */
8061
8062 static void
8063 x_clear_mouse_face (w)
8064 struct window *w;
8065 {
8066 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
8067 Lisp_Object window;
8068
8069 BLOCK_INPUT;
8070 XSETWINDOW (window, w);
8071 if (EQ (window, dpyinfo->mouse_face_window))
8072 clear_mouse_face (dpyinfo);
8073 UNBLOCK_INPUT;
8074 }
8075
8076
8077 /* Just discard the mouse face information for frame F, if any.
8078 This is used when the size of F is changed. */
8079
8080 void
8081 cancel_mouse_face (f)
8082 FRAME_PTR f;
8083 {
8084 Lisp_Object window;
8085 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8086
8087 window = dpyinfo->mouse_face_window;
8088 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8089 {
8090 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8091 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8092 dpyinfo->mouse_face_window = Qnil;
8093 }
8094 }
8095
8096 \f
8097 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
8098
8099
8100 /* Try to determine frame pixel position and size of the glyph under
8101 frame pixel coordinates X/Y on frame F . Return the position and
8102 size in *RECT. Value is non-zero if we could compute these
8103 values. */
8104
8105 static int
8106 glyph_rect (f, x, y, rect)
8107 struct frame *f;
8108 int x, y;
8109 XRectangle *rect;
8110 {
8111 Lisp_Object window;
8112 int part, found = 0;
8113
8114 window = window_from_coordinates (f, x, y, &part, 0);
8115 if (!NILP (window))
8116 {
8117 struct window *w = XWINDOW (window);
8118 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8119 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8120
8121 frame_to_window_pixel_xy (w, &x, &y);
8122
8123 for (; !found && r < end && r->enabled_p; ++r)
8124 if (r->y >= y)
8125 {
8126 struct glyph *g = r->glyphs[TEXT_AREA];
8127 struct glyph *end = g + r->used[TEXT_AREA];
8128 int gx;
8129
8130 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
8131 if (gx >= x)
8132 {
8133 rect->width = g->pixel_width;
8134 rect->height = r->height;
8135 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8136 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8137 found = 1;
8138 }
8139 }
8140 }
8141
8142 return found;
8143 }
8144
8145
8146 /* Return the current position of the mouse.
8147 *FP should be a frame which indicates which display to ask about.
8148
8149 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
8150 and *PART to the frame, window, and scroll bar part that the mouse
8151 is over. Set *X and *Y to the portion and whole of the mouse's
8152 position on the scroll bar.
8153
8154 If the mouse movement started elsewhere, set *FP to the frame the
8155 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
8156 the mouse is over.
8157
8158 Set *TIME to the server time-stamp for the time at which the mouse
8159 was at this position.
8160
8161 Don't store anything if we don't have a valid set of values to report.
8162
8163 This clears the mouse_moved flag, so we can wait for the next mouse
8164 movement. */
8165
8166 static void
8167 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8168 FRAME_PTR *fp;
8169 int insist;
8170 Lisp_Object *bar_window;
8171 enum scroll_bar_part *part;
8172 Lisp_Object *x, *y;
8173 unsigned long *time;
8174 {
8175 FRAME_PTR f1;
8176
8177 BLOCK_INPUT;
8178
8179 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8180 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8181 else
8182 {
8183 Window root;
8184 int root_x, root_y;
8185
8186 Window dummy_window;
8187 int dummy;
8188
8189 Lisp_Object frame, tail;
8190
8191 /* Clear the mouse-moved flag for every frame on this display. */
8192 FOR_EACH_FRAME (tail, frame)
8193 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
8194 XFRAME (frame)->mouse_moved = 0;
8195
8196 last_mouse_scroll_bar = Qnil;
8197
8198 /* Figure out which root window we're on. */
8199 XQueryPointer (FRAME_X_DISPLAY (*fp),
8200 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
8201
8202 /* The root window which contains the pointer. */
8203 &root,
8204
8205 /* Trash which we can't trust if the pointer is on
8206 a different screen. */
8207 &dummy_window,
8208
8209 /* The position on that root window. */
8210 &root_x, &root_y,
8211
8212 /* More trash we can't trust. */
8213 &dummy, &dummy,
8214
8215 /* Modifier keys and pointer buttons, about which
8216 we don't care. */
8217 (unsigned int *) &dummy);
8218
8219 /* Now we have a position on the root; find the innermost window
8220 containing the pointer. */
8221 {
8222 Window win, child;
8223 int win_x, win_y;
8224 int parent_x = 0, parent_y = 0;
8225 int count;
8226
8227 win = root;
8228
8229 /* XTranslateCoordinates can get errors if the window
8230 structure is changing at the same time this function
8231 is running. So at least we must not crash from them. */
8232
8233 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
8234
8235 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
8236 && FRAME_LIVE_P (last_mouse_frame))
8237 {
8238 /* If mouse was grabbed on a frame, give coords for that frame
8239 even if the mouse is now outside it. */
8240 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8241
8242 /* From-window, to-window. */
8243 root, FRAME_X_WINDOW (last_mouse_frame),
8244
8245 /* From-position, to-position. */
8246 root_x, root_y, &win_x, &win_y,
8247
8248 /* Child of win. */
8249 &child);
8250 f1 = last_mouse_frame;
8251 }
8252 else
8253 {
8254 while (1)
8255 {
8256 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8257
8258 /* From-window, to-window. */
8259 root, win,
8260
8261 /* From-position, to-position. */
8262 root_x, root_y, &win_x, &win_y,
8263
8264 /* Child of win. */
8265 &child);
8266
8267 if (child == None || child == win)
8268 break;
8269
8270 win = child;
8271 parent_x = win_x;
8272 parent_y = win_y;
8273 }
8274
8275 /* Now we know that:
8276 win is the innermost window containing the pointer
8277 (XTC says it has no child containing the pointer),
8278 win_x and win_y are the pointer's position in it
8279 (XTC did this the last time through), and
8280 parent_x and parent_y are the pointer's position in win's parent.
8281 (They are what win_x and win_y were when win was child.
8282 If win is the root window, it has no parent, and
8283 parent_{x,y} are invalid, but that's okay, because we'll
8284 never use them in that case.) */
8285
8286 /* Is win one of our frames? */
8287 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
8288
8289 #ifdef USE_X_TOOLKIT
8290 /* If we end up with the menu bar window, say it's not
8291 on the frame. */
8292 if (f1 != NULL
8293 && f1->output_data.x->menubar_widget
8294 && win == XtWindow (f1->output_data.x->menubar_widget))
8295 f1 = NULL;
8296 #endif /* USE_X_TOOLKIT */
8297 }
8298
8299 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8300 f1 = 0;
8301
8302 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
8303
8304 /* If not, is it one of our scroll bars? */
8305 if (! f1)
8306 {
8307 struct scroll_bar *bar = x_window_to_scroll_bar (win);
8308
8309 if (bar)
8310 {
8311 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8312 win_x = parent_x;
8313 win_y = parent_y;
8314 }
8315 }
8316
8317 if (f1 == 0 && insist > 0)
8318 f1 = SELECTED_FRAME ();
8319
8320 if (f1)
8321 {
8322 /* Ok, we found a frame. Store all the values.
8323 last_mouse_glyph is a rectangle used to reduce the
8324 generation of mouse events. To not miss any motion
8325 events, we must divide the frame into rectangles of the
8326 size of the smallest character that could be displayed
8327 on it, i.e. into the same rectangles that matrices on
8328 the frame are divided into. */
8329
8330 int width, height, gx, gy;
8331 XRectangle rect;
8332
8333 if (glyph_rect (f1, win_x, win_y, &rect))
8334 last_mouse_glyph = rect;
8335 else
8336 {
8337 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8338 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8339 gx = win_x;
8340 gy = win_y;
8341
8342 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8343 round down even for negative values. */
8344 if (gx < 0)
8345 gx -= width - 1;
8346 if (gy < 0)
8347 gy -= height - 1;
8348 gx = (gx + width - 1) / width * width;
8349 gy = (gy + height - 1) / height * height;
8350
8351 last_mouse_glyph.width = width;
8352 last_mouse_glyph.height = height;
8353 last_mouse_glyph.x = gx;
8354 last_mouse_glyph.y = gy;
8355 }
8356
8357 *bar_window = Qnil;
8358 *part = 0;
8359 *fp = f1;
8360 XSETINT (*x, win_x);
8361 XSETINT (*y, win_y);
8362 *time = last_mouse_movement_time;
8363 }
8364 }
8365 }
8366
8367 UNBLOCK_INPUT;
8368 }
8369
8370
8371 #ifdef USE_X_TOOLKIT
8372
8373 /* Atimer callback function for TIMER. Called every 0.1s to process
8374 Xt timeouts, if needed. We must avoid calling XtAppPending as
8375 much as possible because that function does an implicit XFlush
8376 that slows us down. */
8377
8378 static void
8379 x_process_timeouts (timer)
8380 struct atimer *timer;
8381 {
8382 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8383 {
8384 BLOCK_INPUT;
8385 while (XtAppPending (Xt_app_con) & XtIMTimer)
8386 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8387 UNBLOCK_INPUT;
8388 }
8389 }
8390
8391 #endif /* USE_X_TOOLKIT */
8392
8393 \f
8394 /* Scroll bar support. */
8395
8396 /* Given an X window ID, find the struct scroll_bar which manages it.
8397 This can be called in GC, so we have to make sure to strip off mark
8398 bits. */
8399
8400 static struct scroll_bar *
8401 x_window_to_scroll_bar (window_id)
8402 Window window_id;
8403 {
8404 Lisp_Object tail;
8405
8406 for (tail = Vframe_list;
8407 XGCTYPE (tail) == Lisp_Cons;
8408 tail = XCDR (tail))
8409 {
8410 Lisp_Object frame, bar, condemned;
8411
8412 frame = XCAR (tail);
8413 /* All elements of Vframe_list should be frames. */
8414 if (! GC_FRAMEP (frame))
8415 abort ();
8416
8417 /* Scan this frame's scroll bar list for a scroll bar with the
8418 right window ID. */
8419 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8420 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8421 /* This trick allows us to search both the ordinary and
8422 condemned scroll bar lists with one loop. */
8423 ! GC_NILP (bar) || (bar = condemned,
8424 condemned = Qnil,
8425 ! GC_NILP (bar));
8426 bar = XSCROLL_BAR (bar)->next)
8427 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8428 return XSCROLL_BAR (bar);
8429 }
8430
8431 return 0;
8432 }
8433
8434
8435 #if defined USE_LUCID
8436
8437 /* Return the Lucid menu bar WINDOW is part of. Return null
8438 if WINDOW is not part of a menu bar. */
8439
8440 static Widget
8441 x_window_to_menu_bar (window)
8442 Window window;
8443 {
8444 Lisp_Object tail;
8445
8446 for (tail = Vframe_list;
8447 XGCTYPE (tail) == Lisp_Cons;
8448 tail = XCDR (tail))
8449 {
8450 Lisp_Object frame = XCAR (tail);
8451 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8452
8453 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8454 return menu_bar;
8455 }
8456
8457 return NULL;
8458 }
8459
8460 #endif /* USE_LUCID */
8461
8462 \f
8463 /************************************************************************
8464 Toolkit scroll bars
8465 ************************************************************************/
8466
8467 #ifdef USE_TOOLKIT_SCROLL_BARS
8468
8469 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8470 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8471 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8472 struct scroll_bar *));
8473 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8474 int, int, int));
8475
8476
8477 /* Id of action hook installed for scroll bars. */
8478
8479 static XtActionHookId action_hook_id;
8480
8481 /* Lisp window being scrolled. Set when starting to interact with
8482 a toolkit scroll bar, reset to nil when ending the interaction. */
8483
8484 static Lisp_Object window_being_scrolled;
8485
8486 /* Last scroll bar part sent in xm_scroll_callback. */
8487
8488 static int last_scroll_bar_part;
8489
8490 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8491 that movements of 1/20 of the screen size are mapped to up/down. */
8492
8493 static Boolean xaw3d_arrow_scroll;
8494
8495 /* Whether the drag scrolling maintains the mouse at the top of the
8496 thumb. If not, resizing the thumb needs to be done more carefully
8497 to avoid jerkyness. */
8498
8499 static Boolean xaw3d_pick_top;
8500
8501
8502 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8503 bars are used.. The hook is responsible for detecting when
8504 the user ends an interaction with the scroll bar, and generates
8505 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
8506
8507 static void
8508 xt_action_hook (widget, client_data, action_name, event, params,
8509 num_params)
8510 Widget widget;
8511 XtPointer client_data;
8512 String action_name;
8513 XEvent *event;
8514 String *params;
8515 Cardinal *num_params;
8516 {
8517 int scroll_bar_p;
8518 char *end_action;
8519
8520 #ifdef USE_MOTIF
8521 scroll_bar_p = XmIsScrollBar (widget);
8522 end_action = "Release";
8523 #else /* !USE_MOTIF i.e. use Xaw */
8524 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8525 end_action = "EndScroll";
8526 #endif /* USE_MOTIF */
8527
8528 if (scroll_bar_p
8529 && strcmp (action_name, end_action) == 0
8530 && WINDOWP (window_being_scrolled))
8531 {
8532 struct window *w;
8533
8534 x_send_scroll_bar_event (window_being_scrolled,
8535 scroll_bar_end_scroll, 0, 0);
8536 w = XWINDOW (window_being_scrolled);
8537 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8538 window_being_scrolled = Qnil;
8539 last_scroll_bar_part = -1;
8540
8541 /* Xt timeouts no longer needed. */
8542 toolkit_scroll_bar_interaction = 0;
8543 }
8544 }
8545
8546 /* A vector of windows used for communication between
8547 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8548
8549 static struct window **scroll_bar_windows;
8550 static int scroll_bar_windows_size;
8551
8552
8553 /* Send a client message with message type Xatom_Scrollbar for a
8554 scroll action to the frame of WINDOW. PART is a value identifying
8555 the part of the scroll bar that was clicked on. PORTION is the
8556 amount to scroll of a whole of WHOLE. */
8557
8558 static void
8559 x_send_scroll_bar_event (window, part, portion, whole)
8560 Lisp_Object window;
8561 int part, portion, whole;
8562 {
8563 XEvent event;
8564 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8565 struct window *w = XWINDOW (window);
8566 struct frame *f = XFRAME (w->frame);
8567 int i;
8568
8569 BLOCK_INPUT;
8570
8571 /* Construct a ClientMessage event to send to the frame. */
8572 ev->type = ClientMessage;
8573 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8574 ev->display = FRAME_X_DISPLAY (f);
8575 ev->window = FRAME_X_WINDOW (f);
8576 ev->format = 32;
8577
8578 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8579 not enough to store a pointer or Lisp_Object on a 64 bit system.
8580 So, store the window in scroll_bar_windows and pass the index
8581 into that array in the event. */
8582 for (i = 0; i < scroll_bar_windows_size; ++i)
8583 if (scroll_bar_windows[i] == NULL)
8584 break;
8585
8586 if (i == scroll_bar_windows_size)
8587 {
8588 int new_size = max (10, 2 * scroll_bar_windows_size);
8589 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8590 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8591
8592 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8593 nbytes);
8594 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8595 scroll_bar_windows_size = new_size;
8596 }
8597
8598 scroll_bar_windows[i] = w;
8599 ev->data.l[0] = (long) i;
8600 ev->data.l[1] = (long) part;
8601 ev->data.l[2] = (long) 0;
8602 ev->data.l[3] = (long) portion;
8603 ev->data.l[4] = (long) whole;
8604
8605 /* Make Xt timeouts work while the scroll bar is active. */
8606 toolkit_scroll_bar_interaction = 1;
8607
8608 /* Setting the event mask to zero means that the message will
8609 be sent to the client that created the window, and if that
8610 window no longer exists, no event will be sent. */
8611 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8612 UNBLOCK_INPUT;
8613 }
8614
8615
8616 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8617 in *IEVENT. */
8618
8619 static void
8620 x_scroll_bar_to_input_event (event, ievent)
8621 XEvent *event;
8622 struct input_event *ievent;
8623 {
8624 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8625 Lisp_Object window;
8626 struct frame *f;
8627 struct window *w;
8628
8629 w = scroll_bar_windows[ev->data.l[0]];
8630 scroll_bar_windows[ev->data.l[0]] = NULL;
8631
8632 XSETWINDOW (window, w);
8633 f = XFRAME (w->frame);
8634
8635 ievent->kind = SCROLL_BAR_CLICK_EVENT;
8636 ievent->frame_or_window = window;
8637 ievent->arg = Qnil;
8638 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8639 ievent->part = ev->data.l[1];
8640 ievent->code = ev->data.l[2];
8641 ievent->x = make_number ((int) ev->data.l[3]);
8642 ievent->y = make_number ((int) ev->data.l[4]);
8643 ievent->modifiers = 0;
8644 }
8645
8646
8647 #ifdef USE_MOTIF
8648
8649 /* Minimum and maximum values used for Motif scroll bars. */
8650
8651 #define XM_SB_MIN 1
8652 #define XM_SB_MAX 10000000
8653 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8654
8655
8656 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8657 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8658 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
8659
8660 static void
8661 xm_scroll_callback (widget, client_data, call_data)
8662 Widget widget;
8663 XtPointer client_data, call_data;
8664 {
8665 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8666 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8667 int part = -1, whole = 0, portion = 0;
8668
8669 switch (cs->reason)
8670 {
8671 case XmCR_DECREMENT:
8672 bar->dragging = Qnil;
8673 part = scroll_bar_up_arrow;
8674 break;
8675
8676 case XmCR_INCREMENT:
8677 bar->dragging = Qnil;
8678 part = scroll_bar_down_arrow;
8679 break;
8680
8681 case XmCR_PAGE_DECREMENT:
8682 bar->dragging = Qnil;
8683 part = scroll_bar_above_handle;
8684 break;
8685
8686 case XmCR_PAGE_INCREMENT:
8687 bar->dragging = Qnil;
8688 part = scroll_bar_below_handle;
8689 break;
8690
8691 case XmCR_TO_TOP:
8692 bar->dragging = Qnil;
8693 part = scroll_bar_to_top;
8694 break;
8695
8696 case XmCR_TO_BOTTOM:
8697 bar->dragging = Qnil;
8698 part = scroll_bar_to_bottom;
8699 break;
8700
8701 case XmCR_DRAG:
8702 {
8703 int slider_size;
8704 int dragging_down_p = (INTEGERP (bar->dragging)
8705 && XINT (bar->dragging) <= cs->value);
8706
8707 /* Get the slider size. */
8708 BLOCK_INPUT;
8709 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8710 UNBLOCK_INPUT;
8711
8712 whole = XM_SB_RANGE - slider_size;
8713 portion = min (cs->value - XM_SB_MIN, whole);
8714 part = scroll_bar_handle;
8715 bar->dragging = make_number (cs->value);
8716 }
8717 break;
8718
8719 case XmCR_VALUE_CHANGED:
8720 break;
8721 };
8722
8723 if (part >= 0)
8724 {
8725 window_being_scrolled = bar->window;
8726 last_scroll_bar_part = part;
8727 x_send_scroll_bar_event (bar->window, part, portion, whole);
8728 }
8729 }
8730
8731
8732 #else /* !USE_MOTIF, i.e. Xaw. */
8733
8734
8735 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8736 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8737 scroll bar struct. CALL_DATA is a pointer to a float saying where
8738 the thumb is. */
8739
8740 static void
8741 xaw_jump_callback (widget, client_data, call_data)
8742 Widget widget;
8743 XtPointer client_data, call_data;
8744 {
8745 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8746 float top = *(float *) call_data;
8747 float shown;
8748 int whole, portion, height;
8749 int part;
8750
8751 /* Get the size of the thumb, a value between 0 and 1. */
8752 BLOCK_INPUT;
8753 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8754 UNBLOCK_INPUT;
8755
8756 whole = 10000000;
8757 portion = shown < 1 ? top * whole : 0;
8758
8759 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8760 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8761 the bottom, so we force the scrolling whenever we see that we're
8762 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8763 we try to ensure that we always stay two pixels away from the
8764 bottom). */
8765 part = scroll_bar_down_arrow;
8766 else
8767 part = scroll_bar_handle;
8768
8769 window_being_scrolled = bar->window;
8770 bar->dragging = make_number (portion);
8771 last_scroll_bar_part = part;
8772 x_send_scroll_bar_event (bar->window, part, portion, whole);
8773 }
8774
8775
8776 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8777 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8778 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8779 the scroll bar. CALL_DATA is an integer specifying the action that
8780 has taken place. It's magnitude is in the range 0..height of the
8781 scroll bar. Negative values mean scroll towards buffer start.
8782 Values < height of scroll bar mean line-wise movement. */
8783
8784 static void
8785 xaw_scroll_callback (widget, client_data, call_data)
8786 Widget widget;
8787 XtPointer client_data, call_data;
8788 {
8789 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8790 int position = (int) call_data;
8791 Dimension height;
8792 int part;
8793
8794 /* Get the height of the scroll bar. */
8795 BLOCK_INPUT;
8796 XtVaGetValues (widget, XtNheight, &height, NULL);
8797 UNBLOCK_INPUT;
8798
8799 if (abs (position) >= height)
8800 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8801
8802 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8803 it maps line-movement to call_data = max(5, height/20). */
8804 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8805 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8806 else
8807 part = scroll_bar_move_ratio;
8808
8809 window_being_scrolled = bar->window;
8810 bar->dragging = Qnil;
8811 last_scroll_bar_part = part;
8812 x_send_scroll_bar_event (bar->window, part, position, height);
8813 }
8814
8815
8816 #endif /* not USE_MOTIF */
8817
8818
8819 /* Create the widget for scroll bar BAR on frame F. Record the widget
8820 and X window of the scroll bar in BAR. */
8821
8822 static void
8823 x_create_toolkit_scroll_bar (f, bar)
8824 struct frame *f;
8825 struct scroll_bar *bar;
8826 {
8827 Window xwindow;
8828 Widget widget;
8829 Arg av[20];
8830 int ac = 0;
8831 char *scroll_bar_name = "verticalScrollBar";
8832 unsigned long pixel;
8833
8834 BLOCK_INPUT;
8835
8836 #ifdef USE_MOTIF
8837 /* Set resources. Create the widget. */
8838 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8839 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8840 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8841 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8842 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8843 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8844 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8845
8846 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8847 if (pixel != -1)
8848 {
8849 XtSetArg (av[ac], XmNforeground, pixel);
8850 ++ac;
8851 }
8852
8853 pixel = f->output_data.x->scroll_bar_background_pixel;
8854 if (pixel != -1)
8855 {
8856 XtSetArg (av[ac], XmNbackground, pixel);
8857 ++ac;
8858 }
8859
8860 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8861 scroll_bar_name, av, ac);
8862
8863 /* Add one callback for everything that can happen. */
8864 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8865 (XtPointer) bar);
8866 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8867 (XtPointer) bar);
8868 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8869 (XtPointer) bar);
8870 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8871 (XtPointer) bar);
8872 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8873 (XtPointer) bar);
8874 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8875 (XtPointer) bar);
8876 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8877 (XtPointer) bar);
8878
8879 /* Realize the widget. Only after that is the X window created. */
8880 XtRealizeWidget (widget);
8881
8882 /* Set the cursor to an arrow. I didn't find a resource to do that.
8883 And I'm wondering why it hasn't an arrow cursor by default. */
8884 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8885 f->output_data.x->nontext_cursor);
8886
8887 #else /* !USE_MOTIF i.e. use Xaw */
8888
8889 /* Set resources. Create the widget. The background of the
8890 Xaw3d scroll bar widget is a little bit light for my taste.
8891 We don't alter it here to let users change it according
8892 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8893 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8894 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8895 /* For smoother scrolling with Xaw3d -sm */
8896 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8897
8898 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8899 if (pixel != -1)
8900 {
8901 XtSetArg (av[ac], XtNforeground, pixel);
8902 ++ac;
8903 }
8904
8905 pixel = f->output_data.x->scroll_bar_background_pixel;
8906 if (pixel != -1)
8907 {
8908 XtSetArg (av[ac], XtNbackground, pixel);
8909 ++ac;
8910 }
8911
8912 /* Top/bottom shadow colors. */
8913
8914 /* Allocate them, if necessary. */
8915 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8916 {
8917 pixel = f->output_data.x->scroll_bar_background_pixel;
8918 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8919 &pixel, 1.2, 0x8000))
8920 pixel = -1;
8921 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8922 }
8923 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8924 {
8925 pixel = f->output_data.x->scroll_bar_background_pixel;
8926 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8927 &pixel, 0.6, 0x4000))
8928 pixel = -1;
8929 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8930 }
8931
8932 /* Tell the toolkit about them. */
8933 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8934 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8935 /* We tried to allocate a color for the top/bottom shadow, and
8936 failed, so tell Xaw3d to use dithering instead. */
8937 {
8938 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8939 ++ac;
8940 }
8941 else
8942 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8943 be more consistent with other emacs 3d colors, and since Xaw3d is
8944 not good at dealing with allocation failure. */
8945 {
8946 /* This tells Xaw3d to use real colors instead of dithering for
8947 the shadows. */
8948 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8949 ++ac;
8950
8951 /* Specify the colors. */
8952 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8953 if (pixel != -1)
8954 {
8955 XtSetArg (av[ac], "topShadowPixel", pixel);
8956 ++ac;
8957 }
8958 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8959 if (pixel != -1)
8960 {
8961 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8962 ++ac;
8963 }
8964 }
8965
8966 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8967 f->output_data.x->edit_widget, av, ac);
8968
8969 {
8970 char *initial = "";
8971 char *val = initial;
8972 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8973 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8974 if (val == initial)
8975 { /* ARROW_SCROLL */
8976 xaw3d_arrow_scroll = True;
8977 /* Isn't that just a personal preference ? -sm */
8978 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8979 }
8980 }
8981
8982 /* Define callbacks. */
8983 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8984 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8985 (XtPointer) bar);
8986
8987 /* Realize the widget. Only after that is the X window created. */
8988 XtRealizeWidget (widget);
8989
8990 #endif /* !USE_MOTIF */
8991
8992 /* Install an action hook that lets us detect when the user
8993 finishes interacting with a scroll bar. */
8994 if (action_hook_id == 0)
8995 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8996
8997 /* Remember X window and widget in the scroll bar vector. */
8998 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8999 xwindow = XtWindow (widget);
9000 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
9001
9002 UNBLOCK_INPUT;
9003 }
9004
9005
9006 /* Set the thumb size and position of scroll bar BAR. We are currently
9007 displaying PORTION out of a whole WHOLE, and our position POSITION. */
9008
9009 static void
9010 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
9011 struct scroll_bar *bar;
9012 int portion, position, whole;
9013 {
9014 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9015 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9016 float top, shown;
9017
9018 BLOCK_INPUT;
9019
9020 #ifdef USE_MOTIF
9021
9022 /* We use an estimate of 30 chars per line rather than the real
9023 `portion' value. This has the disadvantage that the thumb size
9024 is not very representative, but it makes our life a lot easier.
9025 Otherwise, we have to constantly adjust the thumb size, which
9026 we can't always do quickly enough: while dragging, the size of
9027 the thumb might prevent the user from dragging the thumb all the
9028 way to the end. but Motif and some versions of Xaw3d don't allow
9029 updating the thumb size while dragging. Also, even if we can update
9030 its size, the update will often happen too late.
9031 If you don't believe it, check out revision 1.650 of xterm.c to see
9032 what hoops we were going through and the still poor behavior we got. */
9033 portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
9034 /* When the thumb is at the bottom, position == whole.
9035 So we need to increase `whole' to make space for the thumb. */
9036 whole += portion;
9037
9038 if (whole <= 0)
9039 top = 0, shown = 1;
9040 else
9041 {
9042 top = (float) position / whole;
9043 shown = (float) portion / whole;
9044 }
9045
9046 if (NILP (bar->dragging))
9047 {
9048 int size, value;
9049
9050 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
9051 is the scroll bar's maximum and MIN is the scroll bar's minimum
9052 value. */
9053 size = shown * XM_SB_RANGE;
9054 size = min (size, XM_SB_RANGE);
9055 size = max (size, 1);
9056
9057 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
9058 value = top * XM_SB_RANGE;
9059 value = min (value, XM_SB_MAX - size);
9060 value = max (value, XM_SB_MIN);
9061
9062 XmScrollBarSetValues (widget, value, size, 0, 0, False);
9063 }
9064 #else /* !USE_MOTIF i.e. use Xaw */
9065
9066 if (whole == 0)
9067 top = 0, shown = 1;
9068 else
9069 {
9070 top = (float) position / whole;
9071 shown = (float) portion / whole;
9072 }
9073
9074 {
9075 float old_top, old_shown;
9076 Dimension height;
9077 XtVaGetValues (widget,
9078 XtNtopOfThumb, &old_top,
9079 XtNshown, &old_shown,
9080 XtNheight, &height,
9081 NULL);
9082
9083 /* Massage the top+shown values. */
9084 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
9085 top = max (0, min (1, top));
9086 else
9087 top = old_top;
9088 /* Keep two pixels available for moving the thumb down. */
9089 shown = max (0, min (1 - top - (2.0 / height), shown));
9090
9091 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
9092 check that your system's configuration file contains a define
9093 for `NARROWPROTO'. See s/freebsd.h for an example. */
9094 if (top != old_top || shown != old_shown)
9095 {
9096 if (NILP (bar->dragging))
9097 XawScrollbarSetThumb (widget, top, shown);
9098 else
9099 {
9100 #ifdef HAVE_XAW3D
9101 ScrollbarWidget sb = (ScrollbarWidget) widget;
9102 int scroll_mode = 0;
9103
9104 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
9105 if (xaw3d_arrow_scroll)
9106 {
9107 /* Xaw3d stupidly ignores resize requests while dragging
9108 so we have to make it believe it's not in dragging mode. */
9109 scroll_mode = sb->scrollbar.scroll_mode;
9110 if (scroll_mode == 2)
9111 sb->scrollbar.scroll_mode = 0;
9112 }
9113 #endif
9114 /* Try to make the scrolling a tad smoother. */
9115 if (!xaw3d_pick_top)
9116 shown = min (shown, old_shown);
9117
9118 XawScrollbarSetThumb (widget, top, shown);
9119
9120 #ifdef HAVE_XAW3D
9121 if (xaw3d_arrow_scroll && scroll_mode == 2)
9122 sb->scrollbar.scroll_mode = scroll_mode;
9123 #endif
9124 }
9125 }
9126 }
9127 #endif /* !USE_MOTIF */
9128
9129 UNBLOCK_INPUT;
9130 }
9131
9132 #endif /* USE_TOOLKIT_SCROLL_BARS */
9133
9134
9135 \f
9136 /************************************************************************
9137 Scroll bars, general
9138 ************************************************************************/
9139
9140 /* Create a scroll bar and return the scroll bar vector for it. W is
9141 the Emacs window on which to create the scroll bar. TOP, LEFT,
9142 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
9143 scroll bar. */
9144
9145 static struct scroll_bar *
9146 x_scroll_bar_create (w, top, left, width, height)
9147 struct window *w;
9148 int top, left, width, height;
9149 {
9150 struct frame *f = XFRAME (w->frame);
9151 struct scroll_bar *bar
9152 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
9153
9154 BLOCK_INPUT;
9155
9156 #ifdef USE_TOOLKIT_SCROLL_BARS
9157 x_create_toolkit_scroll_bar (f, bar);
9158 #else /* not USE_TOOLKIT_SCROLL_BARS */
9159 {
9160 XSetWindowAttributes a;
9161 unsigned long mask;
9162 Window window;
9163
9164 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
9165 if (a.background_pixel == -1)
9166 a.background_pixel = f->output_data.x->background_pixel;
9167
9168 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9169 | ButtonMotionMask | PointerMotionHintMask
9170 | ExposureMask);
9171 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
9172
9173 mask = (CWBackPixel | CWEventMask | CWCursor);
9174
9175 /* Clear the area of W that will serve as a scroll bar. This is
9176 for the case that a window has been split horizontally. In
9177 this case, no clear_frame is generated to reduce flickering. */
9178 if (width > 0 && height > 0)
9179 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9180 left, top, width,
9181 window_box_height (w), False);
9182
9183 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9184 /* Position and size of scroll bar. */
9185 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9186 top,
9187 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9188 height,
9189 /* Border width, depth, class, and visual. */
9190 0,
9191 CopyFromParent,
9192 CopyFromParent,
9193 CopyFromParent,
9194 /* Attributes. */
9195 mask, &a);
9196 SET_SCROLL_BAR_X_WINDOW (bar, window);
9197 }
9198 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9199
9200 XSETWINDOW (bar->window, w);
9201 XSETINT (bar->top, top);
9202 XSETINT (bar->left, left);
9203 XSETINT (bar->width, width);
9204 XSETINT (bar->height, height);
9205 XSETINT (bar->start, 0);
9206 XSETINT (bar->end, 0);
9207 bar->dragging = Qnil;
9208
9209 /* Add bar to its frame's list of scroll bars. */
9210 bar->next = FRAME_SCROLL_BARS (f);
9211 bar->prev = Qnil;
9212 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9213 if (!NILP (bar->next))
9214 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9215
9216 /* Map the window/widget. */
9217 #ifdef USE_TOOLKIT_SCROLL_BARS
9218 {
9219 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9220 XtConfigureWidget (scroll_bar,
9221 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9222 top,
9223 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9224 max (height, 1), 0);
9225 XtMapWidget (scroll_bar);
9226 }
9227 #else /* not USE_TOOLKIT_SCROLL_BARS */
9228 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9229 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9230
9231 UNBLOCK_INPUT;
9232 return bar;
9233 }
9234
9235
9236 /* Draw BAR's handle in the proper position.
9237
9238 If the handle is already drawn from START to END, don't bother
9239 redrawing it, unless REBUILD is non-zero; in that case, always
9240 redraw it. (REBUILD is handy for drawing the handle after expose
9241 events.)
9242
9243 Normally, we want to constrain the start and end of the handle to
9244 fit inside its rectangle, but if the user is dragging the scroll
9245 bar handle, we want to let them drag it down all the way, so that
9246 the bar's top is as far down as it goes; otherwise, there's no way
9247 to move to the very end of the buffer. */
9248
9249 #ifndef USE_TOOLKIT_SCROLL_BARS
9250
9251 static void
9252 x_scroll_bar_set_handle (bar, start, end, rebuild)
9253 struct scroll_bar *bar;
9254 int start, end;
9255 int rebuild;
9256 {
9257 int dragging = ! NILP (bar->dragging);
9258 Window w = SCROLL_BAR_X_WINDOW (bar);
9259 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9260 GC gc = f->output_data.x->normal_gc;
9261
9262 /* If the display is already accurate, do nothing. */
9263 if (! rebuild
9264 && start == XINT (bar->start)
9265 && end == XINT (bar->end))
9266 return;
9267
9268 BLOCK_INPUT;
9269
9270 {
9271 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9272 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9273 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9274
9275 /* Make sure the values are reasonable, and try to preserve
9276 the distance between start and end. */
9277 {
9278 int length = end - start;
9279
9280 if (start < 0)
9281 start = 0;
9282 else if (start > top_range)
9283 start = top_range;
9284 end = start + length;
9285
9286 if (end < start)
9287 end = start;
9288 else if (end > top_range && ! dragging)
9289 end = top_range;
9290 }
9291
9292 /* Store the adjusted setting in the scroll bar. */
9293 XSETINT (bar->start, start);
9294 XSETINT (bar->end, end);
9295
9296 /* Clip the end position, just for display. */
9297 if (end > top_range)
9298 end = top_range;
9299
9300 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9301 below top positions, to make sure the handle is always at least
9302 that many pixels tall. */
9303 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
9304
9305 /* Draw the empty space above the handle. Note that we can't clear
9306 zero-height areas; that means "clear to end of window." */
9307 if (0 < start)
9308 x_clear_area (FRAME_X_DISPLAY (f), w,
9309 /* x, y, width, height, and exposures. */
9310 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9311 VERTICAL_SCROLL_BAR_TOP_BORDER,
9312 inside_width, start,
9313 False);
9314
9315 /* Change to proper foreground color if one is specified. */
9316 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9317 XSetForeground (FRAME_X_DISPLAY (f), gc,
9318 f->output_data.x->scroll_bar_foreground_pixel);
9319
9320 /* Draw the handle itself. */
9321 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
9322 /* x, y, width, height */
9323 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9324 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
9325 inside_width, end - start);
9326
9327 /* Restore the foreground color of the GC if we changed it above. */
9328 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9329 XSetForeground (FRAME_X_DISPLAY (f), gc,
9330 f->output_data.x->foreground_pixel);
9331
9332 /* Draw the empty space below the handle. Note that we can't
9333 clear zero-height areas; that means "clear to end of window." */
9334 if (end < inside_height)
9335 x_clear_area (FRAME_X_DISPLAY (f), w,
9336 /* x, y, width, height, and exposures. */
9337 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9338 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9339 inside_width, inside_height - end,
9340 False);
9341
9342 }
9343
9344 UNBLOCK_INPUT;
9345 }
9346
9347 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9348
9349 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9350 nil. */
9351
9352 static void
9353 x_scroll_bar_remove (bar)
9354 struct scroll_bar *bar;
9355 {
9356 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9357 BLOCK_INPUT;
9358
9359 #ifdef USE_TOOLKIT_SCROLL_BARS
9360 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9361 #else
9362 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9363 #endif
9364
9365 /* Disassociate this scroll bar from its window. */
9366 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
9367
9368 UNBLOCK_INPUT;
9369 }
9370
9371
9372 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9373 that we are displaying PORTION characters out of a total of WHOLE
9374 characters, starting at POSITION. If WINDOW has no scroll bar,
9375 create one. */
9376
9377 static void
9378 XTset_vertical_scroll_bar (w, portion, whole, position)
9379 struct window *w;
9380 int portion, whole, position;
9381 {
9382 struct frame *f = XFRAME (w->frame);
9383 struct scroll_bar *bar;
9384 int top, height, left, sb_left, width, sb_width;
9385 int window_x, window_y, window_width, window_height;
9386
9387 /* Get window dimensions. */
9388 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9389 top = window_y;
9390 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9391 height = window_height;
9392
9393 /* Compute the left edge of the scroll bar area. */
9394 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9395 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9396 else
9397 left = XFASTINT (w->left);
9398 left *= CANON_X_UNIT (f);
9399 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9400
9401 /* Compute the width of the scroll bar which might be less than
9402 the width of the area reserved for the scroll bar. */
9403 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9404 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
9405 else
9406 sb_width = width;
9407
9408 /* Compute the left edge of the scroll bar. */
9409 #ifdef USE_TOOLKIT_SCROLL_BARS
9410 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9411 sb_left = left + width - sb_width - (width - sb_width) / 2;
9412 else
9413 sb_left = left + (width - sb_width) / 2;
9414 #else
9415 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9416 sb_left = left + width - sb_width;
9417 else
9418 sb_left = left;
9419 #endif
9420
9421 /* Does the scroll bar exist yet? */
9422 if (NILP (w->vertical_scroll_bar))
9423 {
9424 if (width > 0 && height > 0)
9425 {
9426 BLOCK_INPUT;
9427 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9428 left, top, width, height, False);
9429 UNBLOCK_INPUT;
9430 }
9431
9432 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9433 }
9434 else
9435 {
9436 /* It may just need to be moved and resized. */
9437 unsigned int mask = 0;
9438
9439 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9440
9441 BLOCK_INPUT;
9442
9443 if (sb_left != XINT (bar->left))
9444 mask |= CWX;
9445 if (top != XINT (bar->top))
9446 mask |= CWY;
9447 if (sb_width != XINT (bar->width))
9448 mask |= CWWidth;
9449 if (height != XINT (bar->height))
9450 mask |= CWHeight;
9451
9452 #ifdef USE_TOOLKIT_SCROLL_BARS
9453
9454 /* Since toolkit scroll bars are smaller than the space reserved
9455 for them on the frame, we have to clear "under" them. */
9456 if (width > 0 && height > 0)
9457 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9458 left, top, width, height, False);
9459
9460 /* Move/size the scroll bar widget. */
9461 if (mask)
9462 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9463 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9464 top,
9465 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9466 max (height, 1), 0);
9467
9468 #else /* not USE_TOOLKIT_SCROLL_BARS */
9469
9470 /* Clear areas not covered by the scroll bar because of
9471 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9472 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9473 {
9474 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9475 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9476 height, False);
9477 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9478 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9479 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9480 height, False);
9481 }
9482
9483 /* Clear areas not covered by the scroll bar because it's not as
9484 wide as the area reserved for it. This makes sure a
9485 previous mode line display is cleared after C-x 2 C-x 1, for
9486 example. */
9487 {
9488 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9489 int rest = area_width - sb_width;
9490 if (rest > 0 && height > 0)
9491 {
9492 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
9493 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9494 left + area_width - rest, top,
9495 rest, height, False);
9496 else
9497 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9498 left, top, rest, height, False);
9499 }
9500 }
9501
9502 /* Move/size the scroll bar window. */
9503 if (mask)
9504 {
9505 XWindowChanges wc;
9506
9507 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9508 wc.y = top;
9509 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9510 wc.height = height;
9511 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9512 mask, &wc);
9513 }
9514
9515 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9516
9517 /* Remember new settings. */
9518 XSETINT (bar->left, sb_left);
9519 XSETINT (bar->top, top);
9520 XSETINT (bar->width, sb_width);
9521 XSETINT (bar->height, height);
9522
9523 UNBLOCK_INPUT;
9524 }
9525
9526 #ifdef USE_TOOLKIT_SCROLL_BARS
9527 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9528 #else /* not USE_TOOLKIT_SCROLL_BARS */
9529 /* Set the scroll bar's current state, unless we're currently being
9530 dragged. */
9531 if (NILP (bar->dragging))
9532 {
9533 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9534
9535 if (whole == 0)
9536 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9537 else
9538 {
9539 int start = ((double) position * top_range) / whole;
9540 int end = ((double) (position + portion) * top_range) / whole;
9541 x_scroll_bar_set_handle (bar, start, end, 0);
9542 }
9543 }
9544 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9545
9546 XSETVECTOR (w->vertical_scroll_bar, bar);
9547 }
9548
9549
9550 /* The following three hooks are used when we're doing a thorough
9551 redisplay of the frame. We don't explicitly know which scroll bars
9552 are going to be deleted, because keeping track of when windows go
9553 away is a real pain - "Can you say set-window-configuration, boys
9554 and girls?" Instead, we just assert at the beginning of redisplay
9555 that *all* scroll bars are to be removed, and then save a scroll bar
9556 from the fiery pit when we actually redisplay its window. */
9557
9558 /* Arrange for all scroll bars on FRAME to be removed at the next call
9559 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9560 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9561
9562 static void
9563 XTcondemn_scroll_bars (frame)
9564 FRAME_PTR frame;
9565 {
9566 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9567 while (! NILP (FRAME_SCROLL_BARS (frame)))
9568 {
9569 Lisp_Object bar;
9570 bar = FRAME_SCROLL_BARS (frame);
9571 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9572 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9573 XSCROLL_BAR (bar)->prev = Qnil;
9574 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9575 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9576 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9577 }
9578 }
9579
9580
9581 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9582 Note that WINDOW isn't necessarily condemned at all. */
9583
9584 static void
9585 XTredeem_scroll_bar (window)
9586 struct window *window;
9587 {
9588 struct scroll_bar *bar;
9589 struct frame *f;
9590
9591 /* We can't redeem this window's scroll bar if it doesn't have one. */
9592 if (NILP (window->vertical_scroll_bar))
9593 abort ();
9594
9595 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9596
9597 /* Unlink it from the condemned list. */
9598 f = XFRAME (WINDOW_FRAME (window));
9599 if (NILP (bar->prev))
9600 {
9601 /* If the prev pointer is nil, it must be the first in one of
9602 the lists. */
9603 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9604 /* It's not condemned. Everything's fine. */
9605 return;
9606 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9607 window->vertical_scroll_bar))
9608 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9609 else
9610 /* If its prev pointer is nil, it must be at the front of
9611 one or the other! */
9612 abort ();
9613 }
9614 else
9615 XSCROLL_BAR (bar->prev)->next = bar->next;
9616
9617 if (! NILP (bar->next))
9618 XSCROLL_BAR (bar->next)->prev = bar->prev;
9619
9620 bar->next = FRAME_SCROLL_BARS (f);
9621 bar->prev = Qnil;
9622 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9623 if (! NILP (bar->next))
9624 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9625 }
9626
9627 /* Remove all scroll bars on FRAME that haven't been saved since the
9628 last call to `*condemn_scroll_bars_hook'. */
9629
9630 static void
9631 XTjudge_scroll_bars (f)
9632 FRAME_PTR f;
9633 {
9634 Lisp_Object bar, next;
9635
9636 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9637
9638 /* Clear out the condemned list now so we won't try to process any
9639 more events on the hapless scroll bars. */
9640 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9641
9642 for (; ! NILP (bar); bar = next)
9643 {
9644 struct scroll_bar *b = XSCROLL_BAR (bar);
9645
9646 x_scroll_bar_remove (b);
9647
9648 next = b->next;
9649 b->next = b->prev = Qnil;
9650 }
9651
9652 /* Now there should be no references to the condemned scroll bars,
9653 and they should get garbage-collected. */
9654 }
9655
9656
9657 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9658 is a no-op when using toolkit scroll bars.
9659
9660 This may be called from a signal handler, so we have to ignore GC
9661 mark bits. */
9662
9663 static void
9664 x_scroll_bar_expose (bar, event)
9665 struct scroll_bar *bar;
9666 XEvent *event;
9667 {
9668 #ifndef USE_TOOLKIT_SCROLL_BARS
9669
9670 Window w = SCROLL_BAR_X_WINDOW (bar);
9671 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9672 GC gc = f->output_data.x->normal_gc;
9673 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9674
9675 BLOCK_INPUT;
9676
9677 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9678
9679 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9680 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9681
9682 /* x, y, width, height */
9683 0, 0,
9684 XINT (bar->width) - 1 - width_trim - width_trim,
9685 XINT (bar->height) - 1);
9686
9687 UNBLOCK_INPUT;
9688
9689 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9690 }
9691
9692 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9693 is set to something other than NO_EVENT, it is enqueued.
9694
9695 This may be called from a signal handler, so we have to ignore GC
9696 mark bits. */
9697
9698 #ifndef USE_TOOLKIT_SCROLL_BARS
9699
9700 static void
9701 x_scroll_bar_handle_click (bar, event, emacs_event)
9702 struct scroll_bar *bar;
9703 XEvent *event;
9704 struct input_event *emacs_event;
9705 {
9706 if (! GC_WINDOWP (bar->window))
9707 abort ();
9708
9709 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
9710 emacs_event->code = event->xbutton.button - Button1;
9711 emacs_event->modifiers
9712 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9713 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9714 event->xbutton.state)
9715 | (event->type == ButtonRelease
9716 ? up_modifier
9717 : down_modifier));
9718 emacs_event->frame_or_window = bar->window;
9719 emacs_event->arg = Qnil;
9720 emacs_event->timestamp = event->xbutton.time;
9721 {
9722 #if 0
9723 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9724 int internal_height
9725 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9726 #endif
9727 int top_range
9728 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9729 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9730
9731 if (y < 0) y = 0;
9732 if (y > top_range) y = top_range;
9733
9734 if (y < XINT (bar->start))
9735 emacs_event->part = scroll_bar_above_handle;
9736 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9737 emacs_event->part = scroll_bar_handle;
9738 else
9739 emacs_event->part = scroll_bar_below_handle;
9740
9741 /* Just because the user has clicked on the handle doesn't mean
9742 they want to drag it. Lisp code needs to be able to decide
9743 whether or not we're dragging. */
9744 #if 0
9745 /* If the user has just clicked on the handle, record where they're
9746 holding it. */
9747 if (event->type == ButtonPress
9748 && emacs_event->part == scroll_bar_handle)
9749 XSETINT (bar->dragging, y - XINT (bar->start));
9750 #endif
9751
9752 /* If the user has released the handle, set it to its final position. */
9753 if (event->type == ButtonRelease
9754 && ! NILP (bar->dragging))
9755 {
9756 int new_start = y - XINT (bar->dragging);
9757 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9758
9759 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9760 bar->dragging = Qnil;
9761 }
9762
9763 /* Same deal here as the other #if 0. */
9764 #if 0
9765 /* Clicks on the handle are always reported as occurring at the top of
9766 the handle. */
9767 if (emacs_event->part == scroll_bar_handle)
9768 emacs_event->x = bar->start;
9769 else
9770 XSETINT (emacs_event->x, y);
9771 #else
9772 XSETINT (emacs_event->x, y);
9773 #endif
9774
9775 XSETINT (emacs_event->y, top_range);
9776 }
9777 }
9778
9779 /* Handle some mouse motion while someone is dragging the scroll bar.
9780
9781 This may be called from a signal handler, so we have to ignore GC
9782 mark bits. */
9783
9784 static void
9785 x_scroll_bar_note_movement (bar, event)
9786 struct scroll_bar *bar;
9787 XEvent *event;
9788 {
9789 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9790
9791 last_mouse_movement_time = event->xmotion.time;
9792
9793 f->mouse_moved = 1;
9794 XSETVECTOR (last_mouse_scroll_bar, bar);
9795
9796 /* If we're dragging the bar, display it. */
9797 if (! GC_NILP (bar->dragging))
9798 {
9799 /* Where should the handle be now? */
9800 int new_start = event->xmotion.y - XINT (bar->dragging);
9801
9802 if (new_start != XINT (bar->start))
9803 {
9804 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9805
9806 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9807 }
9808 }
9809 }
9810
9811 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9812
9813 /* Return information to the user about the current position of the mouse
9814 on the scroll bar. */
9815
9816 static void
9817 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9818 FRAME_PTR *fp;
9819 Lisp_Object *bar_window;
9820 enum scroll_bar_part *part;
9821 Lisp_Object *x, *y;
9822 unsigned long *time;
9823 {
9824 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9825 Window w = SCROLL_BAR_X_WINDOW (bar);
9826 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9827 int win_x, win_y;
9828 Window dummy_window;
9829 int dummy_coord;
9830 unsigned int dummy_mask;
9831
9832 BLOCK_INPUT;
9833
9834 /* Get the mouse's position relative to the scroll bar window, and
9835 report that. */
9836 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9837
9838 /* Root, child, root x and root y. */
9839 &dummy_window, &dummy_window,
9840 &dummy_coord, &dummy_coord,
9841
9842 /* Position relative to scroll bar. */
9843 &win_x, &win_y,
9844
9845 /* Mouse buttons and modifier keys. */
9846 &dummy_mask))
9847 ;
9848 else
9849 {
9850 #if 0
9851 int inside_height
9852 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9853 #endif
9854 int top_range
9855 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9856
9857 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9858
9859 if (! NILP (bar->dragging))
9860 win_y -= XINT (bar->dragging);
9861
9862 if (win_y < 0)
9863 win_y = 0;
9864 if (win_y > top_range)
9865 win_y = top_range;
9866
9867 *fp = f;
9868 *bar_window = bar->window;
9869
9870 if (! NILP (bar->dragging))
9871 *part = scroll_bar_handle;
9872 else if (win_y < XINT (bar->start))
9873 *part = scroll_bar_above_handle;
9874 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9875 *part = scroll_bar_handle;
9876 else
9877 *part = scroll_bar_below_handle;
9878
9879 XSETINT (*x, win_y);
9880 XSETINT (*y, top_range);
9881
9882 f->mouse_moved = 0;
9883 last_mouse_scroll_bar = Qnil;
9884 }
9885
9886 *time = last_mouse_movement_time;
9887
9888 UNBLOCK_INPUT;
9889 }
9890
9891
9892 /* The screen has been cleared so we may have changed foreground or
9893 background colors, and the scroll bars may need to be redrawn.
9894 Clear out the scroll bars, and ask for expose events, so we can
9895 redraw them. */
9896
9897 void
9898 x_scroll_bar_clear (f)
9899 FRAME_PTR f;
9900 {
9901 #ifndef USE_TOOLKIT_SCROLL_BARS
9902 Lisp_Object bar;
9903
9904 /* We can have scroll bars even if this is 0,
9905 if we just turned off scroll bar mode.
9906 But in that case we should not clear them. */
9907 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9908 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9909 bar = XSCROLL_BAR (bar)->next)
9910 XClearArea (FRAME_X_DISPLAY (f),
9911 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9912 0, 0, 0, 0, True);
9913 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9914 }
9915
9916 /* This processes Expose events from the menu-bar specific X event
9917 loop in xmenu.c. This allows to redisplay the frame if necessary
9918 when handling menu-bar or pop-up items. */
9919
9920 int
9921 process_expose_from_menu (event)
9922 XEvent event;
9923 {
9924 FRAME_PTR f;
9925 struct x_display_info *dpyinfo;
9926 int frame_exposed_p = 0;
9927
9928 BLOCK_INPUT;
9929
9930 dpyinfo = x_display_info_for_display (event.xexpose.display);
9931 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9932 if (f)
9933 {
9934 if (f->async_visible == 0)
9935 {
9936 f->async_visible = 1;
9937 f->async_iconified = 0;
9938 f->output_data.x->has_been_visible = 1;
9939 SET_FRAME_GARBAGED (f);
9940 }
9941 else
9942 {
9943 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9944 event.xexpose.x, event.xexpose.y,
9945 event.xexpose.width, event.xexpose.height);
9946 frame_exposed_p = 1;
9947 }
9948 }
9949 else
9950 {
9951 struct scroll_bar *bar
9952 = x_window_to_scroll_bar (event.xexpose.window);
9953
9954 if (bar)
9955 x_scroll_bar_expose (bar, &event);
9956 }
9957
9958 UNBLOCK_INPUT;
9959 return frame_exposed_p;
9960 }
9961 \f
9962 /* Define a queue to save up SelectionRequest events for later handling. */
9963
9964 struct selection_event_queue
9965 {
9966 XEvent event;
9967 struct selection_event_queue *next;
9968 };
9969
9970 static struct selection_event_queue *queue;
9971
9972 /* Nonzero means queue up certain events--don't process them yet. */
9973
9974 static int x_queue_selection_requests;
9975
9976 /* Queue up an X event *EVENT, to be processed later. */
9977
9978 static void
9979 x_queue_event (f, event)
9980 FRAME_PTR f;
9981 XEvent *event;
9982 {
9983 struct selection_event_queue *queue_tmp
9984 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9985
9986 if (queue_tmp != NULL)
9987 {
9988 queue_tmp->event = *event;
9989 queue_tmp->next = queue;
9990 queue = queue_tmp;
9991 }
9992 }
9993
9994 /* Take all the queued events and put them back
9995 so that they get processed afresh. */
9996
9997 static void
9998 x_unqueue_events (display)
9999 Display *display;
10000 {
10001 while (queue != NULL)
10002 {
10003 struct selection_event_queue *queue_tmp = queue;
10004 XPutBackEvent (display, &queue_tmp->event);
10005 queue = queue_tmp->next;
10006 xfree ((char *)queue_tmp);
10007 }
10008 }
10009
10010 /* Start queuing SelectionRequest events. */
10011
10012 void
10013 x_start_queuing_selection_requests (display)
10014 Display *display;
10015 {
10016 x_queue_selection_requests++;
10017 }
10018
10019 /* Stop queuing SelectionRequest events. */
10020
10021 void
10022 x_stop_queuing_selection_requests (display)
10023 Display *display;
10024 {
10025 x_queue_selection_requests--;
10026 x_unqueue_events (display);
10027 }
10028 \f
10029 /* The main X event-reading loop - XTread_socket. */
10030
10031 #if 0
10032 /* Time stamp of enter window event. This is only used by XTread_socket,
10033 but we have to put it out here, since static variables within functions
10034 sometimes don't work. */
10035
10036 static Time enter_timestamp;
10037 #endif
10038
10039 /* This holds the state XLookupString needs to implement dead keys
10040 and other tricks known as "compose processing". _X Window System_
10041 says that a portable program can't use this, but Stephen Gildea assures
10042 me that letting the compiler initialize it to zeros will work okay.
10043
10044 This must be defined outside of XTread_socket, for the same reasons
10045 given for enter_timestamp, above. */
10046
10047 static XComposeStatus compose_status;
10048
10049 /* Record the last 100 characters stored
10050 to help debug the loss-of-chars-during-GC problem. */
10051
10052 static int temp_index;
10053 static short temp_buffer[100];
10054
10055 /* Set this to nonzero to fake an "X I/O error"
10056 on a particular display. */
10057
10058 struct x_display_info *XTread_socket_fake_io_error;
10059
10060 /* When we find no input here, we occasionally do a no-op command
10061 to verify that the X server is still running and we can still talk with it.
10062 We try all the open displays, one by one.
10063 This variable is used for cycling thru the displays. */
10064
10065 static struct x_display_info *next_noop_dpyinfo;
10066
10067 #define SET_SAVED_MENU_EVENT(size) \
10068 do \
10069 { \
10070 if (f->output_data.x->saved_menu_event == 0) \
10071 f->output_data.x->saved_menu_event \
10072 = (XEvent *) xmalloc (sizeof (XEvent)); \
10073 bcopy (&event, f->output_data.x->saved_menu_event, size); \
10074 if (numchars >= 1) \
10075 { \
10076 bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
10077 XSETFRAME (bufp->frame_or_window, f); \
10078 bufp->arg = Qnil; \
10079 bufp++; \
10080 count++; \
10081 numchars--; \
10082 } \
10083 } \
10084 while (0)
10085
10086 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
10087 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
10088
10089 /* Read events coming from the X server.
10090 This routine is called by the SIGIO handler.
10091 We return as soon as there are no more events to be read.
10092
10093 Events representing keys are stored in buffer BUFP,
10094 which can hold up to NUMCHARS characters.
10095 We return the number of characters stored into the buffer,
10096 thus pretending to be `read'.
10097
10098 EXPECTED is nonzero if the caller knows input is available. */
10099
10100 static int
10101 XTread_socket (sd, bufp, numchars, expected)
10102 register int sd;
10103 /* register */ struct input_event *bufp;
10104 /* register */ int numchars;
10105 int expected;
10106 {
10107 int count = 0;
10108 int nbytes = 0;
10109 XEvent event;
10110 struct frame *f;
10111 int event_found = 0;
10112 struct x_display_info *dpyinfo;
10113 struct coding_system coding;
10114
10115 if (interrupt_input_blocked)
10116 {
10117 interrupt_input_pending = 1;
10118 return -1;
10119 }
10120
10121 interrupt_input_pending = 0;
10122 BLOCK_INPUT;
10123
10124 /* So people can tell when we have read the available input. */
10125 input_signal_count++;
10126
10127 if (numchars <= 0)
10128 abort (); /* Don't think this happens. */
10129
10130 ++handling_signal;
10131
10132 /* Find the display we are supposed to read input for.
10133 It's the one communicating on descriptor SD. */
10134 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
10135 {
10136 #if 0 /* This ought to be unnecessary; let's verify it. */
10137 #ifdef FIOSNBIO
10138 /* If available, Xlib uses FIOSNBIO to make the socket
10139 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
10140 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
10141 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
10142 fcntl (dpyinfo->connection, F_SETFL, 0);
10143 #endif /* ! defined (FIOSNBIO) */
10144 #endif
10145
10146 #if 0 /* This code can't be made to work, with multiple displays,
10147 and appears not to be used on any system any more.
10148 Also keyboard.c doesn't turn O_NDELAY on and off
10149 for X connections. */
10150 #ifndef SIGIO
10151 #ifndef HAVE_SELECT
10152 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
10153 {
10154 extern int read_alarm_should_throw;
10155 read_alarm_should_throw = 1;
10156 XPeekEvent (dpyinfo->display, &event);
10157 read_alarm_should_throw = 0;
10158 }
10159 #endif /* HAVE_SELECT */
10160 #endif /* SIGIO */
10161 #endif
10162
10163 /* For debugging, this gives a way to fake an I/O error. */
10164 if (dpyinfo == XTread_socket_fake_io_error)
10165 {
10166 XTread_socket_fake_io_error = 0;
10167 x_io_error_quitter (dpyinfo->display);
10168 }
10169
10170 #ifdef HAVE_X_SM
10171 BLOCK_INPUT;
10172 count += x_session_check_input (bufp, &numchars);
10173 UNBLOCK_INPUT;
10174 #endif
10175
10176 while (XPending (dpyinfo->display))
10177 {
10178 XNextEvent (dpyinfo->display, &event);
10179
10180 #ifdef HAVE_X_I18N
10181 {
10182 /* Filter events for the current X input method.
10183 XFilterEvent returns non-zero if the input method has
10184 consumed the event. We pass the frame's X window to
10185 XFilterEvent because that's the one for which the IC
10186 was created. */
10187 struct frame *f1 = x_any_window_to_frame (dpyinfo,
10188 event.xclient.window);
10189 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
10190 break;
10191 }
10192 #endif
10193 event_found = 1;
10194
10195 switch (event.type)
10196 {
10197 case ClientMessage:
10198 {
10199 if (event.xclient.message_type
10200 == dpyinfo->Xatom_wm_protocols
10201 && event.xclient.format == 32)
10202 {
10203 if (event.xclient.data.l[0]
10204 == dpyinfo->Xatom_wm_take_focus)
10205 {
10206 /* Use x_any_window_to_frame because this
10207 could be the shell widget window
10208 if the frame has no title bar. */
10209 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10210 #ifdef HAVE_X_I18N
10211 /* Not quite sure this is needed -pd */
10212 if (f && FRAME_XIC (f))
10213 XSetICFocus (FRAME_XIC (f));
10214 #endif
10215 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10216 instructs the WM to set the input focus automatically for
10217 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10218 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10219 it has set the focus. So, XSetInputFocus below is not
10220 needed.
10221
10222 The call to XSetInputFocus below has also caused trouble. In
10223 cases where the XSetInputFocus done by the WM and the one
10224 below are temporally close (on a fast machine), the call
10225 below can generate additional FocusIn events which confuse
10226 Emacs. */
10227
10228 /* Since we set WM_TAKE_FOCUS, we must call
10229 XSetInputFocus explicitly. But not if f is null,
10230 since that might be an event for a deleted frame. */
10231 if (f)
10232 {
10233 Display *d = event.xclient.display;
10234 /* Catch and ignore errors, in case window has been
10235 iconified by a window manager such as GWM. */
10236 int count = x_catch_errors (d);
10237 XSetInputFocus (d, event.xclient.window,
10238 /* The ICCCM says this is
10239 the only valid choice. */
10240 RevertToParent,
10241 event.xclient.data.l[1]);
10242 /* This is needed to detect the error
10243 if there is an error. */
10244 XSync (d, False);
10245 x_uncatch_errors (d, count);
10246 }
10247 /* Not certain about handling scroll bars here */
10248 #endif /* 0 */
10249 }
10250 else if (event.xclient.data.l[0]
10251 == dpyinfo->Xatom_wm_save_yourself)
10252 {
10253 /* Save state modify the WM_COMMAND property to
10254 something which can reinstate us. This notifies
10255 the session manager, who's looking for such a
10256 PropertyNotify. Can restart processing when
10257 a keyboard or mouse event arrives. */
10258 /* If we have a session manager, don't set this.
10259 KDE will then start two Emacsen, one for the
10260 session manager and one for this. */
10261 if (numchars > 0
10262 #ifdef HAVE_X_SM
10263 && ! x_session_have_connection ()
10264 #endif
10265 )
10266 {
10267 f = x_top_window_to_frame (dpyinfo,
10268 event.xclient.window);
10269 /* This is just so we only give real data once
10270 for a single Emacs process. */
10271 if (f == SELECTED_FRAME ())
10272 XSetCommand (FRAME_X_DISPLAY (f),
10273 event.xclient.window,
10274 initial_argv, initial_argc);
10275 else if (f)
10276 XSetCommand (FRAME_X_DISPLAY (f),
10277 event.xclient.window,
10278 0, 0);
10279 }
10280 }
10281 else if (event.xclient.data.l[0]
10282 == dpyinfo->Xatom_wm_delete_window)
10283 {
10284 struct frame *f
10285 = x_any_window_to_frame (dpyinfo,
10286 event.xclient.window);
10287
10288 if (f)
10289 {
10290 if (numchars == 0)
10291 abort ();
10292
10293 bufp->kind = DELETE_WINDOW_EVENT;
10294 XSETFRAME (bufp->frame_or_window, f);
10295 bufp->arg = Qnil;
10296 bufp++;
10297
10298 count += 1;
10299 numchars -= 1;
10300 }
10301 }
10302 }
10303 else if (event.xclient.message_type
10304 == dpyinfo->Xatom_wm_configure_denied)
10305 {
10306 }
10307 else if (event.xclient.message_type
10308 == dpyinfo->Xatom_wm_window_moved)
10309 {
10310 int new_x, new_y;
10311 struct frame *f
10312 = x_window_to_frame (dpyinfo, event.xclient.window);
10313
10314 new_x = event.xclient.data.s[0];
10315 new_y = event.xclient.data.s[1];
10316
10317 if (f)
10318 {
10319 f->output_data.x->left_pos = new_x;
10320 f->output_data.x->top_pos = new_y;
10321 }
10322 }
10323 #ifdef HACK_EDITRES
10324 else if (event.xclient.message_type
10325 == dpyinfo->Xatom_editres)
10326 {
10327 struct frame *f
10328 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10329 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10330 &event, NULL);
10331 }
10332 #endif /* HACK_EDITRES */
10333 else if ((event.xclient.message_type
10334 == dpyinfo->Xatom_DONE)
10335 || (event.xclient.message_type
10336 == dpyinfo->Xatom_PAGE))
10337 {
10338 /* Ghostview job completed. Kill it. We could
10339 reply with "Next" if we received "Page", but we
10340 currently never do because we are interested in
10341 images, only, which should have 1 page. */
10342 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10343 struct frame *f
10344 = x_window_to_frame (dpyinfo, event.xclient.window);
10345 x_kill_gs_process (pixmap, f);
10346 expose_frame (f, 0, 0, 0, 0);
10347 }
10348 #ifdef USE_TOOLKIT_SCROLL_BARS
10349 /* Scroll bar callbacks send a ClientMessage from which
10350 we construct an input_event. */
10351 else if (event.xclient.message_type
10352 == dpyinfo->Xatom_Scrollbar)
10353 {
10354 x_scroll_bar_to_input_event (&event, bufp);
10355 ++bufp, ++count, --numchars;
10356 goto out;
10357 }
10358 #endif /* USE_TOOLKIT_SCROLL_BARS */
10359 else
10360 goto OTHER;
10361 }
10362 break;
10363
10364 case SelectionNotify:
10365 #ifdef USE_X_TOOLKIT
10366 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10367 goto OTHER;
10368 #endif /* not USE_X_TOOLKIT */
10369 x_handle_selection_notify (&event.xselection);
10370 break;
10371
10372 case SelectionClear: /* Someone has grabbed ownership. */
10373 #ifdef USE_X_TOOLKIT
10374 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10375 goto OTHER;
10376 #endif /* USE_X_TOOLKIT */
10377 {
10378 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10379
10380 if (numchars == 0)
10381 abort ();
10382
10383 bufp->kind = SELECTION_CLEAR_EVENT;
10384 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10385 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10386 SELECTION_EVENT_TIME (bufp) = eventp->time;
10387 bufp->frame_or_window = Qnil;
10388 bufp->arg = Qnil;
10389 bufp++;
10390
10391 count += 1;
10392 numchars -= 1;
10393 }
10394 break;
10395
10396 case SelectionRequest: /* Someone wants our selection. */
10397 #ifdef USE_X_TOOLKIT
10398 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10399 goto OTHER;
10400 #endif /* USE_X_TOOLKIT */
10401 if (x_queue_selection_requests)
10402 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10403 &event);
10404 else
10405 {
10406 XSelectionRequestEvent *eventp
10407 = (XSelectionRequestEvent *) &event;
10408
10409 if (numchars == 0)
10410 abort ();
10411
10412 bufp->kind = SELECTION_REQUEST_EVENT;
10413 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10414 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10415 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10416 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10417 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10418 SELECTION_EVENT_TIME (bufp) = eventp->time;
10419 bufp->frame_or_window = Qnil;
10420 bufp->arg = Qnil;
10421 bufp++;
10422
10423 count += 1;
10424 numchars -= 1;
10425 }
10426 break;
10427
10428 case PropertyNotify:
10429 #if 0 /* This is plain wrong. In the case that we are waiting for a
10430 PropertyNotify used as an ACK in incremental selection
10431 transfer, the property will be on the receiver's window. */
10432 #if defined USE_X_TOOLKIT
10433 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10434 goto OTHER;
10435 #endif
10436 #endif
10437 x_handle_property_notify (&event.xproperty);
10438 goto OTHER;
10439
10440 case ReparentNotify:
10441 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10442 if (f)
10443 {
10444 int x, y;
10445 f->output_data.x->parent_desc = event.xreparent.parent;
10446 x_real_positions (f, &x, &y);
10447 f->output_data.x->left_pos = x;
10448 f->output_data.x->top_pos = y;
10449 goto OTHER;
10450 }
10451 break;
10452
10453 case Expose:
10454 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10455 if (f)
10456 {
10457 x_check_fullscreen (f);
10458
10459 if (f->async_visible == 0)
10460 {
10461 f->async_visible = 1;
10462 f->async_iconified = 0;
10463 f->output_data.x->has_been_visible = 1;
10464 SET_FRAME_GARBAGED (f);
10465 }
10466 else
10467 expose_frame (x_window_to_frame (dpyinfo,
10468 event.xexpose.window),
10469 event.xexpose.x, event.xexpose.y,
10470 event.xexpose.width, event.xexpose.height);
10471 }
10472 else
10473 {
10474 #ifndef USE_TOOLKIT_SCROLL_BARS
10475 struct scroll_bar *bar;
10476 #endif
10477 #if defined USE_LUCID
10478 /* Submenus of the Lucid menu bar aren't widgets
10479 themselves, so there's no way to dispatch events
10480 to them. Recognize this case separately. */
10481 {
10482 Widget widget
10483 = x_window_to_menu_bar (event.xexpose.window);
10484 if (widget)
10485 xlwmenu_redisplay (widget);
10486 }
10487 #endif /* USE_LUCID */
10488
10489 #ifdef USE_TOOLKIT_SCROLL_BARS
10490 /* Dispatch event to the widget. */
10491 goto OTHER;
10492 #else /* not USE_TOOLKIT_SCROLL_BARS */
10493 bar = x_window_to_scroll_bar (event.xexpose.window);
10494
10495 if (bar)
10496 x_scroll_bar_expose (bar, &event);
10497 #ifdef USE_X_TOOLKIT
10498 else
10499 goto OTHER;
10500 #endif /* USE_X_TOOLKIT */
10501 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10502 }
10503 break;
10504
10505 case GraphicsExpose: /* This occurs when an XCopyArea's
10506 source area was obscured or not
10507 available. */
10508 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10509 if (f)
10510 {
10511 expose_frame (f,
10512 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10513 event.xgraphicsexpose.width,
10514 event.xgraphicsexpose.height);
10515 }
10516 #ifdef USE_X_TOOLKIT
10517 else
10518 goto OTHER;
10519 #endif /* USE_X_TOOLKIT */
10520 break;
10521
10522 case NoExpose: /* This occurs when an XCopyArea's
10523 source area was completely
10524 available. */
10525 break;
10526
10527 case UnmapNotify:
10528 /* Redo the mouse-highlight after the tooltip has gone. */
10529 if (event.xmap.window == tip_window)
10530 {
10531 tip_window = 0;
10532 redo_mouse_highlight ();
10533 }
10534
10535 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10536 if (f) /* F may no longer exist if
10537 the frame was deleted. */
10538 {
10539 /* While a frame is unmapped, display generation is
10540 disabled; you don't want to spend time updating a
10541 display that won't ever be seen. */
10542 f->async_visible = 0;
10543 /* We can't distinguish, from the event, whether the window
10544 has become iconified or invisible. So assume, if it
10545 was previously visible, than now it is iconified.
10546 But x_make_frame_invisible clears both
10547 the visible flag and the iconified flag;
10548 and that way, we know the window is not iconified now. */
10549 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10550 {
10551 f->async_iconified = 1;
10552
10553 bufp->kind = ICONIFY_EVENT;
10554 XSETFRAME (bufp->frame_or_window, f);
10555 bufp->arg = Qnil;
10556 bufp++;
10557 count++;
10558 numchars--;
10559 }
10560 }
10561 goto OTHER;
10562
10563 case MapNotify:
10564 if (event.xmap.window == tip_window)
10565 /* The tooltip has been drawn already. Avoid
10566 the SET_FRAME_GARBAGED below. */
10567 goto OTHER;
10568
10569 /* We use x_top_window_to_frame because map events can
10570 come for sub-windows and they don't mean that the
10571 frame is visible. */
10572 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10573 if (f)
10574 {
10575 f->async_visible = 1;
10576 f->async_iconified = 0;
10577 f->output_data.x->has_been_visible = 1;
10578
10579 /* wait_reading_process_input will notice this and update
10580 the frame's display structures. */
10581 SET_FRAME_GARBAGED (f);
10582
10583 if (f->iconified)
10584 {
10585 bufp->kind = DEICONIFY_EVENT;
10586 XSETFRAME (bufp->frame_or_window, f);
10587 bufp->arg = Qnil;
10588 bufp++;
10589 count++;
10590 numchars--;
10591 }
10592 else if (! NILP (Vframe_list)
10593 && ! NILP (XCDR (Vframe_list)))
10594 /* Force a redisplay sooner or later
10595 to update the frame titles
10596 in case this is the second frame. */
10597 record_asynch_buffer_change ();
10598 }
10599 goto OTHER;
10600
10601 case KeyPress:
10602
10603 /* Dispatch KeyPress events when in menu. */
10604 if (popup_activated_flag)
10605 goto OTHER;
10606
10607 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10608
10609 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10610 {
10611 dpyinfo->mouse_face_hidden = 1;
10612 clear_mouse_face (dpyinfo);
10613 }
10614
10615 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10616 if (f == 0)
10617 {
10618 /* Scroll bars consume key events, but we want
10619 the keys to go to the scroll bar's frame. */
10620 Widget widget = XtWindowToWidget (dpyinfo->display,
10621 event.xkey.window);
10622 if (widget && XmIsScrollBar (widget))
10623 {
10624 widget = XtParent (widget);
10625 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10626 }
10627 }
10628 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10629
10630 if (f != 0)
10631 {
10632 KeySym keysym, orig_keysym;
10633 /* al%imercury@uunet.uu.net says that making this 81
10634 instead of 80 fixed a bug whereby meta chars made
10635 his Emacs hang.
10636
10637 It seems that some version of XmbLookupString has
10638 a bug of not returning XBufferOverflow in
10639 status_return even if the input is too long to
10640 fit in 81 bytes. So, we must prepare sufficient
10641 bytes for copy_buffer. 513 bytes (256 chars for
10642 two-byte character set) seems to be a fairly good
10643 approximation. -- 2000.8.10 handa@etl.go.jp */
10644 unsigned char copy_buffer[513];
10645 unsigned char *copy_bufptr = copy_buffer;
10646 int copy_bufsiz = sizeof (copy_buffer);
10647 int modifiers;
10648 Lisp_Object coding_system = Qlatin_1;
10649
10650 event.xkey.state
10651 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10652 extra_keyboard_modifiers);
10653 modifiers = event.xkey.state;
10654
10655 /* This will have to go some day... */
10656
10657 /* make_lispy_event turns chars into control chars.
10658 Don't do it here because XLookupString is too eager. */
10659 event.xkey.state &= ~ControlMask;
10660 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10661 | dpyinfo->super_mod_mask
10662 | dpyinfo->hyper_mod_mask
10663 | dpyinfo->alt_mod_mask);
10664
10665 /* In case Meta is ComposeCharacter,
10666 clear its status. According to Markus Ehrnsperger
10667 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10668 this enables ComposeCharacter to work whether or
10669 not it is combined with Meta. */
10670 if (modifiers & dpyinfo->meta_mod_mask)
10671 bzero (&compose_status, sizeof (compose_status));
10672
10673 #ifdef HAVE_X_I18N
10674 if (FRAME_XIC (f))
10675 {
10676 Status status_return;
10677
10678 coding_system = Vlocale_coding_system;
10679 nbytes = XmbLookupString (FRAME_XIC (f),
10680 &event.xkey, copy_bufptr,
10681 copy_bufsiz, &keysym,
10682 &status_return);
10683 if (status_return == XBufferOverflow)
10684 {
10685 copy_bufsiz = nbytes + 1;
10686 copy_bufptr = (char *) alloca (copy_bufsiz);
10687 nbytes = XmbLookupString (FRAME_XIC (f),
10688 &event.xkey, copy_bufptr,
10689 copy_bufsiz, &keysym,
10690 &status_return);
10691 }
10692 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10693 #if 0 && defined X_HAVE_UTF8_STRING
10694 else if (status_return == XLookupKeySym)
10695 { /* Try again but with utf-8. */
10696 coding_system = Qutf_8;
10697 nbytes = Xutf8LookupString (FRAME_XIC (f),
10698 &event.xkey, copy_bufptr,
10699 copy_bufsiz, &keysym,
10700 &status_return);
10701 if (status_return == XBufferOverflow)
10702 {
10703 copy_bufsiz = nbytes + 1;
10704 copy_bufptr = (char *) alloca (copy_bufsiz);
10705 nbytes = Xutf8LookupString (FRAME_XIC (f),
10706 &event.xkey,
10707 copy_bufptr,
10708 copy_bufsiz, &keysym,
10709 &status_return);
10710 }
10711 }
10712 #endif
10713
10714 if (status_return == XLookupNone)
10715 break;
10716 else if (status_return == XLookupChars)
10717 {
10718 keysym = NoSymbol;
10719 modifiers = 0;
10720 }
10721 else if (status_return != XLookupKeySym
10722 && status_return != XLookupBoth)
10723 abort ();
10724 }
10725 else
10726 nbytes = XLookupString (&event.xkey, copy_bufptr,
10727 copy_bufsiz, &keysym,
10728 &compose_status);
10729 #else
10730 nbytes = XLookupString (&event.xkey, copy_bufptr,
10731 copy_bufsiz, &keysym,
10732 &compose_status);
10733 #endif
10734
10735 orig_keysym = keysym;
10736
10737 if (numchars > 1)
10738 {
10739 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10740 || keysym == XK_Delete
10741 #ifdef XK_ISO_Left_Tab
10742 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10743 #endif
10744 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10745 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10746 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10747 #ifdef HPUX
10748 /* This recognizes the "extended function keys".
10749 It seems there's no cleaner way.
10750 Test IsModifierKey to avoid handling mode_switch
10751 incorrectly. */
10752 || ((unsigned) (keysym) >= XK_Select
10753 && (unsigned)(keysym) < XK_KP_Space)
10754 #endif
10755 #ifdef XK_dead_circumflex
10756 || orig_keysym == XK_dead_circumflex
10757 #endif
10758 #ifdef XK_dead_grave
10759 || orig_keysym == XK_dead_grave
10760 #endif
10761 #ifdef XK_dead_tilde
10762 || orig_keysym == XK_dead_tilde
10763 #endif
10764 #ifdef XK_dead_diaeresis
10765 || orig_keysym == XK_dead_diaeresis
10766 #endif
10767 #ifdef XK_dead_macron
10768 || orig_keysym == XK_dead_macron
10769 #endif
10770 #ifdef XK_dead_degree
10771 || orig_keysym == XK_dead_degree
10772 #endif
10773 #ifdef XK_dead_acute
10774 || orig_keysym == XK_dead_acute
10775 #endif
10776 #ifdef XK_dead_cedilla
10777 || orig_keysym == XK_dead_cedilla
10778 #endif
10779 #ifdef XK_dead_breve
10780 || orig_keysym == XK_dead_breve
10781 #endif
10782 #ifdef XK_dead_ogonek
10783 || orig_keysym == XK_dead_ogonek
10784 #endif
10785 #ifdef XK_dead_caron
10786 || orig_keysym == XK_dead_caron
10787 #endif
10788 #ifdef XK_dead_doubleacute
10789 || orig_keysym == XK_dead_doubleacute
10790 #endif
10791 #ifdef XK_dead_abovedot
10792 || orig_keysym == XK_dead_abovedot
10793 #endif
10794 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10795 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10796 /* Any "vendor-specific" key is ok. */
10797 || (orig_keysym & (1 << 28))
10798 || (keysym != NoSymbol && nbytes == 0))
10799 && ! (IsModifierKey (orig_keysym)
10800 #ifndef HAVE_X11R5
10801 #ifdef XK_Mode_switch
10802 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10803 #endif
10804 #ifdef XK_Num_Lock
10805 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10806 #endif
10807 #endif /* not HAVE_X11R5 */
10808 /* The symbols from XK_ISO_Lock to
10809 XK_ISO_Last_Group_Lock doesn't have real
10810 modifiers but should be treated similarly
10811 to Mode_switch by Emacs. */
10812 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10813 || ((unsigned)(orig_keysym) >= XK_ISO_Lock
10814 && (unsigned)(orig_keysym) <= XK_ISO_Last_Group_Lock)
10815 #endif
10816 ))
10817 {
10818 if (temp_index == sizeof temp_buffer / sizeof (short))
10819 temp_index = 0;
10820 temp_buffer[temp_index++] = keysym;
10821 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
10822 bufp->code = keysym;
10823 XSETFRAME (bufp->frame_or_window, f);
10824 bufp->arg = Qnil;
10825 bufp->modifiers
10826 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10827 modifiers);
10828 bufp->timestamp = event.xkey.time;
10829 bufp++;
10830 count++;
10831 numchars--;
10832 }
10833 else if (numchars > nbytes)
10834 {
10835 register int i;
10836 register int c;
10837 int nchars, len;
10838
10839 /* The input should be decoded with `coding_system'
10840 which depends on which X*LookupString function
10841 we used just above and the locale. */
10842 setup_coding_system (coding_system, &coding);
10843 coding.src_multibyte = 0;
10844 coding.dst_multibyte = 1;
10845 /* The input is converted to events, thus we can't
10846 handle composition. Anyway, there's no XIM that
10847 gives us composition information. */
10848 coding.composing = COMPOSITION_DISABLED;
10849
10850 for (i = 0; i < nbytes; i++)
10851 {
10852 if (temp_index == (sizeof temp_buffer
10853 / sizeof (short)))
10854 temp_index = 0;
10855 temp_buffer[temp_index++] = copy_bufptr[i];
10856 }
10857
10858 {
10859 /* Decode the input data. */
10860 int require;
10861 unsigned char *p;
10862
10863 require = decoding_buffer_size (&coding, nbytes);
10864 p = (unsigned char *) alloca (require);
10865 coding.mode |= CODING_MODE_LAST_BLOCK;
10866 /* We explicitely disable composition
10867 handling because key data should
10868 not contain any composition
10869 sequence. */
10870 coding.composing = COMPOSITION_DISABLED;
10871 decode_coding (&coding, copy_bufptr, p,
10872 nbytes, require);
10873 nbytes = coding.produced;
10874 nchars = coding.produced_char;
10875 copy_bufptr = p;
10876 }
10877
10878 /* Convert the input data to a sequence of
10879 character events. */
10880 for (i = 0; i < nbytes; i += len)
10881 {
10882 if (nchars == nbytes)
10883 c = copy_bufptr[i], len = 1;
10884 else
10885 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10886 nbytes - i, len);
10887
10888 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10889 ? ASCII_KEYSTROKE_EVENT
10890 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10891 bufp->code = c;
10892 XSETFRAME (bufp->frame_or_window, f);
10893 bufp->arg = Qnil;
10894 bufp->modifiers
10895 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10896 modifiers);
10897 bufp->timestamp = event.xkey.time;
10898 bufp++;
10899 }
10900
10901 count += nchars;
10902 numchars -= nchars;
10903
10904 if (keysym == NoSymbol)
10905 break;
10906 }
10907 else
10908 abort ();
10909 }
10910 else
10911 abort ();
10912 }
10913 #ifdef HAVE_X_I18N
10914 /* Don't dispatch this event since XtDispatchEvent calls
10915 XFilterEvent, and two calls in a row may freeze the
10916 client. */
10917 break;
10918 #else
10919 goto OTHER;
10920 #endif
10921
10922 case KeyRelease:
10923 #ifdef HAVE_X_I18N
10924 /* Don't dispatch this event since XtDispatchEvent calls
10925 XFilterEvent, and two calls in a row may freeze the
10926 client. */
10927 break;
10928 #else
10929 goto OTHER;
10930 #endif
10931
10932 case EnterNotify:
10933 {
10934 int n;
10935
10936 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10937 if (n > 0)
10938 {
10939 bufp += n, count += n, numchars -= n;
10940 }
10941
10942 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10943
10944 #if 0
10945 if (event.xcrossing.focus)
10946 {
10947 /* Avoid nasty pop/raise loops. */
10948 if (f && (!(f->auto_raise)
10949 || !(f->auto_lower)
10950 || (event.xcrossing.time - enter_timestamp) > 500))
10951 {
10952 x_new_focus_frame (dpyinfo, f);
10953 enter_timestamp = event.xcrossing.time;
10954 }
10955 }
10956 else if (f == dpyinfo->x_focus_frame)
10957 x_new_focus_frame (dpyinfo, 0);
10958 #endif
10959
10960 /* EnterNotify counts as mouse movement,
10961 so update things that depend on mouse position. */
10962 if (f && !f->output_data.x->hourglass_p)
10963 note_mouse_movement (f, &event.xmotion);
10964 goto OTHER;
10965 }
10966
10967 case FocusIn:
10968 {
10969 int n;
10970
10971 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10972 if (n > 0)
10973 {
10974 bufp += n, count += n, numchars -= n;
10975 }
10976 }
10977
10978 goto OTHER;
10979
10980 case LeaveNotify:
10981 {
10982 int n;
10983
10984 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
10985 if (n > 0)
10986 {
10987 bufp += n, count += n, numchars -= n;
10988 }
10989 }
10990
10991 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10992 if (f)
10993 {
10994 if (f == dpyinfo->mouse_face_mouse_frame)
10995 {
10996 /* If we move outside the frame, then we're
10997 certainly no longer on any text in the frame. */
10998 clear_mouse_face (dpyinfo);
10999 dpyinfo->mouse_face_mouse_frame = 0;
11000 }
11001
11002 /* Generate a nil HELP_EVENT to cancel a help-echo.
11003 Do it only if there's something to cancel.
11004 Otherwise, the startup message is cleared when
11005 the mouse leaves the frame. */
11006 if (any_help_event_p)
11007 {
11008 Lisp_Object frame;
11009 int n;
11010
11011 XSETFRAME (frame, f);
11012 help_echo = Qnil;
11013 n = gen_help_event (bufp, numchars,
11014 Qnil, frame, Qnil, Qnil, 0);
11015 bufp += n, count += n, numchars -= n;
11016 }
11017
11018 }
11019 goto OTHER;
11020
11021 case FocusOut:
11022 {
11023 int n;
11024
11025 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11026 if (n > 0)
11027 {
11028 bufp += n, count += n, numchars -= n;
11029 }
11030 }
11031
11032 goto OTHER;
11033
11034 case MotionNotify:
11035 {
11036 previous_help_echo = help_echo;
11037 help_echo = help_echo_object = help_echo_window = Qnil;
11038 help_echo_pos = -1;
11039
11040 if (dpyinfo->grabbed && last_mouse_frame
11041 && FRAME_LIVE_P (last_mouse_frame))
11042 f = last_mouse_frame;
11043 else
11044 f = x_window_to_frame (dpyinfo, event.xmotion.window);
11045
11046 if (dpyinfo->mouse_face_hidden)
11047 {
11048 dpyinfo->mouse_face_hidden = 0;
11049 clear_mouse_face (dpyinfo);
11050 }
11051
11052 if (f)
11053 {
11054
11055 /* Generate SELECT_WINDOW_EVENTs when needed. */
11056 if (mouse_autoselect_window)
11057 {
11058 Lisp_Object window;
11059 int area;
11060
11061 window = window_from_coordinates (f,
11062 event.xmotion.x, event.xmotion.y,
11063 &area, 0);
11064
11065 /* Window will be selected only when it is not selected now and
11066 last mouse movement event was not in it. Minibuffer window
11067 will be selected iff it is active. */
11068 if (WINDOWP(window)
11069 && !EQ (window, last_window)
11070 && !EQ (window, selected_window)
11071 && numchars > 0)
11072 {
11073 bufp->kind = SELECT_WINDOW_EVENT;
11074 bufp->frame_or_window = window;
11075 bufp->arg = Qnil;
11076 ++bufp, ++count, --numchars;
11077 }
11078
11079 last_window=window;
11080 }
11081 note_mouse_movement (f, &event.xmotion);
11082 }
11083 else
11084 {
11085 #ifndef USE_TOOLKIT_SCROLL_BARS
11086 struct scroll_bar *bar
11087 = x_window_to_scroll_bar (event.xmotion.window);
11088
11089 if (bar)
11090 x_scroll_bar_note_movement (bar, &event);
11091 #endif /* USE_TOOLKIT_SCROLL_BARS */
11092
11093 /* If we move outside the frame, then we're
11094 certainly no longer on any text in the frame. */
11095 clear_mouse_face (dpyinfo);
11096 }
11097
11098 /* If the contents of the global variable help_echo
11099 has changed, generate a HELP_EVENT. */
11100 if (!NILP (help_echo)
11101 || !NILP (previous_help_echo))
11102 {
11103 Lisp_Object frame;
11104 int n;
11105
11106 if (f)
11107 XSETFRAME (frame, f);
11108 else
11109 frame = Qnil;
11110
11111 any_help_event_p = 1;
11112 n = gen_help_event (bufp, numchars, help_echo, frame,
11113 help_echo_window, help_echo_object,
11114 help_echo_pos);
11115 bufp += n, count += n, numchars -= n;
11116 }
11117
11118 goto OTHER;
11119 }
11120
11121 case ConfigureNotify:
11122 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
11123 if (f)
11124 {
11125 #ifndef USE_X_TOOLKIT
11126 /* If there is a pending resize for fullscreen, don't
11127 do this one, the right one will come later.
11128 The toolkit version doesn't seem to need this, but we
11129 need to reset it below. */
11130 int dont_resize =
11131 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11132 && FRAME_NEW_WIDTH (f) != 0);
11133 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
11134 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
11135 if (dont_resize)
11136 goto OTHER;
11137
11138 /* In the toolkit version, change_frame_size
11139 is called by the code that handles resizing
11140 of the EmacsFrame widget. */
11141
11142 /* Even if the number of character rows and columns has
11143 not changed, the font size may have changed, so we need
11144 to check the pixel dimensions as well. */
11145 if (columns != f->width
11146 || rows != f->height
11147 || event.xconfigure.width != f->output_data.x->pixel_width
11148 || event.xconfigure.height != f->output_data.x->pixel_height)
11149 {
11150 change_frame_size (f, rows, columns, 0, 1, 0);
11151 SET_FRAME_GARBAGED (f);
11152 cancel_mouse_face (f);
11153 }
11154 #endif
11155
11156 f->output_data.x->pixel_width = event.xconfigure.width;
11157 f->output_data.x->pixel_height = event.xconfigure.height;
11158
11159 /* What we have now is the position of Emacs's own window.
11160 Convert that to the position of the window manager window. */
11161 x_real_positions (f, &f->output_data.x->left_pos,
11162 &f->output_data.x->top_pos);
11163
11164 x_check_fullscreen_move(f);
11165 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11166 f->output_data.x->want_fullscreen &=
11167 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
11168 #ifdef HAVE_X_I18N
11169 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
11170 xic_set_statusarea (f);
11171 #endif
11172
11173 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11174 {
11175 /* Since the WM decorations come below top_pos now,
11176 we must put them below top_pos in the future. */
11177 f->output_data.x->win_gravity = NorthWestGravity;
11178 x_wm_set_size_hint (f, (long) 0, 0);
11179 }
11180 }
11181 goto OTHER;
11182
11183 case ButtonPress:
11184 case ButtonRelease:
11185 {
11186 /* If we decide we want to generate an event to be seen
11187 by the rest of Emacs, we put it here. */
11188 struct input_event emacs_event;
11189 int tool_bar_p = 0;
11190
11191 emacs_event.kind = NO_EVENT;
11192 bzero (&compose_status, sizeof (compose_status));
11193
11194 if (dpyinfo->grabbed
11195 && last_mouse_frame
11196 && FRAME_LIVE_P (last_mouse_frame))
11197 f = last_mouse_frame;
11198 else
11199 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11200
11201 if (f)
11202 {
11203 /* Is this in the tool-bar? */
11204 if (WINDOWP (f->tool_bar_window)
11205 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11206 {
11207 Lisp_Object window;
11208 int p, x, y;
11209
11210 x = event.xbutton.x;
11211 y = event.xbutton.y;
11212
11213 /* Set x and y. */
11214 window = window_from_coordinates (f, x, y, &p, 1);
11215 if (EQ (window, f->tool_bar_window))
11216 {
11217 x_handle_tool_bar_click (f, &event.xbutton);
11218 tool_bar_p = 1;
11219 }
11220 }
11221
11222 if (!tool_bar_p)
11223 if (!dpyinfo->x_focus_frame
11224 || f == dpyinfo->x_focus_frame)
11225 construct_mouse_click (&emacs_event, &event, f);
11226 }
11227 else
11228 {
11229 #ifndef USE_TOOLKIT_SCROLL_BARS
11230 struct scroll_bar *bar
11231 = x_window_to_scroll_bar (event.xbutton.window);
11232
11233 if (bar)
11234 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11235 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11236 }
11237
11238 if (event.type == ButtonPress)
11239 {
11240 dpyinfo->grabbed |= (1 << event.xbutton.button);
11241 last_mouse_frame = f;
11242 /* Ignore any mouse motion that happened
11243 before this event; any subsequent mouse-movement
11244 Emacs events should reflect only motion after
11245 the ButtonPress. */
11246 if (f != 0)
11247 f->mouse_moved = 0;
11248
11249 if (!tool_bar_p)
11250 last_tool_bar_item = -1;
11251 }
11252 else
11253 {
11254 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11255 }
11256
11257 if (numchars >= 1 && emacs_event.kind != NO_EVENT)
11258 {
11259 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11260 bufp++;
11261 count++;
11262 numchars--;
11263 }
11264
11265 #ifdef USE_X_TOOLKIT
11266 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11267 /* For a down-event in the menu bar,
11268 don't pass it to Xt right now.
11269 Instead, save it away
11270 and we will pass it to Xt from kbd_buffer_get_event.
11271 That way, we can run some Lisp code first. */
11272 if (f && event.type == ButtonPress
11273 /* Verify the event is really within the menu bar
11274 and not just sent to it due to grabbing. */
11275 && event.xbutton.x >= 0
11276 && event.xbutton.x < f->output_data.x->pixel_width
11277 && event.xbutton.y >= 0
11278 && event.xbutton.y < f->output_data.x->menubar_height
11279 && event.xbutton.same_screen)
11280 {
11281 SET_SAVED_BUTTON_EVENT;
11282 XSETFRAME (last_mouse_press_frame, f);
11283 }
11284 else if (event.type == ButtonPress)
11285 {
11286 last_mouse_press_frame = Qnil;
11287 goto OTHER;
11288 }
11289
11290 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11291 but I am trying to be cautious. */
11292 else if (event.type == ButtonRelease)
11293 {
11294 if (!NILP (last_mouse_press_frame))
11295 {
11296 f = XFRAME (last_mouse_press_frame);
11297 if (f->output_data.x)
11298 SET_SAVED_BUTTON_EVENT;
11299 }
11300 else
11301 goto OTHER;
11302 }
11303 #endif /* USE_MOTIF */
11304 else
11305 goto OTHER;
11306 #endif /* USE_X_TOOLKIT */
11307 }
11308 break;
11309
11310 case CirculateNotify:
11311 goto OTHER;
11312
11313 case CirculateRequest:
11314 goto OTHER;
11315
11316 case VisibilityNotify:
11317 goto OTHER;
11318
11319 case MappingNotify:
11320 /* Someone has changed the keyboard mapping - update the
11321 local cache. */
11322 switch (event.xmapping.request)
11323 {
11324 case MappingModifier:
11325 x_find_modifier_meanings (dpyinfo);
11326 /* This is meant to fall through. */
11327 case MappingKeyboard:
11328 XRefreshKeyboardMapping (&event.xmapping);
11329 }
11330 goto OTHER;
11331
11332 default:
11333 OTHER:
11334 #ifdef USE_X_TOOLKIT
11335 BLOCK_INPUT;
11336 XtDispatchEvent (&event);
11337 UNBLOCK_INPUT;
11338 #endif /* USE_X_TOOLKIT */
11339 break;
11340 }
11341 }
11342 }
11343
11344 out:;
11345
11346 /* On some systems, an X bug causes Emacs to get no more events
11347 when the window is destroyed. Detect that. (1994.) */
11348 if (! event_found)
11349 {
11350 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11351 One XNOOP in 100 loops will make Emacs terminate.
11352 B. Bretthauer, 1994 */
11353 x_noop_count++;
11354 if (x_noop_count >= 100)
11355 {
11356 x_noop_count=0;
11357
11358 if (next_noop_dpyinfo == 0)
11359 next_noop_dpyinfo = x_display_list;
11360
11361 XNoOp (next_noop_dpyinfo->display);
11362
11363 /* Each time we get here, cycle through the displays now open. */
11364 next_noop_dpyinfo = next_noop_dpyinfo->next;
11365 }
11366 }
11367
11368 /* If the focus was just given to an auto-raising frame,
11369 raise it now. */
11370 /* ??? This ought to be able to handle more than one such frame. */
11371 if (pending_autoraise_frame)
11372 {
11373 x_raise_frame (pending_autoraise_frame);
11374 pending_autoraise_frame = 0;
11375 }
11376
11377 UNBLOCK_INPUT;
11378 --handling_signal;
11379 return count;
11380 }
11381
11382
11383
11384 \f
11385 /***********************************************************************
11386 Text Cursor
11387 ***********************************************************************/
11388
11389 /* Notice when the text cursor of window W has been completely
11390 overwritten by a drawing operation that outputs glyphs in AREA
11391 starting at X0 and ending at X1 in the line starting at Y0 and
11392 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11393 the rest of the line after X0 has been written. Y coordinates
11394 are window-relative. */
11395
11396 static void
11397 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
11398 struct window *w;
11399 enum glyph_row_area area;
11400 int x0, y0, x1, y1;
11401 {
11402 if (area == TEXT_AREA && w->phys_cursor_on_p)
11403 {
11404 int cx0 = w->phys_cursor.x;
11405 int cx1 = cx0 + w->phys_cursor_width;
11406 int cy0 = w->phys_cursor.y;
11407 int cy1 = cy0 + w->phys_cursor_height;
11408
11409 if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
11410 {
11411 /* The cursor image will be completely removed from the
11412 screen if the output area intersects the cursor area in
11413 y-direction. When we draw in [y0 y1[, and some part of
11414 the cursor is at y < y0, that part must have been drawn
11415 before. When scrolling, the cursor is erased before
11416 actually scrolling, so we don't come here. When not
11417 scrolling, the rows above the old cursor row must have
11418 changed, and in this case these rows must have written
11419 over the cursor image.
11420
11421 Likewise if part of the cursor is below y1, with the
11422 exception of the cursor being in the first blank row at
11423 the buffer and window end because update_text_area
11424 doesn't draw that row. (Except when it does, but
11425 that's handled in update_text_area.) */
11426
11427 if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
11428 && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
11429 w->phys_cursor_on_p = 0;
11430 }
11431 }
11432 }
11433
11434
11435 /* Set clipping for output in glyph row ROW. W is the window in which
11436 we operate. GC is the graphics context to set clipping in.
11437 WHOLE_LINE_P non-zero means include the areas used for truncation
11438 mark display and alike in the clipping rectangle.
11439
11440 ROW may be a text row or, e.g., a mode line. Text rows must be
11441 clipped to the interior of the window dedicated to text display,
11442 mode lines must be clipped to the whole window. */
11443
11444 static void
11445 x_clip_to_row (w, row, gc, whole_line_p)
11446 struct window *w;
11447 struct glyph_row *row;
11448 GC gc;
11449 int whole_line_p;
11450 {
11451 struct frame *f = XFRAME (WINDOW_FRAME (w));
11452 XRectangle clip_rect;
11453 int window_x, window_y, window_width, window_height;
11454
11455 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11456
11457 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11458 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11459 clip_rect.y = max (clip_rect.y, window_y);
11460 clip_rect.width = window_width;
11461 clip_rect.height = row->visible_height;
11462
11463 /* If clipping to the whole line, including trunc marks, extend
11464 the rectangle to the left and increase its width. */
11465 if (whole_line_p)
11466 {
11467 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11468 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11469 }
11470
11471 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11472 }
11473
11474
11475 /* Draw a hollow box cursor on window W in glyph row ROW. */
11476
11477 static void
11478 x_draw_hollow_cursor (w, row)
11479 struct window *w;
11480 struct glyph_row *row;
11481 {
11482 struct frame *f = XFRAME (WINDOW_FRAME (w));
11483 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11484 Display *dpy = FRAME_X_DISPLAY (f);
11485 int x, y, wd, h;
11486 XGCValues xgcv;
11487 struct glyph *cursor_glyph;
11488 GC gc;
11489
11490 /* Compute frame-relative coordinates from window-relative
11491 coordinates. */
11492 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11493 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11494 + row->ascent - w->phys_cursor_ascent);
11495 h = row->height - 1;
11496
11497 /* Get the glyph the cursor is on. If we can't tell because
11498 the current matrix is invalid or such, give up. */
11499 cursor_glyph = get_phys_cursor_glyph (w);
11500 if (cursor_glyph == NULL)
11501 return;
11502
11503 /* Compute the width of the rectangle to draw. If on a stretch
11504 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11505 rectangle as wide as the glyph, but use a canonical character
11506 width instead. */
11507 wd = cursor_glyph->pixel_width - 1;
11508 if (cursor_glyph->type == STRETCH_GLYPH
11509 && !x_stretch_cursor_p)
11510 wd = min (CANON_X_UNIT (f), wd);
11511 w->phys_cursor_width = wd;
11512
11513 /* The foreground of cursor_gc is typically the same as the normal
11514 background color, which can cause the cursor box to be invisible. */
11515 xgcv.foreground = f->output_data.x->cursor_pixel;
11516 if (dpyinfo->scratch_cursor_gc)
11517 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11518 else
11519 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11520 GCForeground, &xgcv);
11521 gc = dpyinfo->scratch_cursor_gc;
11522
11523 /* Set clipping, draw the rectangle, and reset clipping again. */
11524 x_clip_to_row (w, row, gc, 0);
11525 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11526 XSetClipMask (dpy, gc, None);
11527 }
11528
11529
11530 /* Draw a bar cursor on window W in glyph row ROW.
11531
11532 Implementation note: One would like to draw a bar cursor with an
11533 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11534 Unfortunately, I didn't find a font yet that has this property set.
11535 --gerd. */
11536
11537 static void
11538 x_draw_bar_cursor (w, row, width, kind)
11539 struct window *w;
11540 struct glyph_row *row;
11541 int width;
11542 enum text_cursor_kinds kind;
11543 {
11544 struct frame *f = XFRAME (w->frame);
11545 struct glyph *cursor_glyph;
11546
11547 /* If cursor is out of bounds, don't draw garbage. This can happen
11548 in mini-buffer windows when switching between echo area glyphs
11549 and mini-buffer. */
11550 cursor_glyph = get_phys_cursor_glyph (w);
11551 if (cursor_glyph == NULL)
11552 return;
11553
11554 /* If on an image, draw like a normal cursor. That's usually better
11555 visible than drawing a bar, esp. if the image is large so that
11556 the bar might not be in the window. */
11557 if (cursor_glyph->type == IMAGE_GLYPH)
11558 {
11559 struct glyph_row *row;
11560 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11561 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11562 }
11563 else
11564 {
11565 Display *dpy = FRAME_X_DISPLAY (f);
11566 Window window = FRAME_X_WINDOW (f);
11567 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11568 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11569 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11570 XGCValues xgcv;
11571
11572 /* If the glyph's background equals the color we normally draw
11573 the bar cursor in, the bar cursor in its normal color is
11574 invisible. Use the glyph's foreground color instead in this
11575 case, on the assumption that the glyph's colors are chosen so
11576 that the glyph is legible. */
11577 if (face->background == f->output_data.x->cursor_pixel)
11578 xgcv.background = xgcv.foreground = face->foreground;
11579 else
11580 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11581 xgcv.graphics_exposures = 0;
11582
11583 if (gc)
11584 XChangeGC (dpy, gc, mask, &xgcv);
11585 else
11586 {
11587 gc = XCreateGC (dpy, window, mask, &xgcv);
11588 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11589 }
11590
11591 if (width < 0)
11592 width = FRAME_CURSOR_WIDTH (f);
11593 width = min (cursor_glyph->pixel_width, width);
11594
11595 w->phys_cursor_width = width;
11596 x_clip_to_row (w, row, gc, 0);
11597
11598 if (kind == BAR_CURSOR)
11599 XFillRectangle (dpy, window, gc,
11600 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11601 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11602 width, row->height);
11603 else
11604 XFillRectangle (dpy, window, gc,
11605 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11606 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
11607 row->height - width),
11608 cursor_glyph->pixel_width,
11609 width);
11610
11611 XSetClipMask (dpy, gc, None);
11612 }
11613 }
11614
11615
11616 /* Clear the cursor of window W to background color, and mark the
11617 cursor as not shown. This is used when the text where the cursor
11618 is is about to be rewritten. */
11619
11620 static void
11621 x_clear_cursor (w)
11622 struct window *w;
11623 {
11624 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11625 x_update_window_cursor (w, 0);
11626 }
11627
11628
11629 /* Draw the cursor glyph of window W in glyph row ROW. See the
11630 comment of x_draw_glyphs for the meaning of HL. */
11631
11632 static void
11633 x_draw_phys_cursor_glyph (w, row, hl)
11634 struct window *w;
11635 struct glyph_row *row;
11636 enum draw_glyphs_face hl;
11637 {
11638 /* If cursor hpos is out of bounds, don't draw garbage. This can
11639 happen in mini-buffer windows when switching between echo area
11640 glyphs and mini-buffer. */
11641 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11642 {
11643 int on_p = w->phys_cursor_on_p;
11644 int x1;
11645
11646 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11647 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11648 hl, 0);
11649 w->phys_cursor_on_p = on_p;
11650
11651 if (hl == DRAW_CURSOR)
11652 w->phys_cursor_width = x1 - w->phys_cursor.x;
11653
11654 /* When we erase the cursor, and ROW is overlapped by other
11655 rows, make sure that these overlapping parts of other rows
11656 are redrawn. */
11657 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11658 {
11659 if (row > w->current_matrix->rows
11660 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11661 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11662
11663 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11664 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11665 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11666 }
11667 }
11668 }
11669
11670
11671 /* Erase the image of a cursor of window W from the screen. */
11672
11673 static void
11674 x_erase_phys_cursor (w)
11675 struct window *w;
11676 {
11677 struct frame *f = XFRAME (w->frame);
11678 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11679 int hpos = w->phys_cursor.hpos;
11680 int vpos = w->phys_cursor.vpos;
11681 int mouse_face_here_p = 0;
11682 struct glyph_matrix *active_glyphs = w->current_matrix;
11683 struct glyph_row *cursor_row;
11684 struct glyph *cursor_glyph;
11685 enum draw_glyphs_face hl;
11686
11687 /* No cursor displayed or row invalidated => nothing to do on the
11688 screen. */
11689 if (w->phys_cursor_type == NO_CURSOR)
11690 goto mark_cursor_off;
11691
11692 /* VPOS >= active_glyphs->nrows means that window has been resized.
11693 Don't bother to erase the cursor. */
11694 if (vpos >= active_glyphs->nrows)
11695 goto mark_cursor_off;
11696
11697 /* If row containing cursor is marked invalid, there is nothing we
11698 can do. */
11699 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11700 if (!cursor_row->enabled_p)
11701 goto mark_cursor_off;
11702
11703 /* If row is completely invisible, don't attempt to delete a cursor which
11704 isn't there. This can happen if cursor is at top of a window, and
11705 we switch to a buffer with a header line in that window. */
11706 if (cursor_row->visible_height <= 0)
11707 goto mark_cursor_off;
11708
11709 /* This can happen when the new row is shorter than the old one.
11710 In this case, either x_draw_glyphs or clear_end_of_line
11711 should have cleared the cursor. Note that we wouldn't be
11712 able to erase the cursor in this case because we don't have a
11713 cursor glyph at hand. */
11714 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11715 goto mark_cursor_off;
11716
11717 /* If the cursor is in the mouse face area, redisplay that when
11718 we clear the cursor. */
11719 if (! NILP (dpyinfo->mouse_face_window)
11720 && w == XWINDOW (dpyinfo->mouse_face_window)
11721 && (vpos > dpyinfo->mouse_face_beg_row
11722 || (vpos == dpyinfo->mouse_face_beg_row
11723 && hpos >= dpyinfo->mouse_face_beg_col))
11724 && (vpos < dpyinfo->mouse_face_end_row
11725 || (vpos == dpyinfo->mouse_face_end_row
11726 && hpos < dpyinfo->mouse_face_end_col))
11727 /* Don't redraw the cursor's spot in mouse face if it is at the
11728 end of a line (on a newline). The cursor appears there, but
11729 mouse highlighting does not. */
11730 && cursor_row->used[TEXT_AREA] > hpos)
11731 mouse_face_here_p = 1;
11732
11733 /* Maybe clear the display under the cursor. */
11734 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11735 {
11736 int x;
11737 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11738
11739 cursor_glyph = get_phys_cursor_glyph (w);
11740 if (cursor_glyph == NULL)
11741 goto mark_cursor_off;
11742
11743 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11744
11745 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11746 x,
11747 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11748 cursor_row->y)),
11749 cursor_glyph->pixel_width,
11750 cursor_row->visible_height,
11751 False);
11752 }
11753
11754 /* Erase the cursor by redrawing the character underneath it. */
11755 if (mouse_face_here_p)
11756 hl = DRAW_MOUSE_FACE;
11757 else
11758 hl = DRAW_NORMAL_TEXT;
11759 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11760
11761 mark_cursor_off:
11762 w->phys_cursor_on_p = 0;
11763 w->phys_cursor_type = NO_CURSOR;
11764 }
11765
11766
11767 /* Non-zero if physical cursor of window W is within mouse face. */
11768
11769 static int
11770 cursor_in_mouse_face_p (w)
11771 struct window *w;
11772 {
11773 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11774 int in_mouse_face = 0;
11775
11776 if (WINDOWP (dpyinfo->mouse_face_window)
11777 && XWINDOW (dpyinfo->mouse_face_window) == w)
11778 {
11779 int hpos = w->phys_cursor.hpos;
11780 int vpos = w->phys_cursor.vpos;
11781
11782 if (vpos >= dpyinfo->mouse_face_beg_row
11783 && vpos <= dpyinfo->mouse_face_end_row
11784 && (vpos > dpyinfo->mouse_face_beg_row
11785 || hpos >= dpyinfo->mouse_face_beg_col)
11786 && (vpos < dpyinfo->mouse_face_end_row
11787 || hpos < dpyinfo->mouse_face_end_col
11788 || dpyinfo->mouse_face_past_end))
11789 in_mouse_face = 1;
11790 }
11791
11792 return in_mouse_face;
11793 }
11794
11795
11796 /* Display or clear cursor of window W. If ON is zero, clear the
11797 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11798 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11799
11800 void
11801 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11802 struct window *w;
11803 int on, hpos, vpos, x, y;
11804 {
11805 struct frame *f = XFRAME (w->frame);
11806 int new_cursor_type;
11807 int new_cursor_width;
11808 int active_cursor;
11809 struct glyph_matrix *current_glyphs;
11810 struct glyph_row *glyph_row;
11811 struct glyph *glyph;
11812
11813 /* This is pointless on invisible frames, and dangerous on garbaged
11814 windows and frames; in the latter case, the frame or window may
11815 be in the midst of changing its size, and x and y may be off the
11816 window. */
11817 if (! FRAME_VISIBLE_P (f)
11818 || FRAME_GARBAGED_P (f)
11819 || vpos >= w->current_matrix->nrows
11820 || hpos >= w->current_matrix->matrix_w)
11821 return;
11822
11823 /* If cursor is off and we want it off, return quickly. */
11824 if (!on && !w->phys_cursor_on_p)
11825 return;
11826
11827 current_glyphs = w->current_matrix;
11828 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11829 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11830
11831 /* If cursor row is not enabled, we don't really know where to
11832 display the cursor. */
11833 if (!glyph_row->enabled_p)
11834 {
11835 w->phys_cursor_on_p = 0;
11836 return;
11837 }
11838
11839 xassert (interrupt_input_blocked);
11840
11841 /* Set new_cursor_type to the cursor we want to be displayed. */
11842 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
11843
11844 /* If cursor is currently being shown and we don't want it to be or
11845 it is in the wrong place, or the cursor type is not what we want,
11846 erase it. */
11847 if (w->phys_cursor_on_p
11848 && (!on
11849 || w->phys_cursor.x != x
11850 || w->phys_cursor.y != y
11851 || new_cursor_type != w->phys_cursor_type
11852 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
11853 && new_cursor_width != w->phys_cursor_width)))
11854 x_erase_phys_cursor (w);
11855
11856 /* Don't check phys_cursor_on_p here because that flag is only set
11857 to zero in some cases where we know that the cursor has been
11858 completely erased, to avoid the extra work of erasing the cursor
11859 twice. In other words, phys_cursor_on_p can be 1 and the cursor
11860 still not be visible, or it has only been partly erased. */
11861 if (on)
11862 {
11863 w->phys_cursor_ascent = glyph_row->ascent;
11864 w->phys_cursor_height = glyph_row->height;
11865
11866 /* Set phys_cursor_.* before x_draw_.* is called because some
11867 of them may need the information. */
11868 w->phys_cursor.x = x;
11869 w->phys_cursor.y = glyph_row->y;
11870 w->phys_cursor.hpos = hpos;
11871 w->phys_cursor.vpos = vpos;
11872 w->phys_cursor_type = new_cursor_type;
11873 w->phys_cursor_on_p = 1;
11874
11875 switch (new_cursor_type)
11876 {
11877 case HOLLOW_BOX_CURSOR:
11878 x_draw_hollow_cursor (w, glyph_row);
11879 break;
11880
11881 case FILLED_BOX_CURSOR:
11882 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11883 break;
11884
11885 case BAR_CURSOR:
11886 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
11887 break;
11888
11889 case HBAR_CURSOR:
11890 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
11891 break;
11892
11893 case NO_CURSOR:
11894 w->phys_cursor_width = 0;
11895 break;
11896
11897 default:
11898 abort ();
11899 }
11900
11901 #ifdef HAVE_X_I18N
11902 if (w == XWINDOW (f->selected_window))
11903 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11904 xic_set_preeditarea (w, x, y);
11905 #endif
11906 }
11907
11908 #ifndef XFlush
11909 if (updating_frame != f)
11910 XFlush (FRAME_X_DISPLAY (f));
11911 #endif
11912 }
11913
11914
11915 /* Display the cursor on window W, or clear it. X and Y are window
11916 relative pixel coordinates. HPOS and VPOS are glyph matrix
11917 positions. If W is not the selected window, display a hollow
11918 cursor. ON non-zero means display the cursor at X, Y which
11919 correspond to HPOS, VPOS, otherwise it is cleared. */
11920
11921 void
11922 x_display_cursor (w, on, hpos, vpos, x, y)
11923 struct window *w;
11924 int on, hpos, vpos, x, y;
11925 {
11926 BLOCK_INPUT;
11927 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11928 UNBLOCK_INPUT;
11929 }
11930
11931
11932 /* Display the cursor on window W, or clear it, according to ON_P.
11933 Don't change the cursor's position. */
11934
11935 void
11936 x_update_cursor (f, on_p)
11937 struct frame *f;
11938 {
11939 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11940 }
11941
11942
11943 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11944 in the window tree rooted at W. */
11945
11946 static void
11947 x_update_cursor_in_window_tree (w, on_p)
11948 struct window *w;
11949 int on_p;
11950 {
11951 while (w)
11952 {
11953 if (!NILP (w->hchild))
11954 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11955 else if (!NILP (w->vchild))
11956 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11957 else
11958 x_update_window_cursor (w, on_p);
11959
11960 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11961 }
11962 }
11963
11964
11965 /* Switch the display of W's cursor on or off, according to the value
11966 of ON. */
11967
11968 static void
11969 x_update_window_cursor (w, on)
11970 struct window *w;
11971 int on;
11972 {
11973 /* Don't update cursor in windows whose frame is in the process
11974 of being deleted. */
11975 if (w->current_matrix)
11976 {
11977 BLOCK_INPUT;
11978 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11979 w->phys_cursor.x, w->phys_cursor.y);
11980 UNBLOCK_INPUT;
11981 }
11982 }
11983
11984
11985
11986 \f
11987 /* Icons. */
11988
11989 /* Make the x-window of frame F use the gnu icon bitmap. */
11990
11991 int
11992 x_bitmap_icon (f, file)
11993 struct frame *f;
11994 Lisp_Object file;
11995 {
11996 int bitmap_id;
11997
11998 if (FRAME_X_WINDOW (f) == 0)
11999 return 1;
12000
12001 /* Free up our existing icon bitmap if any. */
12002 if (f->output_data.x->icon_bitmap > 0)
12003 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12004 f->output_data.x->icon_bitmap = 0;
12005
12006 if (STRINGP (file))
12007 bitmap_id = x_create_bitmap_from_file (f, file);
12008 else
12009 {
12010 /* Create the GNU bitmap if necessary. */
12011 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
12012 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
12013 = x_create_bitmap_from_data (f, gnu_bits,
12014 gnu_width, gnu_height);
12015
12016 /* The first time we create the GNU bitmap,
12017 this increments the ref-count one extra time.
12018 As a result, the GNU bitmap is never freed.
12019 That way, we don't have to worry about allocating it again. */
12020 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
12021
12022 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
12023 }
12024
12025 x_wm_set_icon_pixmap (f, bitmap_id);
12026 f->output_data.x->icon_bitmap = bitmap_id;
12027
12028 return 0;
12029 }
12030
12031
12032 /* Make the x-window of frame F use a rectangle with text.
12033 Use ICON_NAME as the text. */
12034
12035 int
12036 x_text_icon (f, icon_name)
12037 struct frame *f;
12038 char *icon_name;
12039 {
12040 if (FRAME_X_WINDOW (f) == 0)
12041 return 1;
12042
12043 #ifdef HAVE_X11R4
12044 {
12045 XTextProperty text;
12046 text.value = (unsigned char *) icon_name;
12047 text.encoding = XA_STRING;
12048 text.format = 8;
12049 text.nitems = strlen (icon_name);
12050 #ifdef USE_X_TOOLKIT
12051 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12052 &text);
12053 #else /* not USE_X_TOOLKIT */
12054 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
12055 #endif /* not USE_X_TOOLKIT */
12056 }
12057 #else /* not HAVE_X11R4 */
12058 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
12059 #endif /* not HAVE_X11R4 */
12060
12061 if (f->output_data.x->icon_bitmap > 0)
12062 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12063 f->output_data.x->icon_bitmap = 0;
12064 x_wm_set_icon_pixmap (f, 0);
12065
12066 return 0;
12067 }
12068 \f
12069 #define X_ERROR_MESSAGE_SIZE 200
12070
12071 /* If non-nil, this should be a string.
12072 It means catch X errors and store the error message in this string. */
12073
12074 static Lisp_Object x_error_message_string;
12075
12076 /* An X error handler which stores the error message in
12077 x_error_message_string. This is called from x_error_handler if
12078 x_catch_errors is in effect. */
12079
12080 static void
12081 x_error_catcher (display, error)
12082 Display *display;
12083 XErrorEvent *error;
12084 {
12085 XGetErrorText (display, error->error_code,
12086 SDATA (x_error_message_string),
12087 X_ERROR_MESSAGE_SIZE);
12088 }
12089
12090 /* Begin trapping X errors for display DPY. Actually we trap X errors
12091 for all displays, but DPY should be the display you are actually
12092 operating on.
12093
12094 After calling this function, X protocol errors no longer cause
12095 Emacs to exit; instead, they are recorded in the string
12096 stored in x_error_message_string.
12097
12098 Calling x_check_errors signals an Emacs error if an X error has
12099 occurred since the last call to x_catch_errors or x_check_errors.
12100
12101 Calling x_uncatch_errors resumes the normal error handling. */
12102
12103 void x_check_errors ();
12104 static Lisp_Object x_catch_errors_unwind ();
12105
12106 int
12107 x_catch_errors (dpy)
12108 Display *dpy;
12109 {
12110 int count = SPECPDL_INDEX ();
12111
12112 /* Make sure any errors from previous requests have been dealt with. */
12113 XSync (dpy, False);
12114
12115 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
12116
12117 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
12118 SSET (x_error_message_string, 0, 0);
12119
12120 return count;
12121 }
12122
12123 /* Unbind the binding that we made to check for X errors. */
12124
12125 static Lisp_Object
12126 x_catch_errors_unwind (old_val)
12127 Lisp_Object old_val;
12128 {
12129 x_error_message_string = old_val;
12130 return Qnil;
12131 }
12132
12133 /* If any X protocol errors have arrived since the last call to
12134 x_catch_errors or x_check_errors, signal an Emacs error using
12135 sprintf (a buffer, FORMAT, the x error message text) as the text. */
12136
12137 void
12138 x_check_errors (dpy, format)
12139 Display *dpy;
12140 char *format;
12141 {
12142 /* Make sure to catch any errors incurred so far. */
12143 XSync (dpy, False);
12144
12145 if (SREF (x_error_message_string, 0))
12146 error (format, SDATA (x_error_message_string));
12147 }
12148
12149 /* Nonzero if we had any X protocol errors
12150 since we did x_catch_errors on DPY. */
12151
12152 int
12153 x_had_errors_p (dpy)
12154 Display *dpy;
12155 {
12156 /* Make sure to catch any errors incurred so far. */
12157 XSync (dpy, False);
12158
12159 return SREF (x_error_message_string, 0) != 0;
12160 }
12161
12162 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
12163
12164 void
12165 x_clear_errors (dpy)
12166 Display *dpy;
12167 {
12168 SSET (x_error_message_string, 0, 0);
12169 }
12170
12171 /* Stop catching X protocol errors and let them make Emacs die.
12172 DPY should be the display that was passed to x_catch_errors.
12173 COUNT should be the value that was returned by
12174 the corresponding call to x_catch_errors. */
12175
12176 void
12177 x_uncatch_errors (dpy, count)
12178 Display *dpy;
12179 int count;
12180 {
12181 unbind_to (count, Qnil);
12182 }
12183
12184 #if 0
12185 static unsigned int x_wire_count;
12186 x_trace_wire ()
12187 {
12188 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
12189 }
12190 #endif /* ! 0 */
12191
12192 \f
12193 /* Handle SIGPIPE, which can happen when the connection to a server
12194 simply goes away. SIGPIPE is handled by x_connection_signal.
12195 Don't need to do anything, because the write which caused the
12196 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12197 which will do the appropriate cleanup for us. */
12198
12199 static SIGTYPE
12200 x_connection_signal (signalnum) /* If we don't have an argument, */
12201 int signalnum; /* some compilers complain in signal calls. */
12202 {
12203 #ifdef USG
12204 /* USG systems forget handlers when they are used;
12205 must reestablish each time */
12206 signal (signalnum, x_connection_signal);
12207 #endif /* USG */
12208 }
12209
12210 \f
12211 /************************************************************************
12212 Handling X errors
12213 ************************************************************************/
12214
12215 /* Error message passed to x_connection_closed. */
12216
12217 static char *error_msg;
12218
12219 /* Function installed as fatal_error_signal_hook in
12220 x_connection_closed. Print the X error message, and exit normally,
12221 instead of dumping core when XtCloseDisplay fails. */
12222
12223 static void
12224 x_fatal_error_signal ()
12225 {
12226 fprintf (stderr, "%s\n", error_msg);
12227 exit (70);
12228 }
12229
12230 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12231 the text of an error message that lead to the connection loss. */
12232
12233 static SIGTYPE
12234 x_connection_closed (dpy, error_message)
12235 Display *dpy;
12236 char *error_message;
12237 {
12238 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
12239 Lisp_Object frame, tail;
12240 int count;
12241
12242 error_msg = (char *) alloca (strlen (error_message) + 1);
12243 strcpy (error_msg, error_message);
12244 handling_signal = 0;
12245
12246 /* Prevent being called recursively because of an error condition
12247 below. Otherwise, we might end up with printing ``can't find per
12248 display information'' in the recursive call instead of printing
12249 the original message here. */
12250 count = x_catch_errors (dpy);
12251
12252 /* We have to close the display to inform Xt that it doesn't
12253 exist anymore. If we don't, Xt will continue to wait for
12254 events from the display. As a consequence, a sequence of
12255
12256 M-x make-frame-on-display RET :1 RET
12257 ...kill the new frame, so that we get an IO error...
12258 M-x make-frame-on-display RET :1 RET
12259
12260 will indefinitely wait in Xt for events for display `:1', opened
12261 in the first class to make-frame-on-display.
12262
12263 Closing the display is reported to lead to a bus error on
12264 OpenWindows in certain situations. I suspect that is a bug
12265 in OpenWindows. I don't know how to cicumvent it here. */
12266
12267 #ifdef USE_X_TOOLKIT
12268 /* If DPYINFO is null, this means we didn't open the display
12269 in the first place, so don't try to close it. */
12270 if (dpyinfo)
12271 {
12272 extern void (*fatal_error_signal_hook) P_ ((void));
12273 fatal_error_signal_hook = x_fatal_error_signal;
12274 XtCloseDisplay (dpy);
12275 fatal_error_signal_hook = NULL;
12276 }
12277 #endif
12278
12279 /* Indicate that this display is dead. */
12280 if (dpyinfo)
12281 dpyinfo->display = 0;
12282
12283 /* First delete frames whose mini-buffers are on frames
12284 that are on the dead display. */
12285 FOR_EACH_FRAME (tail, frame)
12286 {
12287 Lisp_Object minibuf_frame;
12288 minibuf_frame
12289 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
12290 if (FRAME_X_P (XFRAME (frame))
12291 && FRAME_X_P (XFRAME (minibuf_frame))
12292 && ! EQ (frame, minibuf_frame)
12293 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
12294 Fdelete_frame (frame, Qt);
12295 }
12296
12297 /* Now delete all remaining frames on the dead display.
12298 We are now sure none of these is used as the mini-buffer
12299 for another frame that we need to delete. */
12300 FOR_EACH_FRAME (tail, frame)
12301 if (FRAME_X_P (XFRAME (frame))
12302 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
12303 {
12304 /* Set this to t so that Fdelete_frame won't get confused
12305 trying to find a replacement. */
12306 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12307 Fdelete_frame (frame, Qt);
12308 }
12309
12310 if (dpyinfo)
12311 x_delete_display (dpyinfo);
12312
12313 x_uncatch_errors (dpy, count);
12314
12315 if (x_display_list == 0)
12316 {
12317 fprintf (stderr, "%s\n", error_msg);
12318 shut_down_emacs (0, 0, Qnil);
12319 exit (70);
12320 }
12321
12322 /* Ordinary stack unwind doesn't deal with these. */
12323 #ifdef SIGIO
12324 sigunblock (sigmask (SIGIO));
12325 #endif
12326 sigunblock (sigmask (SIGALRM));
12327 TOTALLY_UNBLOCK_INPUT;
12328
12329 clear_waiting_for_input ();
12330 error ("%s", error_msg);
12331 }
12332
12333
12334 /* This is the usual handler for X protocol errors.
12335 It kills all frames on the display that we got the error for.
12336 If that was the only one, it prints an error message and kills Emacs. */
12337
12338 static void
12339 x_error_quitter (display, error)
12340 Display *display;
12341 XErrorEvent *error;
12342 {
12343 char buf[256], buf1[356];
12344
12345 /* Note that there is no real way portable across R3/R4 to get the
12346 original error handler. */
12347
12348 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12349 sprintf (buf1, "X protocol error: %s on protocol request %d",
12350 buf, error->request_code);
12351 x_connection_closed (display, buf1);
12352 }
12353
12354
12355 /* This is the first-level handler for X protocol errors.
12356 It calls x_error_quitter or x_error_catcher. */
12357
12358 static int
12359 x_error_handler (display, error)
12360 Display *display;
12361 XErrorEvent *error;
12362 {
12363 if (! NILP (x_error_message_string))
12364 x_error_catcher (display, error);
12365 else
12366 x_error_quitter (display, error);
12367 return 0;
12368 }
12369
12370 /* This is the handler for X IO errors, always.
12371 It kills all frames on the display that we lost touch with.
12372 If that was the only one, it prints an error message and kills Emacs. */
12373
12374 static int
12375 x_io_error_quitter (display)
12376 Display *display;
12377 {
12378 char buf[256];
12379
12380 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12381 x_connection_closed (display, buf);
12382 return 0;
12383 }
12384 \f
12385 /* Changing the font of the frame. */
12386
12387 /* Give frame F the font named FONTNAME as its default font, and
12388 return the full name of that font. FONTNAME may be a wildcard
12389 pattern; in that case, we choose some font that fits the pattern.
12390 The return value shows which font we chose. */
12391
12392 Lisp_Object
12393 x_new_font (f, fontname)
12394 struct frame *f;
12395 register char *fontname;
12396 {
12397 struct font_info *fontp
12398 = FS_LOAD_FONT (f, 0, fontname, -1);
12399
12400 if (!fontp)
12401 return Qnil;
12402
12403 f->output_data.x->font = (XFontStruct *) (fontp->font);
12404 f->output_data.x->baseline_offset = fontp->baseline_offset;
12405 f->output_data.x->fontset = -1;
12406
12407 x_compute_fringe_widths (f, 1);
12408
12409 /* Compute the scroll bar width in character columns. */
12410 if (f->scroll_bar_pixel_width > 0)
12411 {
12412 int wid = FONT_WIDTH (f->output_data.x->font);
12413 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12414 }
12415 else
12416 {
12417 int wid = FONT_WIDTH (f->output_data.x->font);
12418 f->scroll_bar_cols = (14 + wid - 1) / wid;
12419 }
12420
12421 /* Now make the frame display the given font. */
12422 if (FRAME_X_WINDOW (f) != 0)
12423 {
12424 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12425 f->output_data.x->font->fid);
12426 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12427 f->output_data.x->font->fid);
12428 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12429 f->output_data.x->font->fid);
12430
12431 frame_update_line_height (f);
12432
12433 /* Don't change the size of a tip frame; there's no point in
12434 doing it because it's done in Fx_show_tip, and it leads to
12435 problems because the tip frame has no widget. */
12436 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12437 x_set_window_size (f, 0, f->width, f->height);
12438 }
12439 else
12440 /* If we are setting a new frame's font for the first time,
12441 there are no faces yet, so this font's height is the line height. */
12442 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12443
12444 return build_string (fontp->full_name);
12445 }
12446
12447 /* Give frame F the fontset named FONTSETNAME as its default font, and
12448 return the full name of that fontset. FONTSETNAME may be a wildcard
12449 pattern; in that case, we choose some fontset that fits the pattern.
12450 The return value shows which fontset we chose. */
12451
12452 Lisp_Object
12453 x_new_fontset (f, fontsetname)
12454 struct frame *f;
12455 char *fontsetname;
12456 {
12457 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12458 Lisp_Object result;
12459
12460 if (fontset < 0)
12461 return Qnil;
12462
12463 if (f->output_data.x->fontset == fontset)
12464 /* This fontset is already set in frame F. There's nothing more
12465 to do. */
12466 return fontset_name (fontset);
12467
12468 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
12469
12470 if (!STRINGP (result))
12471 /* Can't load ASCII font. */
12472 return Qnil;
12473
12474 /* Since x_new_font doesn't update any fontset information, do it now. */
12475 f->output_data.x->fontset = fontset;
12476
12477 #ifdef HAVE_X_I18N
12478 if (FRAME_XIC (f)
12479 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12480 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
12481 #endif
12482
12483 return build_string (fontsetname);
12484 }
12485
12486 /* Compute actual fringe widths */
12487
12488 void
12489 x_compute_fringe_widths (f, redraw)
12490 struct frame *f;
12491 int redraw;
12492 {
12493 int o_left = f->output_data.x->left_fringe_width;
12494 int o_right = f->output_data.x->right_fringe_width;
12495 int o_cols = f->output_data.x->fringe_cols;
12496
12497 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
12498 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
12499 int left_fringe_width, right_fringe_width;
12500
12501 if (!NILP (left_fringe))
12502 left_fringe = Fcdr (left_fringe);
12503 if (!NILP (right_fringe))
12504 right_fringe = Fcdr (right_fringe);
12505
12506 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
12507 XINT (left_fringe));
12508 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
12509 XINT (right_fringe));
12510
12511 if (left_fringe_width || right_fringe_width)
12512 {
12513 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
12514 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
12515 int conf_wid = left_wid + right_wid;
12516 int font_wid = FONT_WIDTH (f->output_data.x->font);
12517 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
12518 int real_wid = cols * font_wid;
12519 if (left_wid && right_wid)
12520 {
12521 if (left_fringe_width < 0)
12522 {
12523 /* Left fringe width is fixed, adjust right fringe if necessary */
12524 f->output_data.x->left_fringe_width = left_wid;
12525 f->output_data.x->right_fringe_width = real_wid - left_wid;
12526 }
12527 else if (right_fringe_width < 0)
12528 {
12529 /* Right fringe width is fixed, adjust left fringe if necessary */
12530 f->output_data.x->left_fringe_width = real_wid - right_wid;
12531 f->output_data.x->right_fringe_width = right_wid;
12532 }
12533 else
12534 {
12535 /* Adjust both fringes with an equal amount.
12536 Note that we are doing integer arithmetic here, so don't
12537 lose a pixel if the total width is an odd number. */
12538 int fill = real_wid - conf_wid;
12539 f->output_data.x->left_fringe_width = left_wid + fill/2;
12540 f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
12541 }
12542 }
12543 else if (left_fringe_width)
12544 {
12545 f->output_data.x->left_fringe_width = real_wid;
12546 f->output_data.x->right_fringe_width = 0;
12547 }
12548 else
12549 {
12550 f->output_data.x->left_fringe_width = 0;
12551 f->output_data.x->right_fringe_width = real_wid;
12552 }
12553 f->output_data.x->fringe_cols = cols;
12554 f->output_data.x->fringes_extra = real_wid;
12555 }
12556 else
12557 {
12558 f->output_data.x->left_fringe_width = 0;
12559 f->output_data.x->right_fringe_width = 0;
12560 f->output_data.x->fringe_cols = 0;
12561 f->output_data.x->fringes_extra = 0;
12562 }
12563
12564 if (redraw && FRAME_VISIBLE_P (f))
12565 if (o_left != f->output_data.x->left_fringe_width ||
12566 o_right != f->output_data.x->right_fringe_width ||
12567 o_cols != f->output_data.x->fringe_cols)
12568 redraw_frame (f);
12569 }
12570 \f
12571 /***********************************************************************
12572 X Input Methods
12573 ***********************************************************************/
12574
12575 #ifdef HAVE_X_I18N
12576
12577 #ifdef HAVE_X11R6
12578
12579 /* XIM destroy callback function, which is called whenever the
12580 connection to input method XIM dies. CLIENT_DATA contains a
12581 pointer to the x_display_info structure corresponding to XIM. */
12582
12583 static void
12584 xim_destroy_callback (xim, client_data, call_data)
12585 XIM xim;
12586 XPointer client_data;
12587 XPointer call_data;
12588 {
12589 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12590 Lisp_Object frame, tail;
12591
12592 BLOCK_INPUT;
12593
12594 /* No need to call XDestroyIC.. */
12595 FOR_EACH_FRAME (tail, frame)
12596 {
12597 struct frame *f = XFRAME (frame);
12598 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12599 {
12600 FRAME_XIC (f) = NULL;
12601 if (FRAME_XIC_FONTSET (f))
12602 {
12603 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12604 FRAME_XIC_FONTSET (f) = NULL;
12605 }
12606 }
12607 }
12608
12609 /* No need to call XCloseIM. */
12610 dpyinfo->xim = NULL;
12611 XFree (dpyinfo->xim_styles);
12612 UNBLOCK_INPUT;
12613 }
12614
12615 #endif /* HAVE_X11R6 */
12616
12617 /* Open the connection to the XIM server on display DPYINFO.
12618 RESOURCE_NAME is the resource name Emacs uses. */
12619
12620 static void
12621 xim_open_dpy (dpyinfo, resource_name)
12622 struct x_display_info *dpyinfo;
12623 char *resource_name;
12624 {
12625 #ifdef USE_XIM
12626 XIM xim;
12627
12628 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12629 dpyinfo->xim = xim;
12630
12631 if (xim)
12632 {
12633 #ifdef HAVE_X11R6
12634 XIMCallback destroy;
12635 #endif
12636
12637 /* Get supported styles and XIM values. */
12638 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12639
12640 #ifdef HAVE_X11R6
12641 destroy.callback = xim_destroy_callback;
12642 destroy.client_data = (XPointer)dpyinfo;
12643 /* This isn't prototyped in OSF 5.0. */
12644 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12645 #endif
12646 }
12647
12648 #else /* not USE_XIM */
12649 dpyinfo->xim = NULL;
12650 #endif /* not USE_XIM */
12651 }
12652
12653
12654 #ifdef HAVE_X11R6_XIM
12655
12656 struct xim_inst_t
12657 {
12658 struct x_display_info *dpyinfo;
12659 char *resource_name;
12660 };
12661
12662 /* XIM instantiate callback function, which is called whenever an XIM
12663 server is available. DISPLAY is teh display of the XIM.
12664 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12665 when the callback was registered. */
12666
12667 static void
12668 xim_instantiate_callback (display, client_data, call_data)
12669 Display *display;
12670 XPointer client_data;
12671 XPointer call_data;
12672 {
12673 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12674 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12675
12676 /* We don't support multiple XIM connections. */
12677 if (dpyinfo->xim)
12678 return;
12679
12680 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12681
12682 /* Create XIC for the existing frames on the same display, as long
12683 as they have no XIC. */
12684 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12685 {
12686 Lisp_Object tail, frame;
12687
12688 BLOCK_INPUT;
12689 FOR_EACH_FRAME (tail, frame)
12690 {
12691 struct frame *f = XFRAME (frame);
12692
12693 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12694 if (FRAME_XIC (f) == NULL)
12695 {
12696 create_frame_xic (f);
12697 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12698 xic_set_statusarea (f);
12699 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12700 {
12701 struct window *w = XWINDOW (f->selected_window);
12702 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12703 }
12704 }
12705 }
12706
12707 UNBLOCK_INPUT;
12708 }
12709 }
12710
12711 #endif /* HAVE_X11R6_XIM */
12712
12713
12714 /* Open a connection to the XIM server on display DPYINFO.
12715 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12716 connection only at the first time. On X11R6, open the connection
12717 in the XIM instantiate callback function. */
12718
12719 static void
12720 xim_initialize (dpyinfo, resource_name)
12721 struct x_display_info *dpyinfo;
12722 char *resource_name;
12723 {
12724 #ifdef USE_XIM
12725 #ifdef HAVE_X11R6_XIM
12726 struct xim_inst_t *xim_inst;
12727 int len;
12728
12729 dpyinfo->xim = NULL;
12730 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12731 xim_inst->dpyinfo = dpyinfo;
12732 len = strlen (resource_name);
12733 xim_inst->resource_name = (char *) xmalloc (len + 1);
12734 bcopy (resource_name, xim_inst->resource_name, len + 1);
12735 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12736 resource_name, EMACS_CLASS,
12737 xim_instantiate_callback,
12738 /* Fixme: This is XPointer in
12739 XFree86 but (XPointer *) on
12740 Tru64, at least. */
12741 (XPointer) xim_inst);
12742 #else /* not HAVE_X11R6_XIM */
12743 dpyinfo->xim = NULL;
12744 xim_open_dpy (dpyinfo, resource_name);
12745 #endif /* not HAVE_X11R6_XIM */
12746
12747 #else /* not USE_XIM */
12748 dpyinfo->xim = NULL;
12749 #endif /* not USE_XIM */
12750 }
12751
12752
12753 /* Close the connection to the XIM server on display DPYINFO. */
12754
12755 static void
12756 xim_close_dpy (dpyinfo)
12757 struct x_display_info *dpyinfo;
12758 {
12759 #ifdef USE_XIM
12760 #ifdef HAVE_X11R6_XIM
12761 if (dpyinfo->display)
12762 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12763 NULL, EMACS_CLASS,
12764 xim_instantiate_callback, NULL);
12765 #endif /* not HAVE_X11R6_XIM */
12766 if (dpyinfo->display)
12767 XCloseIM (dpyinfo->xim);
12768 dpyinfo->xim = NULL;
12769 XFree (dpyinfo->xim_styles);
12770 #endif /* USE_XIM */
12771 }
12772
12773 #endif /* not HAVE_X11R6_XIM */
12774
12775
12776 \f
12777 /* Calculate the absolute position in frame F
12778 from its current recorded position values and gravity. */
12779
12780 void
12781 x_calc_absolute_position (f)
12782 struct frame *f;
12783 {
12784 Window child;
12785 int win_x = 0, win_y = 0;
12786 int flags = f->output_data.x->size_hint_flags;
12787 int this_window;
12788
12789 /* We have nothing to do if the current position
12790 is already for the top-left corner. */
12791 if (! ((flags & XNegative) || (flags & YNegative)))
12792 return;
12793
12794 #ifdef USE_X_TOOLKIT
12795 this_window = XtWindow (f->output_data.x->widget);
12796 #else
12797 this_window = FRAME_X_WINDOW (f);
12798 #endif
12799
12800 /* Find the position of the outside upper-left corner of
12801 the inner window, with respect to the outer window.
12802 But do this only if we will need the results. */
12803 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12804 {
12805 int count;
12806
12807 BLOCK_INPUT;
12808 count = x_catch_errors (FRAME_X_DISPLAY (f));
12809 while (1)
12810 {
12811 x_clear_errors (FRAME_X_DISPLAY (f));
12812 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12813
12814 /* From-window, to-window. */
12815 this_window,
12816 f->output_data.x->parent_desc,
12817
12818 /* From-position, to-position. */
12819 0, 0, &win_x, &win_y,
12820
12821 /* Child of win. */
12822 &child);
12823 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12824 {
12825 Window newroot, newparent = 0xdeadbeef;
12826 Window *newchildren;
12827 unsigned int nchildren;
12828
12829 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12830 &newparent, &newchildren, &nchildren))
12831 break;
12832
12833 XFree ((char *) newchildren);
12834
12835 f->output_data.x->parent_desc = newparent;
12836 }
12837 else
12838 break;
12839 }
12840
12841 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12842 UNBLOCK_INPUT;
12843 }
12844
12845 /* Treat negative positions as relative to the leftmost bottommost
12846 position that fits on the screen. */
12847 if (flags & XNegative)
12848 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12849 - 2 * f->output_data.x->border_width - win_x
12850 - PIXEL_WIDTH (f)
12851 + f->output_data.x->left_pos);
12852
12853 {
12854 int height = PIXEL_HEIGHT (f);
12855
12856 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12857 /* Something is fishy here. When using Motif, starting Emacs with
12858 `-g -0-0', the frame appears too low by a few pixels.
12859
12860 This seems to be so because initially, while Emacs is starting,
12861 the column widget's height and the frame's pixel height are
12862 different. The column widget's height is the right one. In
12863 later invocations, when Emacs is up, the frame's pixel height
12864 is right, though.
12865
12866 It's not obvious where the initial small difference comes from.
12867 2000-12-01, gerd. */
12868
12869 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12870 #endif
12871
12872 if (flags & YNegative)
12873 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12874 - 2 * f->output_data.x->border_width
12875 - win_y
12876 - height
12877 + f->output_data.x->top_pos);
12878 }
12879
12880 /* The left_pos and top_pos
12881 are now relative to the top and left screen edges,
12882 so the flags should correspond. */
12883 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12884 }
12885
12886 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12887 to really change the position, and 0 when calling from
12888 x_make_frame_visible (in that case, XOFF and YOFF are the current
12889 position values). It is -1 when calling from x_set_frame_parameters,
12890 which means, do adjust for borders but don't change the gravity. */
12891
12892 void
12893 x_set_offset (f, xoff, yoff, change_gravity)
12894 struct frame *f;
12895 register int xoff, yoff;
12896 int change_gravity;
12897 {
12898 int modified_top, modified_left;
12899
12900 if (change_gravity > 0)
12901 {
12902 f->output_data.x->top_pos = yoff;
12903 f->output_data.x->left_pos = xoff;
12904 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12905 if (xoff < 0)
12906 f->output_data.x->size_hint_flags |= XNegative;
12907 if (yoff < 0)
12908 f->output_data.x->size_hint_flags |= YNegative;
12909 f->output_data.x->win_gravity = NorthWestGravity;
12910 }
12911 x_calc_absolute_position (f);
12912
12913 BLOCK_INPUT;
12914 x_wm_set_size_hint (f, (long) 0, 0);
12915
12916 modified_left = f->output_data.x->left_pos;
12917 modified_top = f->output_data.x->top_pos;
12918 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12919 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12920 /* It is a mystery why we need to add the border_width here
12921 when the frame is already visible, but experiment says we do. */
12922 if (change_gravity != 0)
12923 {
12924 modified_left += f->output_data.x->border_width;
12925 modified_top += f->output_data.x->border_width;
12926 }
12927 #endif
12928
12929 #ifdef USE_X_TOOLKIT
12930 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12931 modified_left, modified_top);
12932 #else /* not USE_X_TOOLKIT */
12933 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12934 modified_left, modified_top);
12935 #endif /* not USE_X_TOOLKIT */
12936 UNBLOCK_INPUT;
12937 }
12938
12939 /* Check if we need to resize the frame due to a fullscreen request.
12940 If so needed, resize the frame. */
12941 static void
12942 x_check_fullscreen (f)
12943 struct frame *f;
12944 {
12945 if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
12946 {
12947 int width, height, ign;
12948
12949 x_real_positions (f, &f->output_data.x->left_pos,
12950 &f->output_data.x->top_pos);
12951
12952 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
12953
12954 /* We do not need to move the window, it shall be taken care of
12955 when setting WM manager hints.
12956 If the frame is visible already, the position is checked by
12957 x_check_fullscreen_move. */
12958 if (f->width != width || f->height != height)
12959 {
12960 change_frame_size (f, height, width, 0, 1, 0);
12961 SET_FRAME_GARBAGED (f);
12962 cancel_mouse_face (f);
12963
12964 /* Wait for the change of frame size to occur */
12965 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
12966
12967 }
12968 }
12969 }
12970
12971 /* If frame parameters are set after the frame is mapped, we need to move
12972 the window. This is done in xfns.c.
12973 Some window managers moves the window to the right position, some
12974 moves the outer window manager window to the specified position.
12975 Here we check that we are in the right spot. If not, make a second
12976 move, assuming we are dealing with the second kind of window manager. */
12977 static void
12978 x_check_fullscreen_move (f)
12979 struct frame *f;
12980 {
12981 if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
12982 {
12983 int expect_top = f->output_data.x->top_pos;
12984 int expect_left = f->output_data.x->left_pos;
12985
12986 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
12987 expect_top = 0;
12988 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
12989 expect_left = 0;
12990
12991 if (expect_top != f->output_data.x->top_pos
12992 || expect_left != f->output_data.x->left_pos)
12993 x_set_offset (f, expect_left, expect_top, 1);
12994
12995 /* Just do this once */
12996 f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
12997 }
12998 }
12999
13000
13001 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
13002 wanted positions of the WM window (not emacs window).
13003 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
13004 window (FRAME_X_WINDOW).
13005 */
13006 void
13007 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
13008 struct frame *f;
13009 int *width;
13010 int *height;
13011 int *top_pos;
13012 int *left_pos;
13013 {
13014 int newwidth = f->width, newheight = f->height;
13015
13016 *top_pos = f->output_data.x->top_pos;
13017 *left_pos = f->output_data.x->left_pos;
13018
13019 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13020 {
13021 int ph;
13022
13023 ph = FRAME_X_DISPLAY_INFO (f)->height;
13024 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13025 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
13026 - f->output_data.x->y_pixels_diff;
13027 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13028 *top_pos = 0;
13029 }
13030
13031 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13032 {
13033 int pw;
13034
13035 pw = FRAME_X_DISPLAY_INFO (f)->width;
13036 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13037 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
13038 - f->output_data.x->x_pixels_diff;
13039 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13040 *left_pos = 0;
13041 }
13042
13043 *width = newwidth;
13044 *height = newheight;
13045 }
13046
13047
13048 /* Change the size of frame F's X window to COLS/ROWS in the case F
13049 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
13050 top-left-corner window gravity for this size change and subsequent
13051 size changes. Otherwise we leave the window gravity unchanged. */
13052
13053 static void
13054 x_set_window_size_1 (f, change_gravity, cols, rows)
13055 struct frame *f;
13056 int change_gravity;
13057 int cols, rows;
13058 {
13059 int pixelwidth, pixelheight;
13060
13061 check_frame_size (f, &rows, &cols);
13062 f->output_data.x->vertical_scroll_bar_extra
13063 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
13064 ? 0
13065 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
13066 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
13067 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
13068
13069 x_compute_fringe_widths (f, 0);
13070
13071 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
13072 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
13073
13074 f->output_data.x->win_gravity = NorthWestGravity;
13075 x_wm_set_size_hint (f, (long) 0, 0);
13076
13077 XSync (FRAME_X_DISPLAY (f), False);
13078 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13079 pixelwidth, pixelheight);
13080
13081 /* Now, strictly speaking, we can't be sure that this is accurate,
13082 but the window manager will get around to dealing with the size
13083 change request eventually, and we'll hear how it went when the
13084 ConfigureNotify event gets here.
13085
13086 We could just not bother storing any of this information here,
13087 and let the ConfigureNotify event set everything up, but that
13088 might be kind of confusing to the Lisp code, since size changes
13089 wouldn't be reported in the frame parameters until some random
13090 point in the future when the ConfigureNotify event arrives.
13091
13092 We pass 1 for DELAY since we can't run Lisp code inside of
13093 a BLOCK_INPUT. */
13094 change_frame_size (f, rows, cols, 0, 1, 0);
13095 PIXEL_WIDTH (f) = pixelwidth;
13096 PIXEL_HEIGHT (f) = pixelheight;
13097
13098 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
13099 receive in the ConfigureNotify event; if we get what we asked
13100 for, then the event won't cause the screen to become garbaged, so
13101 we have to make sure to do it here. */
13102 SET_FRAME_GARBAGED (f);
13103
13104 XFlush (FRAME_X_DISPLAY (f));
13105 }
13106
13107
13108 /* Call this to change the size of frame F's x-window.
13109 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
13110 for this size change and subsequent size changes.
13111 Otherwise we leave the window gravity unchanged. */
13112
13113 void
13114 x_set_window_size (f, change_gravity, cols, rows)
13115 struct frame *f;
13116 int change_gravity;
13117 int cols, rows;
13118 {
13119 BLOCK_INPUT;
13120
13121 #ifdef USE_X_TOOLKIT
13122
13123 if (f->output_data.x->widget != NULL)
13124 {
13125 /* The x and y position of the widget is clobbered by the
13126 call to XtSetValues within EmacsFrameSetCharSize.
13127 This is a real kludge, but I don't understand Xt so I can't
13128 figure out a correct fix. Can anyone else tell me? -- rms. */
13129 int xpos = f->output_data.x->widget->core.x;
13130 int ypos = f->output_data.x->widget->core.y;
13131 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
13132 f->output_data.x->widget->core.x = xpos;
13133 f->output_data.x->widget->core.y = ypos;
13134 }
13135 else
13136 x_set_window_size_1 (f, change_gravity, cols, rows);
13137
13138 #else /* not USE_X_TOOLKIT */
13139
13140 x_set_window_size_1 (f, change_gravity, cols, rows);
13141
13142 #endif /* not USE_X_TOOLKIT */
13143
13144 /* If cursor was outside the new size, mark it as off. */
13145 mark_window_cursors_off (XWINDOW (f->root_window));
13146
13147 /* Clear out any recollection of where the mouse highlighting was,
13148 since it might be in a place that's outside the new frame size.
13149 Actually checking whether it is outside is a pain in the neck,
13150 so don't try--just let the highlighting be done afresh with new size. */
13151 cancel_mouse_face (f);
13152
13153 UNBLOCK_INPUT;
13154 }
13155 \f
13156 /* Mouse warping. */
13157
13158 void
13159 x_set_mouse_position (f, x, y)
13160 struct frame *f;
13161 int x, y;
13162 {
13163 int pix_x, pix_y;
13164
13165 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
13166 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
13167
13168 if (pix_x < 0) pix_x = 0;
13169 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
13170
13171 if (pix_y < 0) pix_y = 0;
13172 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
13173
13174 BLOCK_INPUT;
13175
13176 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13177 0, 0, 0, 0, pix_x, pix_y);
13178 UNBLOCK_INPUT;
13179 }
13180
13181 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13182
13183 void
13184 x_set_mouse_pixel_position (f, pix_x, pix_y)
13185 struct frame *f;
13186 int pix_x, pix_y;
13187 {
13188 BLOCK_INPUT;
13189
13190 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13191 0, 0, 0, 0, pix_x, pix_y);
13192 UNBLOCK_INPUT;
13193 }
13194 \f
13195 /* focus shifting, raising and lowering. */
13196
13197 void
13198 x_focus_on_frame (f)
13199 struct frame *f;
13200 {
13201 #if 0 /* This proves to be unpleasant. */
13202 x_raise_frame (f);
13203 #endif
13204 #if 0
13205 /* I don't think that the ICCCM allows programs to do things like this
13206 without the interaction of the window manager. Whatever you end up
13207 doing with this code, do it to x_unfocus_frame too. */
13208 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13209 RevertToPointerRoot, CurrentTime);
13210 #endif /* ! 0 */
13211 }
13212
13213 void
13214 x_unfocus_frame (f)
13215 struct frame *f;
13216 {
13217 #if 0
13218 /* Look at the remarks in x_focus_on_frame. */
13219 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
13220 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
13221 RevertToPointerRoot, CurrentTime);
13222 #endif /* ! 0 */
13223 }
13224
13225 /* Raise frame F. */
13226
13227 void
13228 x_raise_frame (f)
13229 struct frame *f;
13230 {
13231 if (f->async_visible)
13232 {
13233 BLOCK_INPUT;
13234 #ifdef USE_X_TOOLKIT
13235 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13236 #else /* not USE_X_TOOLKIT */
13237 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13238 #endif /* not USE_X_TOOLKIT */
13239 XFlush (FRAME_X_DISPLAY (f));
13240 UNBLOCK_INPUT;
13241 }
13242 }
13243
13244 /* Lower frame F. */
13245
13246 void
13247 x_lower_frame (f)
13248 struct frame *f;
13249 {
13250 if (f->async_visible)
13251 {
13252 BLOCK_INPUT;
13253 #ifdef USE_X_TOOLKIT
13254 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13255 #else /* not USE_X_TOOLKIT */
13256 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13257 #endif /* not USE_X_TOOLKIT */
13258 XFlush (FRAME_X_DISPLAY (f));
13259 UNBLOCK_INPUT;
13260 }
13261 }
13262
13263 static void
13264 XTframe_raise_lower (f, raise_flag)
13265 FRAME_PTR f;
13266 int raise_flag;
13267 {
13268 if (raise_flag)
13269 x_raise_frame (f);
13270 else
13271 x_lower_frame (f);
13272 }
13273 \f
13274 /* Change of visibility. */
13275
13276 /* This tries to wait until the frame is really visible.
13277 However, if the window manager asks the user where to position
13278 the frame, this will return before the user finishes doing that.
13279 The frame will not actually be visible at that time,
13280 but it will become visible later when the window manager
13281 finishes with it. */
13282
13283 void
13284 x_make_frame_visible (f)
13285 struct frame *f;
13286 {
13287 Lisp_Object type;
13288 int original_top, original_left;
13289 int retry_count = 2;
13290
13291 retry:
13292
13293 BLOCK_INPUT;
13294
13295 type = x_icon_type (f);
13296 if (!NILP (type))
13297 x_bitmap_icon (f, type);
13298
13299 if (! FRAME_VISIBLE_P (f))
13300 {
13301 /* We test FRAME_GARBAGED_P here to make sure we don't
13302 call x_set_offset a second time
13303 if we get to x_make_frame_visible a second time
13304 before the window gets really visible. */
13305 if (! FRAME_ICONIFIED_P (f)
13306 && ! f->output_data.x->asked_for_visible)
13307 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13308
13309 f->output_data.x->asked_for_visible = 1;
13310
13311 if (! EQ (Vx_no_window_manager, Qt))
13312 x_wm_set_window_state (f, NormalState);
13313 #ifdef USE_X_TOOLKIT
13314 /* This was XtPopup, but that did nothing for an iconified frame. */
13315 XtMapWidget (f->output_data.x->widget);
13316 #else /* not USE_X_TOOLKIT */
13317 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13318 #endif /* not USE_X_TOOLKIT */
13319 #if 0 /* This seems to bring back scroll bars in the wrong places
13320 if the window configuration has changed. They seem
13321 to come back ok without this. */
13322 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
13323 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13324 #endif
13325 }
13326
13327 XFlush (FRAME_X_DISPLAY (f));
13328
13329 /* Synchronize to ensure Emacs knows the frame is visible
13330 before we do anything else. We do this loop with input not blocked
13331 so that incoming events are handled. */
13332 {
13333 Lisp_Object frame;
13334 int count;
13335 /* This must be before UNBLOCK_INPUT
13336 since events that arrive in response to the actions above
13337 will set it when they are handled. */
13338 int previously_visible = f->output_data.x->has_been_visible;
13339
13340 original_left = f->output_data.x->left_pos;
13341 original_top = f->output_data.x->top_pos;
13342
13343 /* This must come after we set COUNT. */
13344 UNBLOCK_INPUT;
13345
13346 /* We unblock here so that arriving X events are processed. */
13347
13348 /* Now move the window back to where it was "supposed to be".
13349 But don't do it if the gravity is negative.
13350 When the gravity is negative, this uses a position
13351 that is 3 pixels too low. Perhaps that's really the border width.
13352
13353 Don't do this if the window has never been visible before,
13354 because the window manager may choose the position
13355 and we don't want to override it. */
13356
13357 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
13358 && f->output_data.x->win_gravity == NorthWestGravity
13359 && previously_visible)
13360 {
13361 Drawable rootw;
13362 int x, y;
13363 unsigned int width, height, border, depth;
13364
13365 BLOCK_INPUT;
13366
13367 /* On some window managers (such as FVWM) moving an existing
13368 window, even to the same place, causes the window manager
13369 to introduce an offset. This can cause the window to move
13370 to an unexpected location. Check the geometry (a little
13371 slow here) and then verify that the window is in the right
13372 place. If the window is not in the right place, move it
13373 there, and take the potential window manager hit. */
13374 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13375 &rootw, &x, &y, &width, &height, &border, &depth);
13376
13377 if (original_left != x || original_top != y)
13378 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13379 original_left, original_top);
13380
13381 UNBLOCK_INPUT;
13382 }
13383
13384 XSETFRAME (frame, f);
13385
13386 /* Wait until the frame is visible. Process X events until a
13387 MapNotify event has been seen, or until we think we won't get a
13388 MapNotify at all.. */
13389 for (count = input_signal_count + 10;
13390 input_signal_count < count && !FRAME_VISIBLE_P (f);)
13391 {
13392 /* Force processing of queued events. */
13393 x_sync (f);
13394
13395 /* Machines that do polling rather than SIGIO have been
13396 observed to go into a busy-wait here. So we'll fake an
13397 alarm signal to let the handler know that there's something
13398 to be read. We used to raise a real alarm, but it seems
13399 that the handler isn't always enabled here. This is
13400 probably a bug. */
13401 if (input_polling_used ())
13402 {
13403 /* It could be confusing if a real alarm arrives while
13404 processing the fake one. Turn it off and let the
13405 handler reset it. */
13406 extern void poll_for_input_1 P_ ((void));
13407 int old_poll_suppress_count = poll_suppress_count;
13408 poll_suppress_count = 1;
13409 poll_for_input_1 ();
13410 poll_suppress_count = old_poll_suppress_count;
13411 }
13412
13413 /* See if a MapNotify event has been processed. */
13414 FRAME_SAMPLE_VISIBILITY (f);
13415 }
13416
13417 /* 2000-09-28: In
13418
13419 (let ((f (selected-frame)))
13420 (iconify-frame f)
13421 (raise-frame f))
13422
13423 the frame is not raised with various window managers on
13424 FreeBSD, Linux and Solaris. It turns out that, for some
13425 unknown reason, the call to XtMapWidget is completely ignored.
13426 Mapping the widget a second time works. */
13427
13428 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
13429 goto retry;
13430 }
13431 }
13432
13433 /* Change from mapped state to withdrawn state. */
13434
13435 /* Make the frame visible (mapped and not iconified). */
13436
13437 void
13438 x_make_frame_invisible (f)
13439 struct frame *f;
13440 {
13441 Window window;
13442
13443 #ifdef USE_X_TOOLKIT
13444 /* Use the frame's outermost window, not the one we normally draw on. */
13445 window = XtWindow (f->output_data.x->widget);
13446 #else /* not USE_X_TOOLKIT */
13447 window = FRAME_X_WINDOW (f);
13448 #endif /* not USE_X_TOOLKIT */
13449
13450 /* Don't keep the highlight on an invisible frame. */
13451 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13452 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13453
13454 #if 0/* This might add unreliability; I don't trust it -- rms. */
13455 if (! f->async_visible && ! f->async_iconified)
13456 return;
13457 #endif
13458
13459 BLOCK_INPUT;
13460
13461 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13462 that the current position of the window is user-specified, rather than
13463 program-specified, so that when the window is mapped again, it will be
13464 placed at the same location, without forcing the user to position it
13465 by hand again (they have already done that once for this window.) */
13466 x_wm_set_size_hint (f, (long) 0, 1);
13467
13468 #ifdef HAVE_X11R4
13469
13470 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
13471 DefaultScreen (FRAME_X_DISPLAY (f))))
13472 {
13473 UNBLOCK_INPUT_RESIGNAL;
13474 error ("Can't notify window manager of window withdrawal");
13475 }
13476 #else /* ! defined (HAVE_X11R4) */
13477
13478 /* Tell the window manager what we're going to do. */
13479 if (! EQ (Vx_no_window_manager, Qt))
13480 {
13481 XEvent unmap;
13482
13483 unmap.xunmap.type = UnmapNotify;
13484 unmap.xunmap.window = window;
13485 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
13486 unmap.xunmap.from_configure = False;
13487 if (! XSendEvent (FRAME_X_DISPLAY (f),
13488 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13489 False,
13490 SubstructureRedirectMaskSubstructureNotifyMask,
13491 &unmap))
13492 {
13493 UNBLOCK_INPUT_RESIGNAL;
13494 error ("Can't notify window manager of withdrawal");
13495 }
13496 }
13497
13498 /* Unmap the window ourselves. Cheeky! */
13499 XUnmapWindow (FRAME_X_DISPLAY (f), window);
13500 #endif /* ! defined (HAVE_X11R4) */
13501
13502 /* We can't distinguish this from iconification
13503 just by the event that we get from the server.
13504 So we can't win using the usual strategy of letting
13505 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13506 and synchronize with the server to make sure we agree. */
13507 f->visible = 0;
13508 FRAME_ICONIFIED_P (f) = 0;
13509 f->async_visible = 0;
13510 f->async_iconified = 0;
13511
13512 x_sync (f);
13513
13514 UNBLOCK_INPUT;
13515 }
13516
13517 /* Change window state from mapped to iconified. */
13518
13519 void
13520 x_iconify_frame (f)
13521 struct frame *f;
13522 {
13523 int result;
13524 Lisp_Object type;
13525
13526 /* Don't keep the highlight on an invisible frame. */
13527 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13528 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13529
13530 if (f->async_iconified)
13531 return;
13532
13533 BLOCK_INPUT;
13534
13535 FRAME_SAMPLE_VISIBILITY (f);
13536
13537 type = x_icon_type (f);
13538 if (!NILP (type))
13539 x_bitmap_icon (f, type);
13540
13541 #ifdef USE_X_TOOLKIT
13542
13543 if (! FRAME_VISIBLE_P (f))
13544 {
13545 if (! EQ (Vx_no_window_manager, Qt))
13546 x_wm_set_window_state (f, IconicState);
13547 /* This was XtPopup, but that did nothing for an iconified frame. */
13548 XtMapWidget (f->output_data.x->widget);
13549 /* The server won't give us any event to indicate
13550 that an invisible frame was changed to an icon,
13551 so we have to record it here. */
13552 f->iconified = 1;
13553 f->visible = 1;
13554 f->async_iconified = 1;
13555 f->async_visible = 0;
13556 UNBLOCK_INPUT;
13557 return;
13558 }
13559
13560 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13561 XtWindow (f->output_data.x->widget),
13562 DefaultScreen (FRAME_X_DISPLAY (f)));
13563 UNBLOCK_INPUT;
13564
13565 if (!result)
13566 error ("Can't notify window manager of iconification");
13567
13568 f->async_iconified = 1;
13569 f->async_visible = 0;
13570
13571
13572 BLOCK_INPUT;
13573 XFlush (FRAME_X_DISPLAY (f));
13574 UNBLOCK_INPUT;
13575 #else /* not USE_X_TOOLKIT */
13576
13577 /* Make sure the X server knows where the window should be positioned,
13578 in case the user deiconifies with the window manager. */
13579 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13580 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13581
13582 /* Since we don't know which revision of X we're running, we'll use both
13583 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13584
13585 /* X11R4: send a ClientMessage to the window manager using the
13586 WM_CHANGE_STATE type. */
13587 {
13588 XEvent message;
13589
13590 message.xclient.window = FRAME_X_WINDOW (f);
13591 message.xclient.type = ClientMessage;
13592 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13593 message.xclient.format = 32;
13594 message.xclient.data.l[0] = IconicState;
13595
13596 if (! XSendEvent (FRAME_X_DISPLAY (f),
13597 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13598 False,
13599 SubstructureRedirectMask | SubstructureNotifyMask,
13600 &message))
13601 {
13602 UNBLOCK_INPUT_RESIGNAL;
13603 error ("Can't notify window manager of iconification");
13604 }
13605 }
13606
13607 /* X11R3: set the initial_state field of the window manager hints to
13608 IconicState. */
13609 x_wm_set_window_state (f, IconicState);
13610
13611 if (!FRAME_VISIBLE_P (f))
13612 {
13613 /* If the frame was withdrawn, before, we must map it. */
13614 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13615 }
13616
13617 f->async_iconified = 1;
13618 f->async_visible = 0;
13619
13620 XFlush (FRAME_X_DISPLAY (f));
13621 UNBLOCK_INPUT;
13622 #endif /* not USE_X_TOOLKIT */
13623 }
13624
13625 \f
13626 /* Free X resources of frame F. */
13627
13628 void
13629 x_free_frame_resources (f)
13630 struct frame *f;
13631 {
13632 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13633 Lisp_Object bar;
13634 struct scroll_bar *b;
13635
13636 BLOCK_INPUT;
13637
13638 /* If a display connection is dead, don't try sending more
13639 commands to the X server. */
13640 if (dpyinfo->display)
13641 {
13642 if (f->output_data.x->icon_desc)
13643 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13644
13645 #ifdef USE_X_TOOLKIT
13646 /* Explicitly destroy the scroll bars of the frame. Without
13647 this, we get "BadDrawable" errors from the toolkit later on,
13648 presumably from expose events generated for the disappearing
13649 toolkit scroll bars. */
13650 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
13651 {
13652 b = XSCROLL_BAR (bar);
13653 x_scroll_bar_remove (b);
13654 }
13655 #endif
13656
13657 #ifdef HAVE_X_I18N
13658 if (FRAME_XIC (f))
13659 free_frame_xic (f);
13660 #endif
13661
13662 #ifdef USE_X_TOOLKIT
13663 if (f->output_data.x->widget)
13664 {
13665 XtDestroyWidget (f->output_data.x->widget);
13666 f->output_data.x->widget = NULL;
13667 }
13668 /* Tooltips don't have widgets, only a simple X window, even if
13669 we are using a toolkit. */
13670 else if (FRAME_X_WINDOW (f))
13671 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13672
13673 free_frame_menubar (f);
13674 #else /* !USE_X_TOOLKIT */
13675 if (FRAME_X_WINDOW (f))
13676 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13677 #endif /* !USE_X_TOOLKIT */
13678
13679 unload_color (f, f->output_data.x->foreground_pixel);
13680 unload_color (f, f->output_data.x->background_pixel);
13681 unload_color (f, f->output_data.x->cursor_pixel);
13682 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13683 unload_color (f, f->output_data.x->border_pixel);
13684 unload_color (f, f->output_data.x->mouse_pixel);
13685
13686 if (f->output_data.x->scroll_bar_background_pixel != -1)
13687 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13688 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13689 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13690 #ifdef USE_TOOLKIT_SCROLL_BARS
13691 /* Scrollbar shadow colors. */
13692 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13693 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13694 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13695 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13696 #endif /* USE_TOOLKIT_SCROLL_BARS */
13697 if (f->output_data.x->white_relief.allocated_p)
13698 unload_color (f, f->output_data.x->white_relief.pixel);
13699 if (f->output_data.x->black_relief.allocated_p)
13700 unload_color (f, f->output_data.x->black_relief.pixel);
13701
13702 if (FRAME_FACE_CACHE (f))
13703 free_frame_faces (f);
13704
13705 x_free_gcs (f);
13706 XFlush (FRAME_X_DISPLAY (f));
13707 }
13708
13709 if (f->output_data.x->saved_menu_event)
13710 xfree (f->output_data.x->saved_menu_event);
13711
13712 xfree (f->output_data.x);
13713 f->output_data.x = NULL;
13714
13715 if (f == dpyinfo->x_focus_frame)
13716 dpyinfo->x_focus_frame = 0;
13717 if (f == dpyinfo->x_focus_event_frame)
13718 dpyinfo->x_focus_event_frame = 0;
13719 if (f == dpyinfo->x_highlight_frame)
13720 dpyinfo->x_highlight_frame = 0;
13721
13722 if (f == dpyinfo->mouse_face_mouse_frame)
13723 {
13724 dpyinfo->mouse_face_beg_row
13725 = dpyinfo->mouse_face_beg_col = -1;
13726 dpyinfo->mouse_face_end_row
13727 = dpyinfo->mouse_face_end_col = -1;
13728 dpyinfo->mouse_face_window = Qnil;
13729 dpyinfo->mouse_face_deferred_gc = 0;
13730 dpyinfo->mouse_face_mouse_frame = 0;
13731 }
13732
13733 UNBLOCK_INPUT;
13734 }
13735
13736
13737 /* Destroy the X window of frame F. */
13738
13739 void
13740 x_destroy_window (f)
13741 struct frame *f;
13742 {
13743 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13744
13745 /* If a display connection is dead, don't try sending more
13746 commands to the X server. */
13747 if (dpyinfo->display != 0)
13748 x_free_frame_resources (f);
13749
13750 dpyinfo->reference_count--;
13751 }
13752
13753 \f
13754 /* Setting window manager hints. */
13755
13756 /* Set the normal size hints for the window manager, for frame F.
13757 FLAGS is the flags word to use--or 0 meaning preserve the flags
13758 that the window now has.
13759 If USER_POSITION is nonzero, we set the USPosition
13760 flag (this is useful when FLAGS is 0). */
13761
13762 void
13763 x_wm_set_size_hint (f, flags, user_position)
13764 struct frame *f;
13765 long flags;
13766 int user_position;
13767 {
13768 XSizeHints size_hints;
13769
13770 #ifdef USE_X_TOOLKIT
13771 Arg al[2];
13772 int ac = 0;
13773 Dimension widget_width, widget_height;
13774 Window window = XtWindow (f->output_data.x->widget);
13775 #else /* not USE_X_TOOLKIT */
13776 Window window = FRAME_X_WINDOW (f);
13777 #endif /* not USE_X_TOOLKIT */
13778
13779 /* Setting PMaxSize caused various problems. */
13780 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13781
13782 size_hints.x = f->output_data.x->left_pos;
13783 size_hints.y = f->output_data.x->top_pos;
13784
13785 #ifdef USE_X_TOOLKIT
13786 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13787 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13788 XtGetValues (f->output_data.x->widget, al, ac);
13789 size_hints.height = widget_height;
13790 size_hints.width = widget_width;
13791 #else /* not USE_X_TOOLKIT */
13792 size_hints.height = PIXEL_HEIGHT (f);
13793 size_hints.width = PIXEL_WIDTH (f);
13794 #endif /* not USE_X_TOOLKIT */
13795
13796 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13797 size_hints.height_inc = f->output_data.x->line_height;
13798 size_hints.max_width
13799 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13800 size_hints.max_height
13801 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13802
13803 /* Calculate the base and minimum sizes.
13804
13805 (When we use the X toolkit, we don't do it here.
13806 Instead we copy the values that the widgets are using, below.) */
13807 #ifndef USE_X_TOOLKIT
13808 {
13809 int base_width, base_height;
13810 int min_rows = 0, min_cols = 0;
13811
13812 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13813 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13814
13815 check_frame_size (f, &min_rows, &min_cols);
13816
13817 /* The window manager uses the base width hints to calculate the
13818 current number of rows and columns in the frame while
13819 resizing; min_width and min_height aren't useful for this
13820 purpose, since they might not give the dimensions for a
13821 zero-row, zero-column frame.
13822
13823 We use the base_width and base_height members if we have
13824 them; otherwise, we set the min_width and min_height members
13825 to the size for a zero x zero frame. */
13826
13827 #ifdef HAVE_X11R4
13828 size_hints.flags |= PBaseSize;
13829 size_hints.base_width = base_width;
13830 size_hints.base_height = base_height;
13831 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13832 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13833 #else
13834 size_hints.min_width = base_width;
13835 size_hints.min_height = base_height;
13836 #endif
13837 }
13838
13839 /* If we don't need the old flags, we don't need the old hint at all. */
13840 if (flags)
13841 {
13842 size_hints.flags |= flags;
13843 goto no_read;
13844 }
13845 #endif /* not USE_X_TOOLKIT */
13846
13847 {
13848 XSizeHints hints; /* Sometimes I hate X Windows... */
13849 long supplied_return;
13850 int value;
13851
13852 #ifdef HAVE_X11R4
13853 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13854 &supplied_return);
13855 #else
13856 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13857 #endif
13858
13859 #ifdef USE_X_TOOLKIT
13860 size_hints.base_height = hints.base_height;
13861 size_hints.base_width = hints.base_width;
13862 size_hints.min_height = hints.min_height;
13863 size_hints.min_width = hints.min_width;
13864 #endif
13865
13866 if (flags)
13867 size_hints.flags |= flags;
13868 else
13869 {
13870 if (value == 0)
13871 hints.flags = 0;
13872 if (hints.flags & PSize)
13873 size_hints.flags |= PSize;
13874 if (hints.flags & PPosition)
13875 size_hints.flags |= PPosition;
13876 if (hints.flags & USPosition)
13877 size_hints.flags |= USPosition;
13878 if (hints.flags & USSize)
13879 size_hints.flags |= USSize;
13880 }
13881 }
13882
13883 #ifndef USE_X_TOOLKIT
13884 no_read:
13885 #endif
13886
13887 #ifdef PWinGravity
13888 size_hints.win_gravity = f->output_data.x->win_gravity;
13889 size_hints.flags |= PWinGravity;
13890
13891 if (user_position)
13892 {
13893 size_hints.flags &= ~ PPosition;
13894 size_hints.flags |= USPosition;
13895 }
13896 #endif /* PWinGravity */
13897
13898 #ifdef HAVE_X11R4
13899 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13900 #else
13901 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13902 #endif
13903 }
13904
13905 /* Used for IconicState or NormalState */
13906
13907 void
13908 x_wm_set_window_state (f, state)
13909 struct frame *f;
13910 int state;
13911 {
13912 #ifdef USE_X_TOOLKIT
13913 Arg al[1];
13914
13915 XtSetArg (al[0], XtNinitialState, state);
13916 XtSetValues (f->output_data.x->widget, al, 1);
13917 #else /* not USE_X_TOOLKIT */
13918 Window window = FRAME_X_WINDOW (f);
13919
13920 f->output_data.x->wm_hints.flags |= StateHint;
13921 f->output_data.x->wm_hints.initial_state = state;
13922
13923 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13924 #endif /* not USE_X_TOOLKIT */
13925 }
13926
13927 void
13928 x_wm_set_icon_pixmap (f, pixmap_id)
13929 struct frame *f;
13930 int pixmap_id;
13931 {
13932 Pixmap icon_pixmap;
13933
13934 #ifndef USE_X_TOOLKIT
13935 Window window = FRAME_X_WINDOW (f);
13936 #endif
13937
13938 if (pixmap_id > 0)
13939 {
13940 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13941 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13942 }
13943 else
13944 {
13945 /* It seems there is no way to turn off use of an icon pixmap.
13946 The following line does it, only if no icon has yet been created,
13947 for some window managers. But with mwm it crashes.
13948 Some people say it should clear the IconPixmapHint bit in this case,
13949 but that doesn't work, and the X consortium said it isn't the
13950 right thing at all. Since there is no way to win,
13951 best to explicitly give up. */
13952 #if 0
13953 f->output_data.x->wm_hints.icon_pixmap = None;
13954 #else
13955 return;
13956 #endif
13957 }
13958
13959 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13960
13961 {
13962 Arg al[1];
13963 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13964 XtSetValues (f->output_data.x->widget, al, 1);
13965 }
13966
13967 #else /* not USE_X_TOOLKIT */
13968
13969 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13970 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13971
13972 #endif /* not USE_X_TOOLKIT */
13973 }
13974
13975 void
13976 x_wm_set_icon_position (f, icon_x, icon_y)
13977 struct frame *f;
13978 int icon_x, icon_y;
13979 {
13980 #ifdef USE_X_TOOLKIT
13981 Window window = XtWindow (f->output_data.x->widget);
13982 #else
13983 Window window = FRAME_X_WINDOW (f);
13984 #endif
13985
13986 f->output_data.x->wm_hints.flags |= IconPositionHint;
13987 f->output_data.x->wm_hints.icon_x = icon_x;
13988 f->output_data.x->wm_hints.icon_y = icon_y;
13989
13990 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13991 }
13992
13993 \f
13994 /***********************************************************************
13995 Fonts
13996 ***********************************************************************/
13997
13998 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13999
14000 struct font_info *
14001 x_get_font_info (f, font_idx)
14002 FRAME_PTR f;
14003 int font_idx;
14004 {
14005 return (FRAME_X_FONT_TABLE (f) + font_idx);
14006 }
14007
14008
14009 /* Return a list of names of available fonts matching PATTERN on frame F.
14010
14011 If SIZE is > 0, it is the size (maximum bounds width) of fonts
14012 to be listed.
14013
14014 SIZE < 0 means include scalable fonts.
14015
14016 Frame F null means we have not yet created any frame on X, and
14017 consult the first display in x_display_list. MAXNAMES sets a limit
14018 on how many fonts to match. */
14019
14020 Lisp_Object
14021 x_list_fonts (f, pattern, size, maxnames)
14022 struct frame *f;
14023 Lisp_Object pattern;
14024 int size;
14025 int maxnames;
14026 {
14027 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
14028 Lisp_Object tem, second_best;
14029 struct x_display_info *dpyinfo
14030 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
14031 Display *dpy = dpyinfo->display;
14032 int try_XLoadQueryFont = 0;
14033 int count;
14034 int allow_scalable_fonts_p = 0;
14035
14036 if (size < 0)
14037 {
14038 allow_scalable_fonts_p = 1;
14039 size = 0;
14040 }
14041
14042 patterns = Fassoc (pattern, Valternate_fontname_alist);
14043 if (NILP (patterns))
14044 patterns = Fcons (pattern, Qnil);
14045
14046 if (maxnames == 1 && !size)
14047 /* We can return any single font matching PATTERN. */
14048 try_XLoadQueryFont = 1;
14049
14050 for (; CONSP (patterns); patterns = XCDR (patterns))
14051 {
14052 int num_fonts;
14053 char **names = NULL;
14054
14055 pattern = XCAR (patterns);
14056 /* See if we cached the result for this particular query.
14057 The cache is an alist of the form:
14058 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
14059 tem = XCDR (dpyinfo->name_list_element);
14060 key = Fcons (Fcons (pattern, make_number (maxnames)),
14061 allow_scalable_fonts_p ? Qt : Qnil);
14062 list = Fassoc (key, tem);
14063 if (!NILP (list))
14064 {
14065 list = Fcdr_safe (list);
14066 /* We have a cashed list. Don't have to get the list again. */
14067 goto label_cached;
14068 }
14069
14070 /* At first, put PATTERN in the cache. */
14071
14072 BLOCK_INPUT;
14073 count = x_catch_errors (dpy);
14074
14075 if (try_XLoadQueryFont)
14076 {
14077 XFontStruct *font;
14078 unsigned long value;
14079
14080 font = XLoadQueryFont (dpy, SDATA (pattern));
14081 if (x_had_errors_p (dpy))
14082 {
14083 /* This error is perhaps due to insufficient memory on X
14084 server. Let's just ignore it. */
14085 font = NULL;
14086 x_clear_errors (dpy);
14087 }
14088
14089 if (font
14090 && XGetFontProperty (font, XA_FONT, &value))
14091 {
14092 char *name = (char *) XGetAtomName (dpy, (Atom) value);
14093 int len = strlen (name);
14094 char *tmp;
14095
14096 /* If DXPC (a Differential X Protocol Compressor)
14097 Ver.3.7 is running, XGetAtomName will return null
14098 string. We must avoid such a name. */
14099 if (len == 0)
14100 try_XLoadQueryFont = 0;
14101 else
14102 {
14103 num_fonts = 1;
14104 names = (char **) alloca (sizeof (char *));
14105 /* Some systems only allow alloca assigned to a
14106 simple var. */
14107 tmp = (char *) alloca (len + 1); names[0] = tmp;
14108 bcopy (name, names[0], len + 1);
14109 XFree (name);
14110 }
14111 }
14112 else
14113 try_XLoadQueryFont = 0;
14114
14115 if (font)
14116 XFreeFont (dpy, font);
14117 }
14118
14119 if (!try_XLoadQueryFont)
14120 {
14121 /* We try at least 10 fonts because XListFonts will return
14122 auto-scaled fonts at the head. */
14123 names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
14124 &num_fonts);
14125 if (x_had_errors_p (dpy))
14126 {
14127 /* This error is perhaps due to insufficient memory on X
14128 server. Let's just ignore it. */
14129 names = NULL;
14130 x_clear_errors (dpy);
14131 }
14132 }
14133
14134 x_uncatch_errors (dpy, count);
14135 UNBLOCK_INPUT;
14136
14137 if (names)
14138 {
14139 int i;
14140
14141 /* Make a list of all the fonts we got back.
14142 Store that in the font cache for the display. */
14143 for (i = 0; i < num_fonts; i++)
14144 {
14145 int width = 0;
14146 char *p = names[i];
14147 int average_width = -1, dashes = 0;
14148
14149 /* Count the number of dashes in NAMES[I]. If there are
14150 14 dashes, and the field value following 12th dash
14151 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
14152 is usually too ugly to be used for editing. Let's
14153 ignore it. */
14154 while (*p)
14155 if (*p++ == '-')
14156 {
14157 dashes++;
14158 if (dashes == 7) /* PIXEL_SIZE field */
14159 width = atoi (p);
14160 else if (dashes == 12) /* AVERAGE_WIDTH field */
14161 average_width = atoi (p);
14162 }
14163
14164 if (allow_scalable_fonts_p
14165 || dashes < 14 || average_width != 0)
14166 {
14167 tem = build_string (names[i]);
14168 if (NILP (Fassoc (tem, list)))
14169 {
14170 if (STRINGP (Vx_pixel_size_width_font_regexp)
14171 && ((fast_c_string_match_ignore_case
14172 (Vx_pixel_size_width_font_regexp, names[i]))
14173 >= 0))
14174 /* We can set the value of PIXEL_SIZE to the
14175 width of this font. */
14176 list = Fcons (Fcons (tem, make_number (width)), list);
14177 else
14178 /* For the moment, width is not known. */
14179 list = Fcons (Fcons (tem, Qnil), list);
14180 }
14181 }
14182 }
14183
14184 if (!try_XLoadQueryFont)
14185 {
14186 BLOCK_INPUT;
14187 XFreeFontNames (names);
14188 UNBLOCK_INPUT;
14189 }
14190 }
14191
14192 /* Now store the result in the cache. */
14193 XSETCDR (dpyinfo->name_list_element,
14194 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
14195
14196 label_cached:
14197 if (NILP (list)) continue; /* Try the remaining alternatives. */
14198
14199 newlist = second_best = Qnil;
14200 /* Make a list of the fonts that have the right width. */
14201 for (; CONSP (list); list = XCDR (list))
14202 {
14203 int found_size;
14204
14205 tem = XCAR (list);
14206
14207 if (!CONSP (tem) || NILP (XCAR (tem)))
14208 continue;
14209 if (!size)
14210 {
14211 newlist = Fcons (XCAR (tem), newlist);
14212 continue;
14213 }
14214
14215 if (!INTEGERP (XCDR (tem)))
14216 {
14217 /* Since we have not yet known the size of this font, we
14218 must try slow function call XLoadQueryFont. */
14219 XFontStruct *thisinfo;
14220
14221 BLOCK_INPUT;
14222 count = x_catch_errors (dpy);
14223 thisinfo = XLoadQueryFont (dpy,
14224 SDATA (XCAR (tem)));
14225 if (x_had_errors_p (dpy))
14226 {
14227 /* This error is perhaps due to insufficient memory on X
14228 server. Let's just ignore it. */
14229 thisinfo = NULL;
14230 x_clear_errors (dpy);
14231 }
14232 x_uncatch_errors (dpy, count);
14233 UNBLOCK_INPUT;
14234
14235 if (thisinfo)
14236 {
14237 XSETCDR (tem,
14238 (thisinfo->min_bounds.width == 0
14239 ? make_number (0)
14240 : make_number (thisinfo->max_bounds.width)));
14241 BLOCK_INPUT;
14242 XFreeFont (dpy, thisinfo);
14243 UNBLOCK_INPUT;
14244 }
14245 else
14246 /* For unknown reason, the previous call of XListFont had
14247 returned a font which can't be opened. Record the size
14248 as 0 not to try to open it again. */
14249 XSETCDR (tem, make_number (0));
14250 }
14251
14252 found_size = XINT (XCDR (tem));
14253 if (found_size == size)
14254 newlist = Fcons (XCAR (tem), newlist);
14255 else if (found_size > 0)
14256 {
14257 if (NILP (second_best))
14258 second_best = tem;
14259 else if (found_size < size)
14260 {
14261 if (XINT (XCDR (second_best)) > size
14262 || XINT (XCDR (second_best)) < found_size)
14263 second_best = tem;
14264 }
14265 else
14266 {
14267 if (XINT (XCDR (second_best)) > size
14268 && XINT (XCDR (second_best)) > found_size)
14269 second_best = tem;
14270 }
14271 }
14272 }
14273 if (!NILP (newlist))
14274 break;
14275 else if (!NILP (second_best))
14276 {
14277 newlist = Fcons (XCAR (second_best), Qnil);
14278 break;
14279 }
14280 }
14281
14282 return newlist;
14283 }
14284
14285
14286 #if GLYPH_DEBUG
14287
14288 /* Check that FONT is valid on frame F. It is if it can be found in F's
14289 font table. */
14290
14291 static void
14292 x_check_font (f, font)
14293 struct frame *f;
14294 XFontStruct *font;
14295 {
14296 int i;
14297 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14298
14299 xassert (font != NULL);
14300
14301 for (i = 0; i < dpyinfo->n_fonts; i++)
14302 if (dpyinfo->font_table[i].name
14303 && font == dpyinfo->font_table[i].font)
14304 break;
14305
14306 xassert (i < dpyinfo->n_fonts);
14307 }
14308
14309 #endif /* GLYPH_DEBUG != 0 */
14310
14311 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14312 Note: There are (broken) X fonts out there with invalid XFontStruct
14313 min_bounds contents. For example, handa@etl.go.jp reports that
14314 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14315 have font->min_bounds.width == 0. */
14316
14317 static INLINE void
14318 x_font_min_bounds (font, w, h)
14319 XFontStruct *font;
14320 int *w, *h;
14321 {
14322 *h = FONT_HEIGHT (font);
14323 *w = font->min_bounds.width;
14324
14325 /* Try to handle the case where FONT->min_bounds has invalid
14326 contents. Since the only font known to have invalid min_bounds
14327 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14328 if (*w <= 0)
14329 *w = font->max_bounds.width;
14330 }
14331
14332
14333 /* Compute the smallest character width and smallest font height over
14334 all fonts available on frame F. Set the members smallest_char_width
14335 and smallest_font_height in F's x_display_info structure to
14336 the values computed. Value is non-zero if smallest_font_height or
14337 smallest_char_width become smaller than they were before. */
14338
14339 static int
14340 x_compute_min_glyph_bounds (f)
14341 struct frame *f;
14342 {
14343 int i;
14344 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14345 XFontStruct *font;
14346 int old_width = dpyinfo->smallest_char_width;
14347 int old_height = dpyinfo->smallest_font_height;
14348
14349 dpyinfo->smallest_font_height = 100000;
14350 dpyinfo->smallest_char_width = 100000;
14351
14352 for (i = 0; i < dpyinfo->n_fonts; ++i)
14353 if (dpyinfo->font_table[i].name)
14354 {
14355 struct font_info *fontp = dpyinfo->font_table + i;
14356 int w, h;
14357
14358 font = (XFontStruct *) fontp->font;
14359 xassert (font != (XFontStruct *) ~0);
14360 x_font_min_bounds (font, &w, &h);
14361
14362 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
14363 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
14364 }
14365
14366 xassert (dpyinfo->smallest_char_width > 0
14367 && dpyinfo->smallest_font_height > 0);
14368
14369 return (dpyinfo->n_fonts == 1
14370 || dpyinfo->smallest_char_width < old_width
14371 || dpyinfo->smallest_font_height < old_height);
14372 }
14373
14374
14375 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14376 pointer to the structure font_info while allocating it dynamically.
14377 If SIZE is 0, load any size of font.
14378 If loading is failed, return NULL. */
14379
14380 struct font_info *
14381 x_load_font (f, fontname, size)
14382 struct frame *f;
14383 register char *fontname;
14384 int size;
14385 {
14386 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14387 Lisp_Object font_names;
14388 int count;
14389
14390 /* Get a list of all the fonts that match this name. Once we
14391 have a list of matching fonts, we compare them against the fonts
14392 we already have by comparing names. */
14393 font_names = x_list_fonts (f, build_string (fontname), size, 1);
14394
14395 if (!NILP (font_names))
14396 {
14397 Lisp_Object tail;
14398 int i;
14399
14400 for (i = 0; i < dpyinfo->n_fonts; i++)
14401 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
14402 if (dpyinfo->font_table[i].name
14403 && (!strcmp (dpyinfo->font_table[i].name,
14404 SDATA (XCAR (tail)))
14405 || !strcmp (dpyinfo->font_table[i].full_name,
14406 SDATA (XCAR (tail)))))
14407 return (dpyinfo->font_table + i);
14408 }
14409
14410 /* Load the font and add it to the table. */
14411 {
14412 char *full_name;
14413 XFontStruct *font;
14414 struct font_info *fontp;
14415 unsigned long value;
14416 int i;
14417
14418 /* If we have found fonts by x_list_font, load one of them. If
14419 not, we still try to load a font by the name given as FONTNAME
14420 because XListFonts (called in x_list_font) of some X server has
14421 a bug of not finding a font even if the font surely exists and
14422 is loadable by XLoadQueryFont. */
14423 if (size > 0 && !NILP (font_names))
14424 fontname = (char *) SDATA (XCAR (font_names));
14425
14426 BLOCK_INPUT;
14427 count = x_catch_errors (FRAME_X_DISPLAY (f));
14428 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
14429 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
14430 {
14431 /* This error is perhaps due to insufficient memory on X
14432 server. Let's just ignore it. */
14433 font = NULL;
14434 x_clear_errors (FRAME_X_DISPLAY (f));
14435 }
14436 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
14437 UNBLOCK_INPUT;
14438 if (!font)
14439 return NULL;
14440
14441 /* Find a free slot in the font table. */
14442 for (i = 0; i < dpyinfo->n_fonts; ++i)
14443 if (dpyinfo->font_table[i].name == NULL)
14444 break;
14445
14446 /* If no free slot found, maybe enlarge the font table. */
14447 if (i == dpyinfo->n_fonts
14448 && dpyinfo->n_fonts == dpyinfo->font_table_size)
14449 {
14450 int sz;
14451 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
14452 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
14453 dpyinfo->font_table
14454 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
14455 }
14456
14457 fontp = dpyinfo->font_table + i;
14458 if (i == dpyinfo->n_fonts)
14459 ++dpyinfo->n_fonts;
14460
14461 /* Now fill in the slots of *FONTP. */
14462 BLOCK_INPUT;
14463 fontp->font = font;
14464 fontp->font_idx = i;
14465 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
14466 bcopy (fontname, fontp->name, strlen (fontname) + 1);
14467
14468 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14469 full_name = 0;
14470 if (XGetFontProperty (font, XA_FONT, &value))
14471 {
14472 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
14473 char *p = name;
14474 int dashes = 0;
14475
14476 /* Count the number of dashes in the "full name".
14477 If it is too few, this isn't really the font's full name,
14478 so don't use it.
14479 In X11R4, the fonts did not come with their canonical names
14480 stored in them. */
14481 while (*p)
14482 {
14483 if (*p == '-')
14484 dashes++;
14485 p++;
14486 }
14487
14488 if (dashes >= 13)
14489 {
14490 full_name = (char *) xmalloc (p - name + 1);
14491 bcopy (name, full_name, p - name + 1);
14492 }
14493
14494 XFree (name);
14495 }
14496
14497 if (full_name != 0)
14498 fontp->full_name = full_name;
14499 else
14500 fontp->full_name = fontp->name;
14501
14502 fontp->size = font->max_bounds.width;
14503 fontp->height = FONT_HEIGHT (font);
14504
14505 if (NILP (font_names))
14506 {
14507 /* We come here because of a bug of XListFonts mentioned at
14508 the head of this block. Let's store this information in
14509 the cache for x_list_fonts. */
14510 Lisp_Object lispy_name = build_string (fontname);
14511 Lisp_Object lispy_full_name = build_string (fontp->full_name);
14512 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
14513 Qnil);
14514
14515 XSETCDR (dpyinfo->name_list_element,
14516 Fcons (Fcons (key,
14517 Fcons (Fcons (lispy_full_name,
14518 make_number (fontp->size)),
14519 Qnil)),
14520 XCDR (dpyinfo->name_list_element)));
14521 if (full_name)
14522 {
14523 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14524 Qnil);
14525 XSETCDR (dpyinfo->name_list_element,
14526 Fcons (Fcons (key,
14527 Fcons (Fcons (lispy_full_name,
14528 make_number (fontp->size)),
14529 Qnil)),
14530 XCDR (dpyinfo->name_list_element)));
14531 }
14532 }
14533
14534 /* The slot `encoding' specifies how to map a character
14535 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14536 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14537 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14538 2:0xA020..0xFF7F). For the moment, we don't know which charset
14539 uses this font. So, we set information in fontp->encoding[1]
14540 which is never used by any charset. If mapping can't be
14541 decided, set FONT_ENCODING_NOT_DECIDED. */
14542 fontp->encoding[1]
14543 = (font->max_byte1 == 0
14544 /* 1-byte font */
14545 ? (font->min_char_or_byte2 < 0x80
14546 ? (font->max_char_or_byte2 < 0x80
14547 ? 0 /* 0x20..0x7F */
14548 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14549 : 1) /* 0xA0..0xFF */
14550 /* 2-byte font */
14551 : (font->min_byte1 < 0x80
14552 ? (font->max_byte1 < 0x80
14553 ? (font->min_char_or_byte2 < 0x80
14554 ? (font->max_char_or_byte2 < 0x80
14555 ? 0 /* 0x2020..0x7F7F */
14556 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14557 : 3) /* 0x20A0..0x7FFF */
14558 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14559 : (font->min_char_or_byte2 < 0x80
14560 ? (font->max_char_or_byte2 < 0x80
14561 ? 2 /* 0xA020..0xFF7F */
14562 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14563 : 1))); /* 0xA0A0..0xFFFF */
14564
14565 fontp->baseline_offset
14566 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14567 ? (long) value : 0);
14568 fontp->relative_compose
14569 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14570 ? (long) value : 0);
14571 fontp->default_ascent
14572 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14573 ? (long) value : 0);
14574
14575 /* Set global flag fonts_changed_p to non-zero if the font loaded
14576 has a character with a smaller width than any other character
14577 before, or if the font loaded has a smaller height than any
14578 other font loaded before. If this happens, it will make a
14579 glyph matrix reallocation necessary. */
14580 fonts_changed_p |= x_compute_min_glyph_bounds (f);
14581 UNBLOCK_INPUT;
14582 return fontp;
14583 }
14584 }
14585
14586
14587 /* Return a pointer to struct font_info of a font named FONTNAME for
14588 frame F. If no such font is loaded, return NULL. */
14589
14590 struct font_info *
14591 x_query_font (f, fontname)
14592 struct frame *f;
14593 register char *fontname;
14594 {
14595 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14596 int i;
14597
14598 for (i = 0; i < dpyinfo->n_fonts; i++)
14599 if (dpyinfo->font_table[i].name
14600 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14601 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14602 return (dpyinfo->font_table + i);
14603 return NULL;
14604 }
14605
14606
14607 /* Find a CCL program for a font specified by FONTP, and set the member
14608 `encoder' of the structure. */
14609
14610 void
14611 x_find_ccl_program (fontp)
14612 struct font_info *fontp;
14613 {
14614 Lisp_Object list, elt;
14615
14616 elt = Qnil;
14617 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14618 {
14619 elt = XCAR (list);
14620 if (CONSP (elt)
14621 && STRINGP (XCAR (elt))
14622 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14623 >= 0)
14624 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14625 >= 0)))
14626 break;
14627 }
14628
14629 if (! NILP (list))
14630 {
14631 struct ccl_program *ccl
14632 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14633
14634 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14635 xfree (ccl);
14636 else
14637 fontp->font_encoder = ccl;
14638 }
14639 }
14640
14641
14642 \f
14643 /***********************************************************************
14644 Initialization
14645 ***********************************************************************/
14646
14647 #ifdef USE_X_TOOLKIT
14648 static XrmOptionDescRec emacs_options[] = {
14649 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14650 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14651
14652 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14653 XrmoptionSepArg, NULL},
14654 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14655
14656 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14657 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14658 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14659 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14660 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14661 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14662 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14663 };
14664 #endif /* USE_X_TOOLKIT */
14665
14666 static int x_initialized;
14667
14668 #ifdef MULTI_KBOARD
14669 /* Test whether two display-name strings agree up to the dot that separates
14670 the screen number from the server number. */
14671 static int
14672 same_x_server (name1, name2)
14673 const char *name1, *name2;
14674 {
14675 int seen_colon = 0;
14676 const unsigned char *system_name = SDATA (Vsystem_name);
14677 int system_name_length = strlen (system_name);
14678 int length_until_period = 0;
14679
14680 while (system_name[length_until_period] != 0
14681 && system_name[length_until_period] != '.')
14682 length_until_period++;
14683
14684 /* Treat `unix' like an empty host name. */
14685 if (! strncmp (name1, "unix:", 5))
14686 name1 += 4;
14687 if (! strncmp (name2, "unix:", 5))
14688 name2 += 4;
14689 /* Treat this host's name like an empty host name. */
14690 if (! strncmp (name1, system_name, system_name_length)
14691 && name1[system_name_length] == ':')
14692 name1 += system_name_length;
14693 if (! strncmp (name2, system_name, system_name_length)
14694 && name2[system_name_length] == ':')
14695 name2 += system_name_length;
14696 /* Treat this host's domainless name like an empty host name. */
14697 if (! strncmp (name1, system_name, length_until_period)
14698 && name1[length_until_period] == ':')
14699 name1 += length_until_period;
14700 if (! strncmp (name2, system_name, length_until_period)
14701 && name2[length_until_period] == ':')
14702 name2 += length_until_period;
14703
14704 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14705 {
14706 if (*name1 == ':')
14707 seen_colon++;
14708 if (seen_colon && *name1 == '.')
14709 return 1;
14710 }
14711 return (seen_colon
14712 && (*name1 == '.' || *name1 == '\0')
14713 && (*name2 == '.' || *name2 == '\0'));
14714 }
14715 #endif
14716
14717 struct x_display_info *
14718 x_term_init (display_name, xrm_option, resource_name)
14719 Lisp_Object display_name;
14720 char *xrm_option;
14721 char *resource_name;
14722 {
14723 int connection;
14724 Display *dpy;
14725 struct x_display_info *dpyinfo;
14726 XrmDatabase xrdb;
14727
14728 BLOCK_INPUT;
14729
14730 if (!x_initialized)
14731 {
14732 x_initialize ();
14733 x_initialized = 1;
14734 }
14735
14736 #ifdef USE_X_TOOLKIT
14737 /* weiner@footloose.sps.mot.com reports that this causes
14738 errors with X11R5:
14739 X protocol error: BadAtom (invalid Atom parameter)
14740 on protocol request 18skiloaf.
14741 So let's not use it until R6. */
14742 #ifdef HAVE_X11XTR6
14743 XtSetLanguageProc (NULL, NULL, NULL);
14744 #endif
14745
14746 {
14747 int argc = 0;
14748 char *argv[3];
14749
14750 argv[0] = "";
14751 argc = 1;
14752 if (xrm_option)
14753 {
14754 argv[argc++] = "-xrm";
14755 argv[argc++] = xrm_option;
14756 }
14757 stop_polling ();
14758 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
14759 resource_name, EMACS_CLASS,
14760 emacs_options, XtNumber (emacs_options),
14761 &argc, argv);
14762 start_polling ();
14763
14764 #ifdef HAVE_X11XTR6
14765 /* I think this is to compensate for XtSetLanguageProc. */
14766 fixup_locale ();
14767 #endif
14768 }
14769
14770 #else /* not USE_X_TOOLKIT */
14771 #ifdef HAVE_X11R5
14772 XSetLocaleModifiers ("");
14773 #endif
14774 dpy = XOpenDisplay (SDATA (display_name));
14775 #endif /* not USE_X_TOOLKIT */
14776
14777 /* Detect failure. */
14778 if (dpy == 0)
14779 {
14780 UNBLOCK_INPUT;
14781 return 0;
14782 }
14783
14784 /* We have definitely succeeded. Record the new connection. */
14785
14786 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14787 bzero (dpyinfo, sizeof *dpyinfo);
14788
14789 #ifdef MULTI_KBOARD
14790 {
14791 struct x_display_info *share;
14792 Lisp_Object tail;
14793
14794 for (share = x_display_list, tail = x_display_name_list; share;
14795 share = share->next, tail = XCDR (tail))
14796 if (same_x_server (SDATA (XCAR (XCAR (tail))),
14797 SDATA (display_name)))
14798 break;
14799 if (share)
14800 dpyinfo->kboard = share->kboard;
14801 else
14802 {
14803 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14804 init_kboard (dpyinfo->kboard);
14805 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14806 {
14807 char *vendor = ServerVendor (dpy);
14808 UNBLOCK_INPUT;
14809 dpyinfo->kboard->Vsystem_key_alist
14810 = call1 (Qvendor_specific_keysyms,
14811 build_string (vendor ? vendor : ""));
14812 BLOCK_INPUT;
14813 }
14814
14815 dpyinfo->kboard->next_kboard = all_kboards;
14816 all_kboards = dpyinfo->kboard;
14817 /* Don't let the initial kboard remain current longer than necessary.
14818 That would cause problems if a file loaded on startup tries to
14819 prompt in the mini-buffer. */
14820 if (current_kboard == initial_kboard)
14821 current_kboard = dpyinfo->kboard;
14822 }
14823 dpyinfo->kboard->reference_count++;
14824 }
14825 #endif
14826
14827 /* Put this display on the chain. */
14828 dpyinfo->next = x_display_list;
14829 x_display_list = dpyinfo;
14830
14831 /* Put it on x_display_name_list as well, to keep them parallel. */
14832 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14833 x_display_name_list);
14834 dpyinfo->name_list_element = XCAR (x_display_name_list);
14835
14836 dpyinfo->display = dpy;
14837
14838 #if 0
14839 XSetAfterFunction (x_current_display, x_trace_wire);
14840 #endif /* ! 0 */
14841
14842 dpyinfo->x_id_name
14843 = (char *) xmalloc (SBYTES (Vinvocation_name)
14844 + SBYTES (Vsystem_name)
14845 + 2);
14846 sprintf (dpyinfo->x_id_name, "%s@%s",
14847 SDATA (Vinvocation_name), SDATA (Vsystem_name));
14848
14849 /* Figure out which modifier bits mean what. */
14850 x_find_modifier_meanings (dpyinfo);
14851
14852 /* Get the scroll bar cursor. */
14853 dpyinfo->vertical_scroll_bar_cursor
14854 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14855
14856 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14857 resource_name, EMACS_CLASS);
14858 #ifdef HAVE_XRMSETDATABASE
14859 XrmSetDatabase (dpyinfo->display, xrdb);
14860 #else
14861 dpyinfo->display->db = xrdb;
14862 #endif
14863 /* Put the rdb where we can find it in a way that works on
14864 all versions. */
14865 dpyinfo->xrdb = xrdb;
14866
14867 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14868 DefaultScreen (dpyinfo->display));
14869 select_visual (dpyinfo);
14870 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14871 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14872 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14873 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14874 dpyinfo->grabbed = 0;
14875 dpyinfo->reference_count = 0;
14876 dpyinfo->icon_bitmap_id = -1;
14877 dpyinfo->font_table = NULL;
14878 dpyinfo->n_fonts = 0;
14879 dpyinfo->font_table_size = 0;
14880 dpyinfo->bitmaps = 0;
14881 dpyinfo->bitmaps_size = 0;
14882 dpyinfo->bitmaps_last = 0;
14883 dpyinfo->scratch_cursor_gc = 0;
14884 dpyinfo->mouse_face_mouse_frame = 0;
14885 dpyinfo->mouse_face_deferred_gc = 0;
14886 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14887 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14888 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14889 dpyinfo->mouse_face_window = Qnil;
14890 dpyinfo->mouse_face_overlay = Qnil;
14891 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14892 dpyinfo->mouse_face_defer = 0;
14893 dpyinfo->mouse_face_hidden = 0;
14894 dpyinfo->x_focus_frame = 0;
14895 dpyinfo->x_focus_event_frame = 0;
14896 dpyinfo->x_highlight_frame = 0;
14897 dpyinfo->image_cache = make_image_cache ();
14898
14899 /* See if a private colormap is requested. */
14900 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14901 {
14902 if (dpyinfo->visual->class == PseudoColor)
14903 {
14904 Lisp_Object value;
14905 value = display_x_get_resource (dpyinfo,
14906 build_string ("privateColormap"),
14907 build_string ("PrivateColormap"),
14908 Qnil, Qnil);
14909 if (STRINGP (value)
14910 && (!strcmp (SDATA (value), "true")
14911 || !strcmp (SDATA (value), "on")))
14912 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14913 }
14914 }
14915 else
14916 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14917 dpyinfo->visual, AllocNone);
14918
14919 {
14920 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14921 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14922 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14923 dpyinfo->resy = pixels * 25.4 / mm;
14924 pixels = DisplayWidth (dpyinfo->display, screen_number);
14925 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14926 dpyinfo->resx = pixels * 25.4 / mm;
14927 }
14928
14929 dpyinfo->Xatom_wm_protocols
14930 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14931 dpyinfo->Xatom_wm_take_focus
14932 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14933 dpyinfo->Xatom_wm_save_yourself
14934 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14935 dpyinfo->Xatom_wm_delete_window
14936 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14937 dpyinfo->Xatom_wm_change_state
14938 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14939 dpyinfo->Xatom_wm_configure_denied
14940 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14941 dpyinfo->Xatom_wm_window_moved
14942 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14943 dpyinfo->Xatom_editres
14944 = XInternAtom (dpyinfo->display, "Editres", False);
14945 dpyinfo->Xatom_CLIPBOARD
14946 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14947 dpyinfo->Xatom_TIMESTAMP
14948 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14949 dpyinfo->Xatom_TEXT
14950 = XInternAtom (dpyinfo->display, "TEXT", False);
14951 dpyinfo->Xatom_COMPOUND_TEXT
14952 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14953 dpyinfo->Xatom_UTF8_STRING
14954 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
14955 dpyinfo->Xatom_DELETE
14956 = XInternAtom (dpyinfo->display, "DELETE", False);
14957 dpyinfo->Xatom_MULTIPLE
14958 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14959 dpyinfo->Xatom_INCR
14960 = XInternAtom (dpyinfo->display, "INCR", False);
14961 dpyinfo->Xatom_EMACS_TMP
14962 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14963 dpyinfo->Xatom_TARGETS
14964 = XInternAtom (dpyinfo->display, "TARGETS", False);
14965 dpyinfo->Xatom_NULL
14966 = XInternAtom (dpyinfo->display, "NULL", False);
14967 dpyinfo->Xatom_ATOM_PAIR
14968 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14969 /* For properties of font. */
14970 dpyinfo->Xatom_PIXEL_SIZE
14971 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14972 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14973 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14974 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14975 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14976 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14977 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14978
14979 /* Ghostscript support. */
14980 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14981 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14982
14983 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14984 False);
14985
14986 dpyinfo->cut_buffers_initialized = 0;
14987
14988 connection = ConnectionNumber (dpyinfo->display);
14989 dpyinfo->connection = connection;
14990
14991 {
14992 char null_bits[1];
14993
14994 null_bits[0] = 0x00;
14995
14996 dpyinfo->null_pixel
14997 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14998 null_bits, 1, 1, (long) 0, (long) 0,
14999 1);
15000 }
15001
15002 {
15003 extern int gray_bitmap_width, gray_bitmap_height;
15004 extern char *gray_bitmap_bits;
15005 dpyinfo->gray
15006 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15007 gray_bitmap_bits,
15008 gray_bitmap_width, gray_bitmap_height,
15009 (unsigned long) 1, (unsigned long) 0, 1);
15010 }
15011
15012 #ifdef HAVE_X_I18N
15013 xim_initialize (dpyinfo, resource_name);
15014 #endif
15015
15016 #ifdef subprocesses
15017 /* This is only needed for distinguishing keyboard and process input. */
15018 if (connection != 0)
15019 add_keyboard_wait_descriptor (connection);
15020 #endif
15021
15022 #ifndef F_SETOWN_BUG
15023 #ifdef F_SETOWN
15024 #ifdef F_SETOWN_SOCK_NEG
15025 /* stdin is a socket here */
15026 fcntl (connection, F_SETOWN, -getpid ());
15027 #else /* ! defined (F_SETOWN_SOCK_NEG) */
15028 fcntl (connection, F_SETOWN, getpid ());
15029 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
15030 #endif /* ! defined (F_SETOWN) */
15031 #endif /* F_SETOWN_BUG */
15032
15033 #ifdef SIGIO
15034 if (interrupt_input)
15035 init_sigio (connection);
15036 #endif /* ! defined (SIGIO) */
15037
15038 #ifdef USE_LUCID
15039 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
15040 /* Make sure that we have a valid font for dialog boxes
15041 so that Xt does not crash. */
15042 {
15043 Display *dpy = dpyinfo->display;
15044 XrmValue d, fr, to;
15045 Font font;
15046 int count;
15047
15048 d.addr = (XPointer)&dpy;
15049 d.size = sizeof (Display *);
15050 fr.addr = XtDefaultFont;
15051 fr.size = sizeof (XtDefaultFont);
15052 to.size = sizeof (Font *);
15053 to.addr = (XPointer)&font;
15054 count = x_catch_errors (dpy);
15055 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
15056 abort ();
15057 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
15058 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
15059 x_uncatch_errors (dpy, count);
15060 }
15061 #endif
15062 #endif
15063
15064 /* See if we should run in synchronous mode. This is useful
15065 for debugging X code. */
15066 {
15067 Lisp_Object value;
15068 value = display_x_get_resource (dpyinfo,
15069 build_string ("synchronous"),
15070 build_string ("Synchronous"),
15071 Qnil, Qnil);
15072 if (STRINGP (value)
15073 && (!strcmp (SDATA (value), "true")
15074 || !strcmp (SDATA (value), "on")))
15075 XSynchronize (dpyinfo->display, True);
15076 }
15077
15078 UNBLOCK_INPUT;
15079
15080 return dpyinfo;
15081 }
15082 \f
15083 /* Get rid of display DPYINFO, assuming all frames are already gone,
15084 and without sending any more commands to the X server. */
15085
15086 void
15087 x_delete_display (dpyinfo)
15088 struct x_display_info *dpyinfo;
15089 {
15090 delete_keyboard_wait_descriptor (dpyinfo->connection);
15091
15092 /* Discard this display from x_display_name_list and x_display_list.
15093 We can't use Fdelq because that can quit. */
15094 if (! NILP (x_display_name_list)
15095 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
15096 x_display_name_list = XCDR (x_display_name_list);
15097 else
15098 {
15099 Lisp_Object tail;
15100
15101 tail = x_display_name_list;
15102 while (CONSP (tail) && CONSP (XCDR (tail)))
15103 {
15104 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
15105 {
15106 XSETCDR (tail, XCDR (XCDR (tail)));
15107 break;
15108 }
15109 tail = XCDR (tail);
15110 }
15111 }
15112
15113 if (next_noop_dpyinfo == dpyinfo)
15114 next_noop_dpyinfo = dpyinfo->next;
15115
15116 if (x_display_list == dpyinfo)
15117 x_display_list = dpyinfo->next;
15118 else
15119 {
15120 struct x_display_info *tail;
15121
15122 for (tail = x_display_list; tail; tail = tail->next)
15123 if (tail->next == dpyinfo)
15124 tail->next = tail->next->next;
15125 }
15126
15127 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
15128 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
15129 XrmDestroyDatabase (dpyinfo->xrdb);
15130 #endif
15131 #endif
15132 #ifdef MULTI_KBOARD
15133 if (--dpyinfo->kboard->reference_count == 0)
15134 delete_kboard (dpyinfo->kboard);
15135 #endif
15136 #ifdef HAVE_X_I18N
15137 if (dpyinfo->xim)
15138 xim_close_dpy (dpyinfo);
15139 #endif
15140
15141 xfree (dpyinfo->font_table);
15142 xfree (dpyinfo->x_id_name);
15143 xfree (dpyinfo->color_cells);
15144 xfree (dpyinfo);
15145 }
15146
15147 \f
15148 /* Set up use of X before we make the first connection. */
15149
15150 static struct redisplay_interface x_redisplay_interface =
15151 {
15152 x_produce_glyphs,
15153 x_write_glyphs,
15154 x_insert_glyphs,
15155 x_clear_end_of_line,
15156 x_scroll_run,
15157 x_after_update_window_line,
15158 x_update_window_begin,
15159 x_update_window_end,
15160 XTcursor_to,
15161 x_flush,
15162 x_clear_mouse_face,
15163 x_get_glyph_overhangs,
15164 x_fix_overlapping_area
15165 };
15166
15167 void
15168 x_initialize ()
15169 {
15170 rif = &x_redisplay_interface;
15171
15172 clear_frame_hook = x_clear_frame;
15173 ins_del_lines_hook = x_ins_del_lines;
15174 delete_glyphs_hook = x_delete_glyphs;
15175 ring_bell_hook = XTring_bell;
15176 reset_terminal_modes_hook = XTreset_terminal_modes;
15177 set_terminal_modes_hook = XTset_terminal_modes;
15178 update_begin_hook = x_update_begin;
15179 update_end_hook = x_update_end;
15180 set_terminal_window_hook = XTset_terminal_window;
15181 read_socket_hook = XTread_socket;
15182 frame_up_to_date_hook = XTframe_up_to_date;
15183 mouse_position_hook = XTmouse_position;
15184 frame_rehighlight_hook = XTframe_rehighlight;
15185 frame_raise_lower_hook = XTframe_raise_lower;
15186 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
15187 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
15188 redeem_scroll_bar_hook = XTredeem_scroll_bar;
15189 judge_scroll_bars_hook = XTjudge_scroll_bars;
15190 estimate_mode_line_height_hook = x_estimate_mode_line_height;
15191
15192 scroll_region_ok = 1; /* we'll scroll partial frames */
15193 char_ins_del_ok = 1;
15194 line_ins_del_ok = 1; /* we'll just blt 'em */
15195 fast_clear_end_of_line = 1; /* X does this well */
15196 memory_below_frame = 0; /* we don't remember what scrolls
15197 off the bottom */
15198 baud_rate = 19200;
15199
15200 x_noop_count = 0;
15201 last_tool_bar_item = -1;
15202 any_help_event_p = 0;
15203
15204 /* Try to use interrupt input; if we can't, then start polling. */
15205 Fset_input_mode (Qt, Qnil, Qt, Qnil);
15206
15207 #ifdef USE_X_TOOLKIT
15208 XtToolkitInitialize ();
15209
15210 Xt_app_con = XtCreateApplicationContext ();
15211
15212 /* Register a converter from strings to pixels, which uses
15213 Emacs' color allocation infrastructure. */
15214 XtAppSetTypeConverter (Xt_app_con,
15215 XtRString, XtRPixel, cvt_string_to_pixel,
15216 cvt_string_to_pixel_args,
15217 XtNumber (cvt_string_to_pixel_args),
15218 XtCacheByDisplay, cvt_pixel_dtor);
15219
15220 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
15221
15222 /* Install an asynchronous timer that processes Xt timeout events
15223 every 0.1s. This is necessary because some widget sets use
15224 timeouts internally, for example the LessTif menu bar, or the
15225 Xaw3d scroll bar. When Xt timouts aren't processed, these
15226 widgets don't behave normally. */
15227 {
15228 EMACS_TIME interval;
15229 EMACS_SET_SECS_USECS (interval, 0, 100000);
15230 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
15231 }
15232 #endif
15233
15234 #ifdef USE_TOOLKIT_SCROLL_BARS
15235 xaw3d_arrow_scroll = False;
15236 xaw3d_pick_top = True;
15237 #endif
15238
15239 /* Note that there is no real way portable across R3/R4 to get the
15240 original error handler. */
15241 XSetErrorHandler (x_error_handler);
15242 XSetIOErrorHandler (x_io_error_quitter);
15243
15244 /* Disable Window Change signals; they are handled by X events. */
15245 #ifdef SIGWINCH
15246 signal (SIGWINCH, SIG_DFL);
15247 #endif /* SIGWINCH */
15248
15249 signal (SIGPIPE, x_connection_signal);
15250
15251 #ifdef HAVE_X_SM
15252 x_session_initialize ();
15253 #endif
15254 }
15255
15256
15257 void
15258 syms_of_xterm ()
15259 {
15260 staticpro (&x_error_message_string);
15261 x_error_message_string = Qnil;
15262
15263 staticpro (&x_display_name_list);
15264 x_display_name_list = Qnil;
15265
15266 staticpro (&last_mouse_scroll_bar);
15267 last_mouse_scroll_bar = Qnil;
15268
15269 staticpro (&Qvendor_specific_keysyms);
15270 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
15271
15272 staticpro (&Qutf_8);
15273 Qutf_8 = intern ("utf-8");
15274 staticpro (&Qlatin_1);
15275 Qlatin_1 = intern ("latin-1");
15276
15277 staticpro (&last_mouse_press_frame);
15278 last_mouse_press_frame = Qnil;
15279
15280 help_echo = Qnil;
15281 staticpro (&help_echo);
15282 help_echo_object = Qnil;
15283 staticpro (&help_echo_object);
15284 help_echo_window = Qnil;
15285 staticpro (&help_echo_window);
15286 previous_help_echo = Qnil;
15287 staticpro (&previous_help_echo);
15288 help_echo_pos = -1;
15289
15290 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
15291 doc: /* *Non-nil means autoselect window with mouse pointer. */);
15292 mouse_autoselect_window = 0;
15293
15294 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
15295 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
15296 For example, if a block cursor is over a tab, it will be drawn as
15297 wide as that tab on the display. */);
15298 x_stretch_cursor_p = 0;
15299
15300 DEFVAR_BOOL ("x-use-underline-position-properties",
15301 &x_use_underline_position_properties,
15302 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15303 nil means ignore them. If you encounter fonts with bogus
15304 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15305 to 4.1, set this to nil. */);
15306 x_use_underline_position_properties = 1;
15307
15308 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
15309 doc: /* What X toolkit scroll bars Emacs uses.
15310 A value of nil means Emacs doesn't use X toolkit scroll bars.
15311 Otherwise, value is a symbol describing the X toolkit. */);
15312 #ifdef USE_TOOLKIT_SCROLL_BARS
15313 #ifdef USE_MOTIF
15314 Vx_toolkit_scroll_bars = intern ("motif");
15315 #elif defined HAVE_XAW3D
15316 Vx_toolkit_scroll_bars = intern ("xaw3d");
15317 #else
15318 Vx_toolkit_scroll_bars = intern ("xaw");
15319 #endif
15320 #else
15321 Vx_toolkit_scroll_bars = Qnil;
15322 #endif
15323
15324 staticpro (&last_mouse_motion_frame);
15325 last_mouse_motion_frame = Qnil;
15326
15327 Qmodifier_value = intern ("modifier-value");
15328 Qalt = intern ("alt");
15329 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
15330 Qhyper = intern ("hyper");
15331 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
15332 Qmeta = intern ("meta");
15333 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
15334 Qsuper = intern ("super");
15335 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
15336
15337 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
15338 doc: /* Which keys Emacs uses for the alt modifier.
15339 This should be one of the symbols `alt', `hyper', `meta', `super'.
15340 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15341 is nil, which is the same as `alt'. */);
15342 Vx_alt_keysym = Qnil;
15343
15344 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
15345 doc: /* Which keys Emacs uses for the hyper modifier.
15346 This should be one of the symbols `alt', `hyper', `meta', `super'.
15347 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15348 default is nil, which is the same as `hyper'. */);
15349 Vx_hyper_keysym = Qnil;
15350
15351 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
15352 doc: /* Which keys Emacs uses for the meta modifier.
15353 This should be one of the symbols `alt', `hyper', `meta', `super'.
15354 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15355 default is nil, which is the same as `meta'. */);
15356 Vx_meta_keysym = Qnil;
15357
15358 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
15359 doc: /* Which keys Emacs uses for the super modifier.
15360 This should be one of the symbols `alt', `hyper', `meta', `super'.
15361 For example, `super' means use the Super_L and Super_R keysyms. The
15362 default is nil, which is the same as `super'. */);
15363 Vx_super_keysym = Qnil;
15364
15365 }
15366
15367 #endif /* HAVE_X_WINDOWS */