*** empty log message ***
[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
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 #if 0
80 #include "sink.h"
81 #include "sinkmask.h"
82 #endif /* ! 0 */
83 #include "gnu.h"
84 #include "disptab.h"
85 #include "buffer.h"
86 #include "window.h"
87 #include "keyboard.h"
88 #include "intervals.h"
89 #include "process.h"
90 #include "atimer.h"
91
92 #ifdef USE_X_TOOLKIT
93 #include <X11/Shell.h>
94 #endif
95
96 #ifdef HAVE_SYS_TIME_H
97 #include <sys/time.h>
98 #endif
99 #ifdef HAVE_UNISTD_H
100 #include <unistd.h>
101 #endif
102
103 #ifdef USE_X_TOOLKIT
104
105 extern void free_frame_menubar P_ ((struct frame *));
106 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
108
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110 #define HACK_EDITRES
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
113
114 /* Include toolkit specific headers for the scroll bar widget. */
115
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #include <Xm/ScrollBarP.h>
121 #else /* !USE_MOTIF i.e. use Xaw */
122
123 #ifdef HAVE_XAW3D
124 #include <X11/Xaw3d/Simple.h>
125 #include <X11/Xaw3d/Scrollbar.h>
126 #define ARROW_SCROLLBAR
127 #include <X11/Xaw3d/ScrollbarP.h>
128 #else /* !HAVE_XAW3D */
129 #include <X11/Xaw/Simple.h>
130 #include <X11/Xaw/Scrollbar.h>
131 #endif /* !HAVE_XAW3D */
132 #ifndef XtNpickTop
133 #define XtNpickTop "pickTop"
134 #endif /* !XtNpickTop */
135 #endif /* !USE_MOTIF */
136 #endif /* USE_TOOLKIT_SCROLL_BARS */
137
138 #endif /* USE_X_TOOLKIT */
139
140 #ifndef USE_X_TOOLKIT
141 #define x_any_window_to_frame x_window_to_frame
142 #define x_top_window_to_frame x_window_to_frame
143 #endif
144
145 #ifdef USE_X_TOOLKIT
146 #include "widget.h"
147 #ifndef XtNinitialState
148 #define XtNinitialState "initialState"
149 #endif
150 #endif
151
152 #ifdef SOLARIS2
153 /* memmove will be defined as a macro in Xfuncs.h unless
154 <string.h> is included beforehand. The declaration for memmove in
155 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
156 #include <string.h>
157 #endif
158
159 #ifndef min
160 #define min(a,b) ((a) < (b) ? (a) : (b))
161 #endif
162 #ifndef max
163 #define max(a,b) ((a) > (b) ? (a) : (b))
164 #endif
165
166 #define abs(x) ((x) < 0 ? -(x) : (x))
167
168 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
169
170 \f
171 /* Bitmaps for truncated lines. */
172
173 enum bitmap_type
174 {
175 NO_BITMAP,
176 LEFT_TRUNCATION_BITMAP,
177 RIGHT_TRUNCATION_BITMAP,
178 OVERLAY_ARROW_BITMAP,
179 CONTINUED_LINE_BITMAP,
180 CONTINUATION_LINE_BITMAP,
181 ZV_LINE_BITMAP
182 };
183
184 /* Bitmap drawn to indicate lines not displaying text if
185 `indicate-empty-lines' is non-nil. */
186
187 #define zv_width 8
188 #define zv_height 8
189 static unsigned char zv_bits[] = {
190 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
191
192 /* An arrow like this: `<-'. */
193
194 #define left_width 8
195 #define left_height 8
196 static unsigned char left_bits[] = {
197 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
198
199 /* Right truncation arrow bitmap `->'. */
200
201 #define right_width 8
202 #define right_height 8
203 static unsigned char right_bits[] = {
204 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
205
206 /* Marker for continued lines. */
207
208 #define continued_width 8
209 #define continued_height 8
210 static unsigned char continued_bits[] = {
211 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
212
213 /* Marker for continuation lines. */
214
215 #define continuation_width 8
216 #define continuation_height 8
217 static unsigned char continuation_bits[] = {
218 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
219
220 /* Overlay arrow bitmap. */
221
222 #if 0
223 /* A bomb. */
224 #define ov_width 8
225 #define ov_height 8
226 static unsigned char ov_bits[] = {
227 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
228 #else
229 /* A triangular arrow. */
230 #define ov_width 8
231 #define ov_height 8
232 static unsigned char ov_bits[] = {
233 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
234
235 #endif
236
237 extern Lisp_Object Qhelp_echo;
238
239 \f
240 /* Non-zero means Emacs uses toolkit scroll bars. */
241
242 int x_toolkit_scroll_bars_p;
243
244 /* If a string, XTread_socket generates an event to display that string.
245 (The display is done in read_char.) */
246
247 static Lisp_Object help_echo;
248 static Lisp_Object help_echo_window;
249 static Lisp_Object help_echo_object;
250 static int help_echo_pos;
251
252 /* Temporary variable for XTread_socket. */
253
254 static Lisp_Object previous_help_echo;
255
256 /* Non-zero means that a HELP_EVENT has been generated since Emacs
257 start. */
258
259 static int any_help_event_p;
260
261 /* Non-zero means draw block and hollow cursor as wide as the glyph
262 under it. For example, if a block cursor is over a tab, it will be
263 drawn as wide as that tab on the display. */
264
265 int x_stretch_cursor_p;
266
267 /* This is a chain of structures for all the X displays currently in
268 use. */
269
270 struct x_display_info *x_display_list;
271
272 /* This is a list of cons cells, each of the form (NAME
273 . FONT-LIST-CACHE), one for each element of x_display_list and in
274 the same order. NAME is the name of the frame. FONT-LIST-CACHE
275 records previous values returned by x-list-fonts. */
276
277 Lisp_Object x_display_name_list;
278
279 /* Frame being updated by update_frame. This is declared in term.c.
280 This is set by update_begin and looked at by all the XT functions.
281 It is zero while not inside an update. In that case, the XT
282 functions assume that `selected_frame' is the frame to apply to. */
283
284 extern struct frame *updating_frame;
285
286 extern int waiting_for_input;
287
288 /* This is a frame waiting to be auto-raised, within XTread_socket. */
289
290 struct frame *pending_autoraise_frame;
291
292 #ifdef USE_X_TOOLKIT
293 /* The application context for Xt use. */
294 XtAppContext Xt_app_con;
295 static String Xt_default_resources[] = {0};
296 #endif /* USE_X_TOOLKIT */
297
298 /* Nominal cursor position -- where to draw output.
299 HPOS and VPOS are window relative glyph matrix coordinates.
300 X and Y are window relative pixel coordinates. */
301
302 struct cursor_pos output_cursor;
303
304 /* Non-zero means user is interacting with a toolkit scroll bar. */
305
306 static int toolkit_scroll_bar_interaction;
307
308 /* Mouse movement.
309
310 Formerly, we used PointerMotionHintMask (in standard_event_mask)
311 so that we would have to call XQueryPointer after each MotionNotify
312 event to ask for another such event. However, this made mouse tracking
313 slow, and there was a bug that made it eventually stop.
314
315 Simply asking for MotionNotify all the time seems to work better.
316
317 In order to avoid asking for motion events and then throwing most
318 of them away or busy-polling the server for mouse positions, we ask
319 the server for pointer motion hints. This means that we get only
320 one event per group of mouse movements. "Groups" are delimited by
321 other kinds of events (focus changes and button clicks, for
322 example), or by XQueryPointer calls; when one of these happens, we
323 get another MotionNotify event the next time the mouse moves. This
324 is at least as efficient as getting motion events when mouse
325 tracking is on, and I suspect only negligibly worse when tracking
326 is off. */
327
328 /* Where the mouse was last time we reported a mouse event. */
329
330 FRAME_PTR last_mouse_frame;
331 static XRectangle last_mouse_glyph;
332 static Lisp_Object last_mouse_press_frame;
333
334 /* The scroll bar in which the last X motion event occurred.
335
336 If the last X motion event occurred in a scroll bar, we set this so
337 XTmouse_position can know whether to report a scroll bar motion or
338 an ordinary motion.
339
340 If the last X motion event didn't occur in a scroll bar, we set
341 this to Qnil, to tell XTmouse_position to return an ordinary motion
342 event. */
343
344 static Lisp_Object last_mouse_scroll_bar;
345
346 /* This is a hack. We would really prefer that XTmouse_position would
347 return the time associated with the position it returns, but there
348 doesn't seem to be any way to wrest the time-stamp from the server
349 along with the position query. So, we just keep track of the time
350 of the last movement we received, and return that in hopes that
351 it's somewhat accurate. */
352
353 static Time last_mouse_movement_time;
354
355 /* Incremented by XTread_socket whenever it really tries to read
356 events. */
357
358 #ifdef __STDC__
359 static int volatile input_signal_count;
360 #else
361 static int input_signal_count;
362 #endif
363
364 /* Used locally within XTread_socket. */
365
366 static int x_noop_count;
367
368 /* Initial values of argv and argc. */
369
370 extern char **initial_argv;
371 extern int initial_argc;
372
373 extern Lisp_Object Vcommand_line_args, Vsystem_name;
374
375 /* Tells if a window manager is present or not. */
376
377 extern Lisp_Object Vx_no_window_manager;
378
379 extern Lisp_Object Qface, Qmouse_face;
380
381 extern int errno;
382
383 /* A mask of extra modifier bits to put into every keyboard char. */
384
385 extern int extra_keyboard_modifiers;
386
387 static Lisp_Object Qvendor_specific_keysyms;
388
389 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
390 extern Lisp_Object x_icon_type P_ ((struct frame *));
391
392
393 /* Enumeration for overriding/changing the face to use for drawing
394 glyphs in x_draw_glyphs. */
395
396 enum draw_glyphs_face
397 {
398 DRAW_NORMAL_TEXT,
399 DRAW_INVERSE_VIDEO,
400 DRAW_CURSOR,
401 DRAW_MOUSE_FACE,
402 DRAW_IMAGE_RAISED,
403 DRAW_IMAGE_SUNKEN
404 };
405
406 static void x_update_window_end P_ ((struct window *, int, int));
407 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
408 void x_delete_display P_ ((struct x_display_info *));
409 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
410 unsigned));
411 static int fast_find_position P_ ((struct window *, int, int *, int *,
412 int *, int *));
413 static void set_output_cursor P_ ((struct cursor_pos *));
414 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
415 int *, int *, int *));
416 static void note_mode_line_highlight P_ ((struct window *, int, int));
417 static void note_mouse_highlight P_ ((struct frame *, int, int));
418 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
419 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
420 static void show_mouse_face P_ ((struct x_display_info *,
421 enum draw_glyphs_face));
422 static int x_io_error_quitter P_ ((Display *));
423 int x_catch_errors P_ ((Display *));
424 void x_uncatch_errors P_ ((Display *, int));
425 void x_lower_frame P_ ((struct frame *));
426 void x_scroll_bar_clear P_ ((struct frame *));
427 int x_had_errors_p P_ ((Display *));
428 void x_wm_set_size_hint P_ ((struct frame *, long, int));
429 void x_raise_frame P_ ((struct frame *));
430 void x_set_window_size P_ ((struct frame *, int, int, int));
431 void x_wm_set_window_state P_ ((struct frame *, int));
432 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
433 void x_initialize P_ ((void));
434 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
435 static int x_compute_min_glyph_bounds P_ ((struct frame *));
436 static void x_draw_phys_cursor_glyph P_ ((struct window *,
437 struct glyph_row *,
438 enum draw_glyphs_face));
439 static void x_update_end P_ ((struct frame *));
440 static void XTframe_up_to_date P_ ((struct frame *));
441 static void XTreassert_line_highlight P_ ((int, int));
442 static void x_change_line_highlight P_ ((int, int, int, int));
443 static void XTset_terminal_modes P_ ((void));
444 static void XTreset_terminal_modes P_ ((void));
445 static void XTcursor_to P_ ((int, int, int, int));
446 static void x_write_glyphs P_ ((struct glyph *, int));
447 static void x_clear_end_of_line P_ ((int));
448 static void x_clear_frame P_ ((void));
449 static void x_clear_cursor P_ ((struct window *));
450 static void frame_highlight P_ ((struct frame *));
451 static void frame_unhighlight P_ ((struct frame *));
452 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
453 static void XTframe_rehighlight P_ ((struct frame *));
454 static void x_frame_rehighlight P_ ((struct x_display_info *));
455 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
456 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
457 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
458 XRectangle *));
459 static void expose_frame P_ ((struct frame *, int, int, int, int));
460 static void expose_window_tree P_ ((struct window *, XRectangle *));
461 static void expose_window P_ ((struct window *, XRectangle *));
462 static void expose_area P_ ((struct window *, struct glyph_row *,
463 XRectangle *, enum glyph_row_area));
464 static void expose_line P_ ((struct window *, struct glyph_row *,
465 XRectangle *));
466 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
467 static void x_update_window_cursor P_ ((struct window *, int));
468 static void x_erase_phys_cursor P_ ((struct window *));
469 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
470 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
471 enum bitmap_type));
472
473 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
474 GC, int));
475 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
476 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
477 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
478 static void x_flush P_ ((struct frame *f));
479 static void x_update_begin P_ ((struct frame *));
480 static void x_update_window_begin P_ ((struct window *));
481 static void x_draw_vertical_border P_ ((struct window *));
482 static void x_after_update_window_line P_ ((struct glyph_row *));
483 static INLINE void take_vertical_position_into_account P_ ((struct it *));
484 static void x_produce_stretch_glyph P_ ((struct it *));
485
486
487 /* Flush display of frame F, or of all frames if F is null. */
488
489 static void
490 x_flush (f)
491 struct frame *f;
492 {
493 BLOCK_INPUT;
494 if (f == NULL)
495 {
496 Lisp_Object rest, frame;
497 FOR_EACH_FRAME (rest, frame)
498 x_flush (XFRAME (frame));
499 }
500 else if (FRAME_X_P (f))
501 XFlush (FRAME_X_DISPLAY (f));
502 UNBLOCK_INPUT;
503 }
504
505
506 /* Remove calls to XFlush by defining XFlush to an empty replacement.
507 Calls to XFlush should be unnecessary because the X output buffer
508 is flushed automatically as needed by calls to XPending,
509 XNextEvent, or XWindowEvent according to the XFlush man page.
510 XTread_socket calls XPending. Removing XFlush improves
511 performance. */
512
513 #define XFlush(DISPLAY) (void) 0
514
515 \f
516 /***********************************************************************
517 Debugging
518 ***********************************************************************/
519
520 #if 0
521
522 /* This is a function useful for recording debugging information about
523 the sequence of occurrences in this file. */
524
525 struct record
526 {
527 char *locus;
528 int type;
529 };
530
531 struct record event_record[100];
532
533 int event_record_index;
534
535 record_event (locus, type)
536 char *locus;
537 int type;
538 {
539 if (event_record_index == sizeof (event_record) / sizeof (struct record))
540 event_record_index = 0;
541
542 event_record[event_record_index].locus = locus;
543 event_record[event_record_index].type = type;
544 event_record_index++;
545 }
546
547 #endif /* 0 */
548
549
550 \f
551 /* Return the struct x_display_info corresponding to DPY. */
552
553 struct x_display_info *
554 x_display_info_for_display (dpy)
555 Display *dpy;
556 {
557 struct x_display_info *dpyinfo;
558
559 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
560 if (dpyinfo->display == dpy)
561 return dpyinfo;
562
563 return 0;
564 }
565
566
567 \f
568 /***********************************************************************
569 Starting and ending an update
570 ***********************************************************************/
571
572 /* Start an update of frame F. This function is installed as a hook
573 for update_begin, i.e. it is called when update_begin is called.
574 This function is called prior to calls to x_update_window_begin for
575 each window being updated. Currently, there is nothing to do here
576 because all interesting stuff is done on a window basis. */
577
578 static void
579 x_update_begin (f)
580 struct frame *f;
581 {
582 /* Nothing to do. */
583 }
584
585
586 /* Start update of window W. Set the global variable updated_window
587 to the window being updated and set output_cursor to the cursor
588 position of W. */
589
590 static void
591 x_update_window_begin (w)
592 struct window *w;
593 {
594 struct frame *f = XFRAME (WINDOW_FRAME (w));
595 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
596
597 updated_window = w;
598 set_output_cursor (&w->cursor);
599
600 BLOCK_INPUT;
601
602 if (f == display_info->mouse_face_mouse_frame)
603 {
604 /* Don't do highlighting for mouse motion during the update. */
605 display_info->mouse_face_defer = 1;
606
607 /* If F needs to be redrawn, simply forget about any prior mouse
608 highlighting. */
609 if (FRAME_GARBAGED_P (f))
610 display_info->mouse_face_window = Qnil;
611
612 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
613 their mouse_face_p flag set, which means that they are always
614 unequal to rows in a desired matrix which never have that
615 flag set. So, rows containing mouse-face glyphs are never
616 scrolled, and we don't have to switch the mouse highlight off
617 here to prevent it from being scrolled. */
618
619 /* Can we tell that this update does not affect the window
620 where the mouse highlight is? If so, no need to turn off.
621 Likewise, don't do anything if the frame is garbaged;
622 in that case, the frame's current matrix that we would use
623 is all wrong, and we will redisplay that line anyway. */
624 if (!NILP (display_info->mouse_face_window)
625 && w == XWINDOW (display_info->mouse_face_window))
626 {
627 int i;
628
629 for (i = 0; i < w->desired_matrix->nrows; ++i)
630 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
631 break;
632
633 if (i < w->desired_matrix->nrows)
634 clear_mouse_face (display_info);
635 }
636 #endif /* 0 */
637 }
638
639 UNBLOCK_INPUT;
640 }
641
642
643 /* Draw a vertical window border to the right of window W if W doesn't
644 have vertical scroll bars. */
645
646 static void
647 x_draw_vertical_border (w)
648 struct window *w;
649 {
650 struct frame *f = XFRAME (WINDOW_FRAME (w));
651
652 /* Redraw borders between horizontally adjacent windows. Don't
653 do it for frames with vertical scroll bars because either the
654 right scroll bar of a window, or the left scroll bar of its
655 neighbor will suffice as a border. */
656 if (!WINDOW_RIGHTMOST_P (w)
657 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
658 {
659 int x0, x1, y0, y1;
660
661 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
662 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
663 y1 -= 1;
664
665 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
666 f->output_data.x->normal_gc, x1, y0, x1, y1);
667 }
668 }
669
670
671 /* End update of window W (which is equal to updated_window).
672
673 Draw vertical borders between horizontally adjacent windows, and
674 display W's cursor if CURSOR_ON_P is non-zero.
675
676 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
677 glyphs in mouse-face were overwritten. In that case we have to
678 make sure that the mouse-highlight is properly redrawn.
679
680 W may be a menu bar pseudo-window in case we don't have X toolkit
681 support. Such windows don't have a cursor, so don't display it
682 here. */
683
684 static void
685 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
686 struct window *w;
687 int cursor_on_p, mouse_face_overwritten_p;
688 {
689 if (!w->pseudo_window_p)
690 {
691 struct x_display_info *dpyinfo
692 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
693
694 BLOCK_INPUT;
695
696 /* If a row with mouse-face was overwritten, arrange for
697 XTframe_up_to_date to redisplay the mouse highlight. */
698 if (mouse_face_overwritten_p)
699 {
700 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
701 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
702 dpyinfo->mouse_face_window = Qnil;
703 }
704
705 if (cursor_on_p)
706 x_display_and_set_cursor (w, 1, output_cursor.hpos,
707 output_cursor.vpos,
708 output_cursor.x, output_cursor.y);
709
710 x_draw_vertical_border (w);
711 UNBLOCK_INPUT;
712 }
713
714 updated_window = NULL;
715 }
716
717
718 /* End update of frame F. This function is installed as a hook in
719 update_end. */
720
721 static void
722 x_update_end (f)
723 struct frame *f;
724 {
725 /* Mouse highlight may be displayed again. */
726 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
727
728 BLOCK_INPUT;
729 XFlush (FRAME_X_DISPLAY (f));
730 UNBLOCK_INPUT;
731 }
732
733
734 /* This function is called from various places in xdisp.c whenever a
735 complete update has been performed. The global variable
736 updated_window is not available here. */
737
738 static void
739 XTframe_up_to_date (f)
740 struct frame *f;
741 {
742 if (FRAME_X_P (f))
743 {
744 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
745
746 if (dpyinfo->mouse_face_deferred_gc
747 || f == dpyinfo->mouse_face_mouse_frame)
748 {
749 BLOCK_INPUT;
750 if (dpyinfo->mouse_face_mouse_frame)
751 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
752 dpyinfo->mouse_face_mouse_x,
753 dpyinfo->mouse_face_mouse_y);
754 dpyinfo->mouse_face_deferred_gc = 0;
755 UNBLOCK_INPUT;
756 }
757 }
758 }
759
760
761 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
762 arrow bitmaps, or clear the areas where they would be displayed
763 before DESIRED_ROW is made current. The window being updated is
764 found in updated_window. This function It is called from
765 update_window_line only if it is known that there are differences
766 between bitmaps to be drawn between current row and DESIRED_ROW. */
767
768 static void
769 x_after_update_window_line (desired_row)
770 struct glyph_row *desired_row;
771 {
772 struct window *w = updated_window;
773
774 xassert (w);
775
776 if (!desired_row->mode_line_p && !w->pseudo_window_p)
777 {
778 BLOCK_INPUT;
779 x_draw_row_bitmaps (w, desired_row);
780
781 /* When a window has disappeared, make sure that no rest of
782 full-width rows stays visible in the internal border. */
783 if (windows_or_buffers_changed)
784 {
785 struct frame *f = XFRAME (w->frame);
786 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
787 int height = desired_row->visible_height;
788 int x = (window_box_right (w, -1)
789 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
790 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
791
792 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
793 x, y, width, height, False);
794 }
795
796 UNBLOCK_INPUT;
797 }
798 }
799
800
801 /* Draw the bitmap WHICH in one of the areas to the left or right of
802 window W. ROW is the glyph row for which to display the bitmap; it
803 determines the vertical position at which the bitmap has to be
804 drawn. */
805
806 static void
807 x_draw_bitmap (w, row, which)
808 struct window *w;
809 struct glyph_row *row;
810 enum bitmap_type which;
811 {
812 struct frame *f = XFRAME (WINDOW_FRAME (w));
813 Display *display = FRAME_X_DISPLAY (f);
814 Window window = FRAME_X_WINDOW (f);
815 int x, y, wd, h, dy;
816 unsigned char *bits;
817 Pixmap pixmap;
818 GC gc = f->output_data.x->normal_gc;
819 struct face *face;
820 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
821
822 /* Must clip because of partially visible lines. */
823 x_clip_to_row (w, row, gc, 1);
824
825 switch (which)
826 {
827 case LEFT_TRUNCATION_BITMAP:
828 wd = left_width;
829 h = left_height;
830 bits = left_bits;
831 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
832 - wd
833 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
834 break;
835
836 case OVERLAY_ARROW_BITMAP:
837 wd = left_width;
838 h = left_height;
839 bits = ov_bits;
840 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
841 - wd
842 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
843 break;
844
845 case RIGHT_TRUNCATION_BITMAP:
846 wd = right_width;
847 h = right_height;
848 bits = right_bits;
849 x = window_box_right (w, -1);
850 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
851 break;
852
853 case CONTINUED_LINE_BITMAP:
854 wd = right_width;
855 h = right_height;
856 bits = continued_bits;
857 x = window_box_right (w, -1);
858 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
859 break;
860
861 case CONTINUATION_LINE_BITMAP:
862 wd = continuation_width;
863 h = continuation_height;
864 bits = continuation_bits;
865 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
866 - wd
867 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
868 break;
869
870 case ZV_LINE_BITMAP:
871 wd = zv_width;
872 h = zv_height;
873 bits = zv_bits;
874 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
875 - wd
876 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
877 break;
878
879 default:
880 abort ();
881 }
882
883 /* Convert to frame coordinates. Set dy to the offset in the row to
884 start drawing the bitmap. */
885 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
886 dy = (row->height - h) / 2;
887
888 /* Draw the bitmap. I believe these small pixmaps can be cached
889 by the server. */
890 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
891 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
892 face->foreground,
893 face->background, depth);
894 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
895 XFreePixmap (display, pixmap);
896 XSetClipMask (display, gc, None);
897 }
898
899
900 /* Draw flags bitmaps for glyph row ROW on window W. Call this
901 function with input blocked. */
902
903 static void
904 x_draw_row_bitmaps (w, row)
905 struct window *w;
906 struct glyph_row *row;
907 {
908 struct frame *f = XFRAME (w->frame);
909 enum bitmap_type bitmap;
910 struct face *face;
911 int header_line_height = -1;
912
913 xassert (interrupt_input_blocked);
914
915 /* If row is completely invisible, because of vscrolling, we
916 don't have to draw anything. */
917 if (row->visible_height <= 0)
918 return;
919
920 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
921 PREPARE_FACE_FOR_DISPLAY (f, face);
922
923 /* Decide which bitmap to draw at the left side. */
924 if (row->overlay_arrow_p)
925 bitmap = OVERLAY_ARROW_BITMAP;
926 else if (row->truncated_on_left_p)
927 bitmap = LEFT_TRUNCATION_BITMAP;
928 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
929 bitmap = CONTINUATION_LINE_BITMAP;
930 else if (row->indicate_empty_line_p)
931 bitmap = ZV_LINE_BITMAP;
932 else
933 bitmap = NO_BITMAP;
934
935 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
936 the flags area. */
937 if (bitmap == NO_BITMAP
938 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
939 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
940 {
941 /* If W has a vertical border to its left, don't draw over it. */
942 int border = ((XFASTINT (w->left) > 0
943 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
944 ? 1 : 0);
945 int left = window_box_left (w, -1);
946
947 if (header_line_height < 0)
948 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
949
950 /* In case the same realized face is used for bitmap areas and
951 for something displayed in the text (e.g. face `region' on
952 mono-displays, the fill style may have been changed to
953 FillSolid in x_draw_glyph_string_background. */
954 if (face->stipple)
955 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
956 else
957 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
958
959 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
960 face->gc,
961 (left
962 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
963 + border),
964 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
965 row->y)),
966 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
967 row->visible_height);
968 if (!face->stipple)
969 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
970 }
971
972 /* Draw the left bitmap. */
973 if (bitmap != NO_BITMAP)
974 x_draw_bitmap (w, row, bitmap);
975
976 /* Decide which bitmap to draw at the right side. */
977 if (row->truncated_on_right_p)
978 bitmap = RIGHT_TRUNCATION_BITMAP;
979 else if (row->continued_p)
980 bitmap = CONTINUED_LINE_BITMAP;
981 else
982 bitmap = NO_BITMAP;
983
984 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
985 the flags area. */
986 if (bitmap == NO_BITMAP
987 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
988 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
989 {
990 int right = window_box_right (w, -1);
991
992 if (header_line_height < 0)
993 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
994
995 /* In case the same realized face is used for bitmap areas and
996 for something displayed in the text (e.g. face `region' on
997 mono-displays, the fill style may have been changed to
998 FillSolid in x_draw_glyph_string_background. */
999 if (face->stipple)
1000 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1001 else
1002 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1003 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1004 face->gc,
1005 right,
1006 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1007 row->y)),
1008 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1009 row->visible_height);
1010 if (!face->stipple)
1011 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1012 }
1013
1014 /* Draw the right bitmap. */
1015 if (bitmap != NO_BITMAP)
1016 x_draw_bitmap (w, row, bitmap);
1017 }
1018
1019 \f
1020 /***********************************************************************
1021 Line Highlighting
1022 ***********************************************************************/
1023
1024 /* External interface to control of standout mode. Not used for X
1025 frames. Aborts when called. */
1026
1027 static void
1028 XTreassert_line_highlight (new, vpos)
1029 int new, vpos;
1030 {
1031 abort ();
1032 }
1033
1034
1035 /* Call this when about to modify line at position VPOS and change
1036 whether it is highlighted. Not used for X frames. Aborts when
1037 called. */
1038
1039 static void
1040 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1041 int new_highlight, vpos, y, first_unused_hpos;
1042 {
1043 abort ();
1044 }
1045
1046
1047 /* This is called when starting Emacs and when restarting after
1048 suspend. When starting Emacs, no X window is mapped. And nothing
1049 must be done to Emacs's own window if it is suspended (though that
1050 rarely happens). */
1051
1052 static void
1053 XTset_terminal_modes ()
1054 {
1055 }
1056
1057 /* This is called when exiting or suspending Emacs. Exiting will make
1058 the X-windows go away, and suspending requires no action. */
1059
1060 static void
1061 XTreset_terminal_modes ()
1062 {
1063 }
1064
1065
1066 \f
1067 /***********************************************************************
1068 Output Cursor
1069 ***********************************************************************/
1070
1071 /* Set the global variable output_cursor to CURSOR. All cursor
1072 positions are relative to updated_window. */
1073
1074 static void
1075 set_output_cursor (cursor)
1076 struct cursor_pos *cursor;
1077 {
1078 output_cursor.hpos = cursor->hpos;
1079 output_cursor.vpos = cursor->vpos;
1080 output_cursor.x = cursor->x;
1081 output_cursor.y = cursor->y;
1082 }
1083
1084
1085 /* Set a nominal cursor position.
1086
1087 HPOS and VPOS are column/row positions in a window glyph matrix. X
1088 and Y are window text area relative pixel positions.
1089
1090 If this is done during an update, updated_window will contain the
1091 window that is being updated and the position is the future output
1092 cursor position for that window. If updated_window is null, use
1093 selected_window and display the cursor at the given position. */
1094
1095 static void
1096 XTcursor_to (vpos, hpos, y, x)
1097 int vpos, hpos, y, x;
1098 {
1099 struct window *w;
1100
1101 /* If updated_window is not set, work on selected_window. */
1102 if (updated_window)
1103 w = updated_window;
1104 else
1105 w = XWINDOW (selected_window);
1106
1107 /* Set the output cursor. */
1108 output_cursor.hpos = hpos;
1109 output_cursor.vpos = vpos;
1110 output_cursor.x = x;
1111 output_cursor.y = y;
1112
1113 /* If not called as part of an update, really display the cursor.
1114 This will also set the cursor position of W. */
1115 if (updated_window == NULL)
1116 {
1117 BLOCK_INPUT;
1118 x_display_cursor (w, 1, hpos, vpos, x, y);
1119 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1120 UNBLOCK_INPUT;
1121 }
1122 }
1123
1124
1125 \f
1126 /***********************************************************************
1127 Display Iterator
1128 ***********************************************************************/
1129
1130 /* Function prototypes of this page. */
1131
1132 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1133 struct glyph *,
1134 XChar2b *,
1135 int *));
1136 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1137 int, XChar2b *, int));
1138 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1139 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1140 static void x_append_glyph P_ ((struct it *));
1141 static void x_append_composite_glyph P_ ((struct it *));
1142 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1143 int, int, double));
1144 static void x_produce_glyphs P_ ((struct it *));
1145 static void x_produce_image_glyph P_ ((struct it *it));
1146
1147
1148 /* Return a pointer to per-char metric information in FONT of a
1149 character pointed by B which is a pointer to an XChar2b. */
1150
1151 #define PER_CHAR_METRIC(font, b) \
1152 ((font)->per_char \
1153 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1154 + (((font)->min_byte1 || (font)->max_byte1) \
1155 ? (((b)->byte1 - (font)->min_byte1) \
1156 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1157 : 0)) \
1158 : &((font)->max_bounds))
1159
1160
1161 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1162 is not contained in the font. */
1163
1164 static INLINE XCharStruct *
1165 x_per_char_metric (font, char2b)
1166 XFontStruct *font;
1167 XChar2b *char2b;
1168 {
1169 /* The result metric information. */
1170 XCharStruct *pcm = NULL;
1171
1172 xassert (font && char2b);
1173
1174 if (font->per_char != NULL)
1175 {
1176 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1177 {
1178 /* min_char_or_byte2 specifies the linear character index
1179 corresponding to the first element of the per_char array,
1180 max_char_or_byte2 is the index of the last character. A
1181 character with non-zero CHAR2B->byte1 is not in the font.
1182 A character with byte2 less than min_char_or_byte2 or
1183 greater max_char_or_byte2 is not in the font. */
1184 if (char2b->byte1 == 0
1185 && char2b->byte2 >= font->min_char_or_byte2
1186 && char2b->byte2 <= font->max_char_or_byte2)
1187 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1188 }
1189 else
1190 {
1191 /* If either min_byte1 or max_byte1 are nonzero, both
1192 min_char_or_byte2 and max_char_or_byte2 are less than
1193 256, and the 2-byte character index values corresponding
1194 to the per_char array element N (counting from 0) are:
1195
1196 byte1 = N/D + min_byte1
1197 byte2 = N\D + min_char_or_byte2
1198
1199 where:
1200
1201 D = max_char_or_byte2 - min_char_or_byte2 + 1
1202 / = integer division
1203 \ = integer modulus */
1204 if (char2b->byte1 >= font->min_byte1
1205 && char2b->byte1 <= font->max_byte1
1206 && char2b->byte2 >= font->min_char_or_byte2
1207 && char2b->byte2 <= font->max_char_or_byte2)
1208 {
1209 pcm = (font->per_char
1210 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1211 * (char2b->byte1 - font->min_byte1))
1212 + (char2b->byte2 - font->min_char_or_byte2));
1213 }
1214 }
1215 }
1216 else
1217 {
1218 /* If the per_char pointer is null, all glyphs between the first
1219 and last character indexes inclusive have the same
1220 information, as given by both min_bounds and max_bounds. */
1221 if (char2b->byte2 >= font->min_char_or_byte2
1222 && char2b->byte2 <= font->max_char_or_byte2)
1223 pcm = &font->max_bounds;
1224 }
1225
1226 return ((pcm == NULL
1227 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1228 ? NULL : pcm);
1229 }
1230
1231
1232 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1233 the two-byte form of C. Encoding is returned in *CHAR2B. */
1234
1235 static INLINE void
1236 x_encode_char (c, char2b, font_info)
1237 int c;
1238 XChar2b *char2b;
1239 struct font_info *font_info;
1240 {
1241 int charset = CHAR_CHARSET (c);
1242 XFontStruct *font = font_info->font;
1243
1244 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1245 This may be either a program in a special encoder language or a
1246 fixed encoding. */
1247 if (font_info->font_encoder)
1248 {
1249 /* It's a program. */
1250 struct ccl_program *ccl = font_info->font_encoder;
1251
1252 if (CHARSET_DIMENSION (charset) == 1)
1253 {
1254 ccl->reg[0] = charset;
1255 ccl->reg[1] = char2b->byte2;
1256 }
1257 else
1258 {
1259 ccl->reg[0] = charset;
1260 ccl->reg[1] = char2b->byte1;
1261 ccl->reg[2] = char2b->byte2;
1262 }
1263
1264 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1265
1266 /* We assume that MSBs are appropriately set/reset by CCL
1267 program. */
1268 if (font->max_byte1 == 0) /* 1-byte font */
1269 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1270 else
1271 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1272 }
1273 else if (font_info->encoding[charset])
1274 {
1275 /* Fixed encoding scheme. See fontset.h for the meaning of the
1276 encoding numbers. */
1277 int enc = font_info->encoding[charset];
1278
1279 if ((enc == 1 || enc == 2)
1280 && CHARSET_DIMENSION (charset) == 2)
1281 char2b->byte1 |= 0x80;
1282
1283 if (enc == 1 || enc == 3)
1284 char2b->byte2 |= 0x80;
1285 }
1286 }
1287
1288
1289 /* Get face and two-byte form of character C in face FACE_ID on frame
1290 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1291 means we want to display multibyte text. Value is a pointer to a
1292 realized face that is ready for display. */
1293
1294 static INLINE struct face *
1295 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1296 struct frame *f;
1297 int c, face_id;
1298 XChar2b *char2b;
1299 int multibyte_p;
1300 {
1301 struct face *face = FACE_FROM_ID (f, face_id);
1302
1303 if (!multibyte_p)
1304 {
1305 /* Unibyte case. We don't have to encode, but we have to make
1306 sure to use a face suitable for unibyte. */
1307 char2b->byte1 = 0;
1308 char2b->byte2 = c;
1309 face_id = FACE_FOR_CHAR (f, face, c);
1310 face = FACE_FROM_ID (f, face_id);
1311 }
1312 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1313 {
1314 /* Case of ASCII in a face known to fit ASCII. */
1315 char2b->byte1 = 0;
1316 char2b->byte2 = c;
1317 }
1318 else
1319 {
1320 int c1, c2, charset;
1321
1322 /* Split characters into bytes. If c2 is -1 afterwards, C is
1323 really a one-byte character so that byte1 is zero. */
1324 SPLIT_CHAR (c, charset, c1, c2);
1325 if (c2 > 0)
1326 char2b->byte1 = c1, char2b->byte2 = c2;
1327 else
1328 char2b->byte1 = 0, char2b->byte2 = c1;
1329
1330 /* Maybe encode the character in *CHAR2B. */
1331 if (face->font != NULL)
1332 {
1333 struct font_info *font_info
1334 = FONT_INFO_FROM_ID (f, face->font_info_id);
1335 if (font_info)
1336 x_encode_char (c, char2b, font_info);
1337 }
1338 }
1339
1340 /* Make sure X resources of the face are allocated. */
1341 xassert (face != NULL);
1342 PREPARE_FACE_FOR_DISPLAY (f, face);
1343
1344 return face;
1345 }
1346
1347
1348 /* Get face and two-byte form of character glyph GLYPH on frame F.
1349 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1350 a pointer to a realized face that is ready for display. */
1351
1352 static INLINE struct face *
1353 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1354 struct frame *f;
1355 struct glyph *glyph;
1356 XChar2b *char2b;
1357 int *two_byte_p;
1358 {
1359 struct face *face;
1360
1361 xassert (glyph->type == CHAR_GLYPH);
1362 face = FACE_FROM_ID (f, glyph->face_id);
1363
1364 if (two_byte_p)
1365 *two_byte_p = 0;
1366
1367 if (!glyph->multibyte_p)
1368 {
1369 /* Unibyte case. We don't have to encode, but we have to make
1370 sure to use a face suitable for unibyte. */
1371 char2b->byte1 = 0;
1372 char2b->byte2 = glyph->u.ch;
1373 }
1374 else if (glyph->u.ch < 128
1375 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1376 {
1377 /* Case of ASCII in a face known to fit ASCII. */
1378 char2b->byte1 = 0;
1379 char2b->byte2 = glyph->u.ch;
1380 }
1381 else
1382 {
1383 int c1, c2, charset;
1384
1385 /* Split characters into bytes. If c2 is -1 afterwards, C is
1386 really a one-byte character so that byte1 is zero. */
1387 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1388 if (c2 > 0)
1389 char2b->byte1 = c1, char2b->byte2 = c2;
1390 else
1391 char2b->byte1 = 0, char2b->byte2 = c1;
1392
1393 /* Maybe encode the character in *CHAR2B. */
1394 if (charset != CHARSET_ASCII)
1395 {
1396 struct font_info *font_info
1397 = FONT_INFO_FROM_ID (f, face->font_info_id);
1398 if (font_info)
1399 {
1400 x_encode_char (glyph->u.ch, char2b, font_info);
1401 if (two_byte_p)
1402 *two_byte_p
1403 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1404 }
1405 }
1406 }
1407
1408 /* Make sure X resources of the face are allocated. */
1409 xassert (face != NULL);
1410 PREPARE_FACE_FOR_DISPLAY (f, face);
1411 return face;
1412 }
1413
1414
1415 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1416 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1417
1418 static INLINE void
1419 x_append_glyph (it)
1420 struct it *it;
1421 {
1422 struct glyph *glyph;
1423 enum glyph_row_area area = it->area;
1424
1425 xassert (it->glyph_row);
1426 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1427
1428 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1429 if (glyph < it->glyph_row->glyphs[area + 1])
1430 {
1431 glyph->charpos = CHARPOS (it->position);
1432 glyph->object = it->object;
1433 glyph->pixel_width = it->pixel_width;
1434 glyph->voffset = it->voffset;
1435 glyph->type = CHAR_GLYPH;
1436 glyph->multibyte_p = it->multibyte_p;
1437 glyph->left_box_line_p = it->start_of_box_run_p;
1438 glyph->right_box_line_p = it->end_of_box_run_p;
1439 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1440 || it->phys_descent > it->descent);
1441 glyph->padding_p = 0;
1442 glyph->glyph_not_available_p = it->glyph_not_available_p;
1443 glyph->face_id = it->face_id;
1444 glyph->u.ch = it->char_to_display;
1445 ++it->glyph_row->used[area];
1446 }
1447 }
1448
1449 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1450 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1451
1452 static INLINE void
1453 x_append_composite_glyph (it)
1454 struct it *it;
1455 {
1456 struct glyph *glyph;
1457 enum glyph_row_area area = it->area;
1458
1459 xassert (it->glyph_row);
1460
1461 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1462 if (glyph < it->glyph_row->glyphs[area + 1])
1463 {
1464 glyph->charpos = CHARPOS (it->position);
1465 glyph->object = it->object;
1466 glyph->pixel_width = it->pixel_width;
1467 glyph->voffset = it->voffset;
1468 glyph->type = COMPOSITE_GLYPH;
1469 glyph->multibyte_p = it->multibyte_p;
1470 glyph->left_box_line_p = it->start_of_box_run_p;
1471 glyph->right_box_line_p = it->end_of_box_run_p;
1472 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1473 || it->phys_descent > it->descent);
1474 glyph->padding_p = 0;
1475 glyph->glyph_not_available_p = 0;
1476 glyph->face_id = it->face_id;
1477 glyph->u.cmp_id = it->cmp_id;
1478 ++it->glyph_row->used[area];
1479 }
1480 }
1481
1482
1483 /* Change IT->ascent and IT->height according to the setting of
1484 IT->voffset. */
1485
1486 static INLINE void
1487 take_vertical_position_into_account (it)
1488 struct it *it;
1489 {
1490 if (it->voffset)
1491 {
1492 if (it->voffset < 0)
1493 /* Increase the ascent so that we can display the text higher
1494 in the line. */
1495 it->ascent += abs (it->voffset);
1496 else
1497 /* Increase the descent so that we can display the text lower
1498 in the line. */
1499 it->descent += it->voffset;
1500 }
1501 }
1502
1503
1504 /* Produce glyphs/get display metrics for the image IT is loaded with.
1505 See the description of struct display_iterator in dispextern.h for
1506 an overview of struct display_iterator. */
1507
1508 static void
1509 x_produce_image_glyph (it)
1510 struct it *it;
1511 {
1512 struct image *img;
1513 struct face *face;
1514
1515 xassert (it->what == IT_IMAGE);
1516
1517 face = FACE_FROM_ID (it->f, it->face_id);
1518 img = IMAGE_FROM_ID (it->f, it->image_id);
1519 xassert (img);
1520
1521 /* Make sure X resources of the face and image are loaded. */
1522 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1523 prepare_image_for_display (it->f, img);
1524
1525 it->ascent = it->phys_ascent = image_ascent (img, face);
1526 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1527 it->pixel_width = img->width + 2 * img->margin;
1528
1529 it->nglyphs = 1;
1530
1531 if (face->box != FACE_NO_BOX)
1532 {
1533 it->ascent += face->box_line_width;
1534 it->descent += face->box_line_width;
1535
1536 if (it->start_of_box_run_p)
1537 it->pixel_width += face->box_line_width;
1538 if (it->end_of_box_run_p)
1539 it->pixel_width += face->box_line_width;
1540 }
1541
1542 take_vertical_position_into_account (it);
1543
1544 if (it->glyph_row)
1545 {
1546 struct glyph *glyph;
1547 enum glyph_row_area area = it->area;
1548
1549 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1550 if (glyph < it->glyph_row->glyphs[area + 1])
1551 {
1552 glyph->charpos = CHARPOS (it->position);
1553 glyph->object = it->object;
1554 glyph->pixel_width = it->pixel_width;
1555 glyph->voffset = it->voffset;
1556 glyph->type = IMAGE_GLYPH;
1557 glyph->multibyte_p = it->multibyte_p;
1558 glyph->left_box_line_p = it->start_of_box_run_p;
1559 glyph->right_box_line_p = it->end_of_box_run_p;
1560 glyph->overlaps_vertically_p = 0;
1561 glyph->padding_p = 0;
1562 glyph->glyph_not_available_p = 0;
1563 glyph->face_id = it->face_id;
1564 glyph->u.img_id = img->id;
1565 ++it->glyph_row->used[area];
1566 }
1567 }
1568 }
1569
1570
1571 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1572 of the glyph, WIDTH and HEIGHT are the width and height of the
1573 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1574 ascent of the glyph (0 <= ASCENT <= 1). */
1575
1576 static void
1577 x_append_stretch_glyph (it, object, width, height, ascent)
1578 struct it *it;
1579 Lisp_Object object;
1580 int width, height;
1581 double ascent;
1582 {
1583 struct glyph *glyph;
1584 enum glyph_row_area area = it->area;
1585
1586 xassert (ascent >= 0 && ascent <= 1);
1587
1588 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1589 if (glyph < it->glyph_row->glyphs[area + 1])
1590 {
1591 glyph->charpos = CHARPOS (it->position);
1592 glyph->object = object;
1593 glyph->pixel_width = width;
1594 glyph->voffset = it->voffset;
1595 glyph->type = STRETCH_GLYPH;
1596 glyph->multibyte_p = it->multibyte_p;
1597 glyph->left_box_line_p = it->start_of_box_run_p;
1598 glyph->right_box_line_p = it->end_of_box_run_p;
1599 glyph->overlaps_vertically_p = 0;
1600 glyph->padding_p = 0;
1601 glyph->glyph_not_available_p = 0;
1602 glyph->face_id = it->face_id;
1603 glyph->u.stretch.ascent = height * ascent;
1604 glyph->u.stretch.height = height;
1605 ++it->glyph_row->used[area];
1606 }
1607 }
1608
1609
1610 /* Produce a stretch glyph for iterator IT. IT->object is the value
1611 of the glyph property displayed. The value must be a list
1612 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1613 being recognized:
1614
1615 1. `:width WIDTH' specifies that the space should be WIDTH *
1616 canonical char width wide. WIDTH may be an integer or floating
1617 point number.
1618
1619 2. `:relative-width FACTOR' specifies that the width of the stretch
1620 should be computed from the width of the first character having the
1621 `glyph' property, and should be FACTOR times that width.
1622
1623 3. `:align-to HPOS' specifies that the space should be wide enough
1624 to reach HPOS, a value in canonical character units.
1625
1626 Exactly one of the above pairs must be present.
1627
1628 4. `:height HEIGHT' specifies that the height of the stretch produced
1629 should be HEIGHT, measured in canonical character units.
1630
1631 5. `:relative-height FACTOR' specifies that the height of the the
1632 stretch should be FACTOR times the height of the characters having
1633 the glyph property.
1634
1635 Either none or exactly one of 4 or 5 must be present.
1636
1637 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1638 of the stretch should be used for the ascent of the stretch.
1639 ASCENT must be in the range 0 <= ASCENT <= 100. */
1640
1641 #define NUMVAL(X) \
1642 ((INTEGERP (X) || FLOATP (X)) \
1643 ? XFLOATINT (X) \
1644 : - 1)
1645
1646
1647 static void
1648 x_produce_stretch_glyph (it)
1649 struct it *it;
1650 {
1651 /* (space :width WIDTH :height HEIGHT. */
1652 #if GLYPH_DEBUG
1653 extern Lisp_Object Qspace;
1654 #endif
1655 extern Lisp_Object QCwidth, QCheight, QCascent;
1656 extern Lisp_Object QCrelative_width, QCrelative_height;
1657 extern Lisp_Object QCalign_to;
1658 Lisp_Object prop, plist;
1659 double width = 0, height = 0, ascent = 0;
1660 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1661 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1662
1663 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1664
1665 /* List should start with `space'. */
1666 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1667 plist = XCDR (it->object);
1668
1669 /* Compute the width of the stretch. */
1670 if (prop = Fplist_get (plist, QCwidth),
1671 NUMVAL (prop) > 0)
1672 /* Absolute width `:width WIDTH' specified and valid. */
1673 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1674 else if (prop = Fplist_get (plist, QCrelative_width),
1675 NUMVAL (prop) > 0)
1676 {
1677 /* Relative width `:relative-width FACTOR' specified and valid.
1678 Compute the width of the characters having the `glyph'
1679 property. */
1680 struct it it2;
1681 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1682
1683 it2 = *it;
1684 if (it->multibyte_p)
1685 {
1686 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1687 - IT_BYTEPOS (*it));
1688 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1689 }
1690 else
1691 it2.c = *p, it2.len = 1;
1692
1693 it2.glyph_row = NULL;
1694 it2.what = IT_CHARACTER;
1695 x_produce_glyphs (&it2);
1696 width = NUMVAL (prop) * it2.pixel_width;
1697 }
1698 else if (prop = Fplist_get (plist, QCalign_to),
1699 NUMVAL (prop) > 0)
1700 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1701 else
1702 /* Nothing specified -> width defaults to canonical char width. */
1703 width = CANON_X_UNIT (it->f);
1704
1705 /* Compute height. */
1706 if (prop = Fplist_get (plist, QCheight),
1707 NUMVAL (prop) > 0)
1708 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1709 else if (prop = Fplist_get (plist, QCrelative_height),
1710 NUMVAL (prop) > 0)
1711 height = FONT_HEIGHT (font) * NUMVAL (prop);
1712 else
1713 height = FONT_HEIGHT (font);
1714
1715 /* Compute percentage of height used for ascent. If
1716 `:ascent ASCENT' is present and valid, use that. Otherwise,
1717 derive the ascent from the font in use. */
1718 if (prop = Fplist_get (plist, QCascent),
1719 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1720 ascent = NUMVAL (prop) / 100.0;
1721 else
1722 ascent = (double) font->ascent / FONT_HEIGHT (font);
1723
1724 if (width <= 0)
1725 width = 1;
1726 if (height <= 0)
1727 height = 1;
1728
1729 if (it->glyph_row)
1730 {
1731 Lisp_Object object = it->stack[it->sp - 1].string;
1732 if (!STRINGP (object))
1733 object = it->w->buffer;
1734 x_append_stretch_glyph (it, object, width, height, ascent);
1735 }
1736
1737 it->pixel_width = width;
1738 it->ascent = it->phys_ascent = height * ascent;
1739 it->descent = it->phys_descent = height - it->ascent;
1740 it->nglyphs = 1;
1741
1742 if (face->box != FACE_NO_BOX)
1743 {
1744 it->ascent += face->box_line_width;
1745 it->descent += face->box_line_width;
1746
1747 if (it->start_of_box_run_p)
1748 it->pixel_width += face->box_line_width;
1749 if (it->end_of_box_run_p)
1750 it->pixel_width += face->box_line_width;
1751 }
1752
1753 take_vertical_position_into_account (it);
1754 }
1755
1756 /* Return proper value to be used as baseline offset of font that has
1757 ASCENT and DESCENT to draw characters by the font at the vertical
1758 center of the line of frame F.
1759
1760 Here, out task is to find the value of BOFF in the following figure;
1761
1762 -------------------------+-----------+-
1763 -+-+---------+-+ | |
1764 | | | | | |
1765 | | | | F_ASCENT F_HEIGHT
1766 | | | ASCENT | |
1767 HEIGHT | | | | |
1768 | | |-|-+------+-----------|------- baseline
1769 | | | | BOFF | |
1770 | |---------|-+-+ | |
1771 | | | DESCENT | |
1772 -+-+---------+-+ F_DESCENT |
1773 -------------------------+-----------+-
1774
1775 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1776 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1777 DESCENT = FONT->descent
1778 HEIGHT = FONT_HEIGHT (FONT)
1779 F_DESCENT = (F->output_data.x->font->descent
1780 - F->output_data.x->baseline_offset)
1781 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1782 */
1783
1784 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1785 ((FONT)->descent \
1786 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1787 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1788
1789 /* Produce glyphs/get display metrics for the display element IT is
1790 loaded with. See the description of struct display_iterator in
1791 dispextern.h for an overview of struct display_iterator. */
1792
1793 static void
1794 x_produce_glyphs (it)
1795 struct it *it;
1796 {
1797 it->glyph_not_available_p = 0;
1798
1799 if (it->what == IT_CHARACTER)
1800 {
1801 XChar2b char2b;
1802 XFontStruct *font;
1803 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1804 XCharStruct *pcm;
1805 int font_not_found_p;
1806 struct font_info *font_info;
1807 int boff; /* baseline offset */
1808
1809 /* Maybe translate single-byte characters to multibyte, or the
1810 other way. */
1811 it->char_to_display = it->c;
1812 if (!ASCII_BYTE_P (it->c))
1813 {
1814 if (unibyte_display_via_language_environment
1815 && SINGLE_BYTE_CHAR_P (it->c)
1816 && (it->c >= 0240
1817 || !NILP (Vnonascii_translation_table)))
1818 {
1819 it->char_to_display = unibyte_char_to_multibyte (it->c);
1820 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1821 face = FACE_FROM_ID (it->f, it->face_id);
1822 }
1823 else if (!SINGLE_BYTE_CHAR_P (it->c)
1824 && !it->multibyte_p)
1825 {
1826 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1827 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1828 face = FACE_FROM_ID (it->f, it->face_id);
1829 }
1830 }
1831
1832 /* Get font to use. Encode IT->char_to_display. */
1833 x_get_char_face_and_encoding (it->f, it->char_to_display,
1834 it->face_id, &char2b,
1835 it->multibyte_p);
1836 font = face->font;
1837
1838 /* When no suitable font found, use the default font. */
1839 font_not_found_p = font == NULL;
1840 if (font_not_found_p)
1841 {
1842 font = FRAME_FONT (it->f);
1843 boff = it->f->output_data.x->baseline_offset;
1844 font_info = NULL;
1845 }
1846 else
1847 {
1848 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1849 boff = font_info->baseline_offset;
1850 if (font_info->vertical_centering)
1851 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1852 }
1853
1854 if (it->char_to_display >= ' '
1855 && (!it->multibyte_p || it->char_to_display < 128))
1856 {
1857 /* Either unibyte or ASCII. */
1858 int stretched_p;
1859
1860 it->nglyphs = 1;
1861
1862 pcm = x_per_char_metric (font, &char2b);
1863 it->ascent = font->ascent + boff;
1864 it->descent = font->descent - boff;
1865
1866 if (pcm)
1867 {
1868 it->phys_ascent = pcm->ascent + boff;
1869 it->phys_descent = pcm->descent - boff;
1870 it->pixel_width = pcm->width;
1871 }
1872 else
1873 {
1874 it->glyph_not_available_p = 1;
1875 it->phys_ascent = font->ascent + boff;
1876 it->phys_descent = font->descent - boff;
1877 it->pixel_width = FONT_WIDTH (font);
1878 }
1879
1880 /* If this is a space inside a region of text with
1881 `space-width' property, change its width. */
1882 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1883 if (stretched_p)
1884 it->pixel_width *= XFLOATINT (it->space_width);
1885
1886 /* If face has a box, add the box thickness to the character
1887 height. If character has a box line to the left and/or
1888 right, add the box line width to the character's width. */
1889 if (face->box != FACE_NO_BOX)
1890 {
1891 int thick = face->box_line_width;
1892
1893 it->ascent += thick;
1894 it->descent += thick;
1895
1896 if (it->start_of_box_run_p)
1897 it->pixel_width += thick;
1898 if (it->end_of_box_run_p)
1899 it->pixel_width += thick;
1900 }
1901
1902 /* If face has an overline, add the height of the overline
1903 (1 pixel) and a 1 pixel margin to the character height. */
1904 if (face->overline_p)
1905 it->ascent += 2;
1906
1907 take_vertical_position_into_account (it);
1908
1909 /* If we have to actually produce glyphs, do it. */
1910 if (it->glyph_row)
1911 {
1912 if (stretched_p)
1913 {
1914 /* Translate a space with a `space-width' property
1915 into a stretch glyph. */
1916 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1917 x_append_stretch_glyph (it, it->object, it->pixel_width,
1918 it->ascent + it->descent, ascent);
1919 }
1920 else
1921 x_append_glyph (it);
1922
1923 /* If characters with lbearing or rbearing are displayed
1924 in this line, record that fact in a flag of the
1925 glyph row. This is used to optimize X output code. */
1926 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1927 it->glyph_row->contains_overlapping_glyphs_p = 1;
1928 }
1929 }
1930 else if (it->char_to_display == '\n')
1931 {
1932 /* A newline has no width but we need the height of the line. */
1933 it->pixel_width = 0;
1934 it->nglyphs = 0;
1935 it->ascent = it->phys_ascent = font->ascent + boff;
1936 it->descent = it->phys_descent = font->descent - boff;
1937
1938 if (face->box != FACE_NO_BOX)
1939 {
1940 int thick = face->box_line_width;
1941 it->ascent += thick;
1942 it->descent += thick;
1943 }
1944 }
1945 else if (it->char_to_display == '\t')
1946 {
1947 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1948 int x = it->current_x + it->continuation_lines_width;
1949 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1950
1951 /* If the distance from the current position to the next tab
1952 stop is less than a canonical character width, use the
1953 tab stop after that. */
1954 if (next_tab_x - x < CANON_X_UNIT (it->f))
1955 next_tab_x += tab_width;
1956
1957 it->pixel_width = next_tab_x - x;
1958 it->nglyphs = 1;
1959 it->ascent = it->phys_ascent = font->ascent + boff;
1960 it->descent = it->phys_descent = font->descent - boff;
1961
1962 if (it->glyph_row)
1963 {
1964 double ascent = (double) it->ascent / (it->ascent + it->descent);
1965 x_append_stretch_glyph (it, it->object, it->pixel_width,
1966 it->ascent + it->descent, ascent);
1967 }
1968 }
1969 else
1970 {
1971 /* A multi-byte character. Assume that the display width of the
1972 character is the width of the character multiplied by the
1973 width of the font. */
1974
1975 /* If we found a font, this font should give us the right
1976 metrics. If we didn't find a font, use the frame's
1977 default font and calculate the width of the character
1978 from the charset width; this is what old redisplay code
1979 did. */
1980 pcm = x_per_char_metric (font, &char2b);
1981 if (font_not_found_p || !pcm)
1982 {
1983 int charset = CHAR_CHARSET (it->char_to_display);
1984
1985 it->glyph_not_available_p = 1;
1986 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1987 * CHARSET_WIDTH (charset));
1988 it->phys_ascent = font->ascent + boff;
1989 it->phys_descent = font->descent - boff;
1990 }
1991 else
1992 {
1993 it->pixel_width = pcm->width;
1994 it->phys_ascent = pcm->ascent + boff;
1995 it->phys_descent = pcm->descent - boff;
1996 if (it->glyph_row
1997 && (pcm->lbearing < 0
1998 || pcm->rbearing > pcm->width))
1999 it->glyph_row->contains_overlapping_glyphs_p = 1;
2000 }
2001 it->nglyphs = 1;
2002 it->ascent = font->ascent + boff;
2003 it->descent = font->descent - boff;
2004 if (face->box != FACE_NO_BOX)
2005 {
2006 int thick = face->box_line_width;
2007 it->ascent += thick;
2008 it->descent += thick;
2009
2010 if (it->start_of_box_run_p)
2011 it->pixel_width += thick;
2012 if (it->end_of_box_run_p)
2013 it->pixel_width += thick;
2014 }
2015
2016 /* If face has an overline, add the height of the overline
2017 (1 pixel) and a 1 pixel margin to the character height. */
2018 if (face->overline_p)
2019 it->ascent += 2;
2020
2021 take_vertical_position_into_account (it);
2022
2023 if (it->glyph_row)
2024 x_append_glyph (it);
2025 }
2026 }
2027 else if (it->what == IT_COMPOSITION)
2028 {
2029 /* Note: A composition is represented as one glyph in the
2030 glyph matrix. There are no padding glyphs. */
2031 XChar2b char2b;
2032 XFontStruct *font;
2033 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2034 XCharStruct *pcm;
2035 int font_not_found_p;
2036 struct font_info *font_info;
2037 int boff; /* baseline offset */
2038 struct composition *cmp = composition_table[it->cmp_id];
2039
2040 /* Maybe translate single-byte characters to multibyte. */
2041 it->char_to_display = it->c;
2042 if (unibyte_display_via_language_environment
2043 && SINGLE_BYTE_CHAR_P (it->c)
2044 && (it->c >= 0240
2045 || (it->c >= 0200
2046 && !NILP (Vnonascii_translation_table))))
2047 {
2048 it->char_to_display = unibyte_char_to_multibyte (it->c);
2049 }
2050
2051 /* Get face and font to use. Encode IT->char_to_display. */
2052 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2053 face = FACE_FROM_ID (it->f, it->face_id);
2054 x_get_char_face_and_encoding (it->f, it->char_to_display,
2055 it->face_id, &char2b, it->multibyte_p);
2056 font = face->font;
2057
2058 /* When no suitable font found, use the default font. */
2059 font_not_found_p = font == NULL;
2060 if (font_not_found_p)
2061 {
2062 font = FRAME_FONT (it->f);
2063 boff = it->f->output_data.x->baseline_offset;
2064 font_info = NULL;
2065 }
2066 else
2067 {
2068 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2069 boff = font_info->baseline_offset;
2070 if (font_info->vertical_centering)
2071 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2072 }
2073
2074 /* There are no padding glyphs, so there is only one glyph to
2075 produce for the composition. Important is that pixel_width,
2076 ascent and descent are the values of what is drawn by
2077 draw_glyphs (i.e. the values of the overall glyphs composed). */
2078 it->nglyphs = 1;
2079
2080 /* If we have not yet calculated pixel size data of glyphs of
2081 the composition for the current face font, calculate them
2082 now. Theoretically, we have to check all fonts for the
2083 glyphs, but that requires much time and memory space. So,
2084 here we check only the font of the first glyph. This leads
2085 to incorrect display very rarely, and C-l (recenter) can
2086 correct the display anyway. */
2087 if (cmp->font != (void *) font)
2088 {
2089 /* Ascent and descent of the font of the first character of
2090 this composition (adjusted by baseline offset). Ascent
2091 and descent of overall glyphs should not be less than
2092 them respectively. */
2093 int font_ascent = font->ascent + boff;
2094 int font_descent = font->descent - boff;
2095 /* Bounding box of the overall glyphs. */
2096 int leftmost, rightmost, lowest, highest;
2097 int i, width, ascent, descent;
2098
2099 cmp->font = (void *) font;
2100
2101 /* Initialize the bounding box. */
2102 pcm = x_per_char_metric (font, &char2b);
2103 if (pcm)
2104 {
2105 width = pcm->width;
2106 ascent = pcm->ascent;
2107 descent = pcm->descent;
2108 }
2109 else
2110 {
2111 width = FONT_WIDTH (font);
2112 ascent = font->ascent;
2113 descent = font->descent;
2114 }
2115
2116 rightmost = width;
2117 lowest = - descent + boff;
2118 highest = ascent + boff;
2119 leftmost = 0;
2120
2121 if (font_info
2122 && font_info->default_ascent
2123 && CHAR_TABLE_P (Vuse_default_ascent)
2124 && !NILP (Faref (Vuse_default_ascent,
2125 make_number (it->char_to_display))))
2126 highest = font_info->default_ascent + boff;
2127
2128 /* Draw the first glyph at the normal position. It may be
2129 shifted to right later if some other glyphs are drawn at
2130 the left. */
2131 cmp->offsets[0] = 0;
2132 cmp->offsets[1] = boff;
2133
2134 /* Set cmp->offsets for the remaining glyphs. */
2135 for (i = 1; i < cmp->glyph_len; i++)
2136 {
2137 int left, right, btm, top;
2138 int ch = COMPOSITION_GLYPH (cmp, i);
2139 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2140
2141 face = FACE_FROM_ID (it->f, face_id);
2142 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2143 it->multibyte_p);
2144 font = face->font;
2145 if (font == NULL)
2146 {
2147 font = FRAME_FONT (it->f);
2148 boff = it->f->output_data.x->baseline_offset;
2149 font_info = NULL;
2150 }
2151 else
2152 {
2153 font_info
2154 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2155 boff = font_info->baseline_offset;
2156 if (font_info->vertical_centering)
2157 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2158 }
2159
2160 pcm = x_per_char_metric (font, &char2b);
2161 if (pcm)
2162 {
2163 width = pcm->width;
2164 ascent = pcm->ascent;
2165 descent = pcm->descent;
2166 }
2167 else
2168 {
2169 width = FONT_WIDTH (font);
2170 ascent = font->ascent;
2171 descent = font->descent;
2172 }
2173
2174 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2175 {
2176 /* Relative composition with or without
2177 alternate chars. */
2178 left = (leftmost + rightmost - width) / 2;
2179 btm = - descent + boff;
2180 if (font_info && font_info->relative_compose
2181 && (! CHAR_TABLE_P (Vignore_relative_composition)
2182 || NILP (Faref (Vignore_relative_composition,
2183 make_number (ch)))))
2184 {
2185
2186 if (- descent >= font_info->relative_compose)
2187 /* One extra pixel between two glyphs. */
2188 btm = highest + 1;
2189 else if (ascent <= 0)
2190 /* One extra pixel between two glyphs. */
2191 btm = lowest - 1 - ascent - descent;
2192 }
2193 }
2194 else
2195 {
2196 /* A composition rule is specified by an integer
2197 value that encodes global and new reference
2198 points (GREF and NREF). GREF and NREF are
2199 specified by numbers as below:
2200
2201 0---1---2 -- ascent
2202 | |
2203 | |
2204 | |
2205 9--10--11 -- center
2206 | |
2207 ---3---4---5--- baseline
2208 | |
2209 6---7---8 -- descent
2210 */
2211 int rule = COMPOSITION_RULE (cmp, i);
2212 int gref, nref, grefx, grefy, nrefx, nrefy;
2213
2214 COMPOSITION_DECODE_RULE (rule, gref, nref);
2215 grefx = gref % 3, nrefx = nref % 3;
2216 grefy = gref / 3, nrefy = nref / 3;
2217
2218 left = (leftmost
2219 + grefx * (rightmost - leftmost) / 2
2220 - nrefx * width / 2);
2221 btm = ((grefy == 0 ? highest
2222 : grefy == 1 ? 0
2223 : grefy == 2 ? lowest
2224 : (highest + lowest) / 2)
2225 - (nrefy == 0 ? ascent + descent
2226 : nrefy == 1 ? descent - boff
2227 : nrefy == 2 ? 0
2228 : (ascent + descent) / 2));
2229 }
2230
2231 cmp->offsets[i * 2] = left;
2232 cmp->offsets[i * 2 + 1] = btm + descent;
2233
2234 /* Update the bounding box of the overall glyphs. */
2235 right = left + width;
2236 top = btm + descent + ascent;
2237 if (left < leftmost)
2238 leftmost = left;
2239 if (right > rightmost)
2240 rightmost = right;
2241 if (top > highest)
2242 highest = top;
2243 if (btm < lowest)
2244 lowest = btm;
2245 }
2246
2247 /* If there are glyphs whose x-offsets are negative,
2248 shift all glyphs to the right and make all x-offsets
2249 non-negative. */
2250 if (leftmost < 0)
2251 {
2252 for (i = 0; i < cmp->glyph_len; i++)
2253 cmp->offsets[i * 2] -= leftmost;
2254 rightmost -= leftmost;
2255 }
2256
2257 cmp->pixel_width = rightmost;
2258 cmp->ascent = highest;
2259 cmp->descent = - lowest;
2260 if (cmp->ascent < font_ascent)
2261 cmp->ascent = font_ascent;
2262 if (cmp->descent < font_descent)
2263 cmp->descent = font_descent;
2264 }
2265
2266 it->pixel_width = cmp->pixel_width;
2267 it->ascent = it->phys_ascent = cmp->ascent;
2268 it->descent = it->phys_descent = cmp->descent;
2269
2270 if (face->box != FACE_NO_BOX)
2271 {
2272 int thick = face->box_line_width;
2273 it->ascent += thick;
2274 it->descent += thick;
2275
2276 if (it->start_of_box_run_p)
2277 it->pixel_width += thick;
2278 if (it->end_of_box_run_p)
2279 it->pixel_width += thick;
2280 }
2281
2282 /* If face has an overline, add the height of the overline
2283 (1 pixel) and a 1 pixel margin to the character height. */
2284 if (face->overline_p)
2285 it->ascent += 2;
2286
2287 take_vertical_position_into_account (it);
2288
2289 if (it->glyph_row)
2290 x_append_composite_glyph (it);
2291 }
2292 else if (it->what == IT_IMAGE)
2293 x_produce_image_glyph (it);
2294 else if (it->what == IT_STRETCH)
2295 x_produce_stretch_glyph (it);
2296
2297 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2298 because this isn't true for images with `:ascent 100'. */
2299 xassert (it->ascent >= 0 && it->descent >= 0);
2300 if (it->area == TEXT_AREA)
2301 it->current_x += it->pixel_width;
2302
2303 it->descent += it->extra_line_spacing;
2304
2305 it->max_ascent = max (it->max_ascent, it->ascent);
2306 it->max_descent = max (it->max_descent, it->descent);
2307 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2308 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2309 }
2310
2311
2312 /* Estimate the pixel height of the mode or top line on frame F.
2313 FACE_ID specifies what line's height to estimate. */
2314
2315 int
2316 x_estimate_mode_line_height (f, face_id)
2317 struct frame *f;
2318 enum face_id face_id;
2319 {
2320 int height = 1;
2321
2322 /* This function is called so early when Emacs starts that the face
2323 cache and mode line face are not yet initialized. */
2324 if (FRAME_FACE_CACHE (f))
2325 {
2326 struct face *face = FACE_FROM_ID (f, face_id);
2327 if (face)
2328 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2329 }
2330
2331 return height;
2332 }
2333
2334 \f
2335 /***********************************************************************
2336 Glyph display
2337 ***********************************************************************/
2338
2339 /* A sequence of glyphs to be drawn in the same face.
2340
2341 This data structure is not really completely X specific, so it
2342 could possibly, at least partially, be useful for other systems. It
2343 is currently not part of the external redisplay interface because
2344 it's not clear what other systems will need. */
2345
2346 struct glyph_string
2347 {
2348 /* X-origin of the string. */
2349 int x;
2350
2351 /* Y-origin and y-position of the base line of this string. */
2352 int y, ybase;
2353
2354 /* The width of the string, not including a face extension. */
2355 int width;
2356
2357 /* The width of the string, including a face extension. */
2358 int background_width;
2359
2360 /* The height of this string. This is the height of the line this
2361 string is drawn in, and can be different from the height of the
2362 font the string is drawn in. */
2363 int height;
2364
2365 /* Number of pixels this string overwrites in front of its x-origin.
2366 This number is zero if the string has an lbearing >= 0; it is
2367 -lbearing, if the string has an lbearing < 0. */
2368 int left_overhang;
2369
2370 /* Number of pixels this string overwrites past its right-most
2371 nominal x-position, i.e. x + width. Zero if the string's
2372 rbearing is <= its nominal width, rbearing - width otherwise. */
2373 int right_overhang;
2374
2375 /* The frame on which the glyph string is drawn. */
2376 struct frame *f;
2377
2378 /* The window on which the glyph string is drawn. */
2379 struct window *w;
2380
2381 /* X display and window for convenience. */
2382 Display *display;
2383 Window window;
2384
2385 /* The glyph row for which this string was built. It determines the
2386 y-origin and height of the string. */
2387 struct glyph_row *row;
2388
2389 /* The area within row. */
2390 enum glyph_row_area area;
2391
2392 /* Characters to be drawn, and number of characters. */
2393 XChar2b *char2b;
2394 int nchars;
2395
2396 /* A face-override for drawing cursors, mouse face and similar. */
2397 enum draw_glyphs_face hl;
2398
2399 /* Face in which this string is to be drawn. */
2400 struct face *face;
2401
2402 /* Font in which this string is to be drawn. */
2403 XFontStruct *font;
2404
2405 /* Font info for this string. */
2406 struct font_info *font_info;
2407
2408 /* Non-null means this string describes (part of) a composition.
2409 All characters from char2b are drawn composed. */
2410 struct composition *cmp;
2411
2412 /* Index of this glyph string's first character in the glyph
2413 definition of CMP. If this is zero, this glyph string describes
2414 the first character of a composition. */
2415 int gidx;
2416
2417 /* 1 means this glyph strings face has to be drawn to the right end
2418 of the window's drawing area. */
2419 unsigned extends_to_end_of_line_p : 1;
2420
2421 /* 1 means the background of this string has been drawn. */
2422 unsigned background_filled_p : 1;
2423
2424 /* 1 means glyph string must be drawn with 16-bit functions. */
2425 unsigned two_byte_p : 1;
2426
2427 /* 1 means that the original font determined for drawing this glyph
2428 string could not be loaded. The member `font' has been set to
2429 the frame's default font in this case. */
2430 unsigned font_not_found_p : 1;
2431
2432 /* 1 means that the face in which this glyph string is drawn has a
2433 stipple pattern. */
2434 unsigned stippled_p : 1;
2435
2436 /* 1 means only the foreground of this glyph string must be drawn,
2437 and we should use the physical height of the line this glyph
2438 string appears in as clip rect. */
2439 unsigned for_overlaps_p : 1;
2440
2441 /* The GC to use for drawing this glyph string. */
2442 GC gc;
2443
2444 /* A pointer to the first glyph in the string. This glyph
2445 corresponds to char2b[0]. Needed to draw rectangles if
2446 font_not_found_p is 1. */
2447 struct glyph *first_glyph;
2448
2449 /* Image, if any. */
2450 struct image *img;
2451
2452 struct glyph_string *next, *prev;
2453 };
2454
2455
2456 #if 0
2457
2458 static void
2459 x_dump_glyph_string (s)
2460 struct glyph_string *s;
2461 {
2462 fprintf (stderr, "glyph string\n");
2463 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2464 s->x, s->y, s->width, s->height);
2465 fprintf (stderr, " ybase = %d\n", s->ybase);
2466 fprintf (stderr, " hl = %d\n", s->hl);
2467 fprintf (stderr, " left overhang = %d, right = %d\n",
2468 s->left_overhang, s->right_overhang);
2469 fprintf (stderr, " nchars = %d\n", s->nchars);
2470 fprintf (stderr, " extends to end of line = %d\n",
2471 s->extends_to_end_of_line_p);
2472 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2473 fprintf (stderr, " bg width = %d\n", s->background_width);
2474 }
2475
2476 #endif /* GLYPH_DEBUG */
2477
2478
2479
2480 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2481 struct glyph_string **,
2482 struct glyph_string *,
2483 struct glyph_string *));
2484 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2485 struct glyph_string **,
2486 struct glyph_string *,
2487 struct glyph_string *));
2488 static void x_append_glyph_string P_ ((struct glyph_string **,
2489 struct glyph_string **,
2490 struct glyph_string *));
2491 static int x_left_overwritten P_ ((struct glyph_string *));
2492 static int x_left_overwriting P_ ((struct glyph_string *));
2493 static int x_right_overwritten P_ ((struct glyph_string *));
2494 static int x_right_overwriting P_ ((struct glyph_string *));
2495 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2496 int));
2497 static void x_init_glyph_string P_ ((struct glyph_string *,
2498 XChar2b *, struct window *,
2499 struct glyph_row *,
2500 enum glyph_row_area, int,
2501 enum draw_glyphs_face));
2502 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2503 enum glyph_row_area, int, int,
2504 enum draw_glyphs_face, int *, int *, int));
2505 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2506 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2507 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2508 int));
2509 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2510 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2511 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2512 static void x_draw_glyph_string P_ ((struct glyph_string *));
2513 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2514 static void x_set_cursor_gc P_ ((struct glyph_string *));
2515 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2516 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2517 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2518 int *, int *));
2519 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2520 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2521 unsigned long *, double, int));
2522 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2523 double, int, unsigned long));
2524 static void x_setup_relief_colors P_ ((struct glyph_string *));
2525 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2526 static void x_draw_image_relief P_ ((struct glyph_string *));
2527 static void x_draw_image_foreground P_ ((struct glyph_string *));
2528 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2529 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2530 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2531 int, int, int));
2532 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2533 int, int, int, int, XRectangle *));
2534 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2535 int, int, int, XRectangle *));
2536 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2537 enum glyph_row_area));
2538 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2539 struct glyph_row *,
2540 enum glyph_row_area, int, int));
2541
2542 #if GLYPH_DEBUG
2543 static void x_check_font P_ ((struct frame *, XFontStruct *));
2544 #endif
2545
2546
2547 /* Append the list of glyph strings with head H and tail T to the list
2548 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2549
2550 static INLINE void
2551 x_append_glyph_string_lists (head, tail, h, t)
2552 struct glyph_string **head, **tail;
2553 struct glyph_string *h, *t;
2554 {
2555 if (h)
2556 {
2557 if (*head)
2558 (*tail)->next = h;
2559 else
2560 *head = h;
2561 h->prev = *tail;
2562 *tail = t;
2563 }
2564 }
2565
2566
2567 /* Prepend the list of glyph strings with head H and tail T to the
2568 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2569 result. */
2570
2571 static INLINE void
2572 x_prepend_glyph_string_lists (head, tail, h, t)
2573 struct glyph_string **head, **tail;
2574 struct glyph_string *h, *t;
2575 {
2576 if (h)
2577 {
2578 if (*head)
2579 (*head)->prev = t;
2580 else
2581 *tail = t;
2582 t->next = *head;
2583 *head = h;
2584 }
2585 }
2586
2587
2588 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2589 Set *HEAD and *TAIL to the resulting list. */
2590
2591 static INLINE void
2592 x_append_glyph_string (head, tail, s)
2593 struct glyph_string **head, **tail;
2594 struct glyph_string *s;
2595 {
2596 s->next = s->prev = NULL;
2597 x_append_glyph_string_lists (head, tail, s, s);
2598 }
2599
2600
2601 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2602 face. */
2603
2604 static void
2605 x_set_cursor_gc (s)
2606 struct glyph_string *s;
2607 {
2608 if (s->font == FRAME_FONT (s->f)
2609 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2610 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2611 && !s->cmp)
2612 s->gc = s->f->output_data.x->cursor_gc;
2613 else
2614 {
2615 /* Cursor on non-default face: must merge. */
2616 XGCValues xgcv;
2617 unsigned long mask;
2618
2619 xgcv.background = s->f->output_data.x->cursor_pixel;
2620 xgcv.foreground = s->face->background;
2621
2622 /* If the glyph would be invisible, try a different foreground. */
2623 if (xgcv.foreground == xgcv.background)
2624 xgcv.foreground = s->face->foreground;
2625 if (xgcv.foreground == xgcv.background)
2626 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2627 if (xgcv.foreground == xgcv.background)
2628 xgcv.foreground = s->face->foreground;
2629
2630 /* Make sure the cursor is distinct from text in this face. */
2631 if (xgcv.background == s->face->background
2632 && xgcv.foreground == s->face->foreground)
2633 {
2634 xgcv.background = s->face->foreground;
2635 xgcv.foreground = s->face->background;
2636 }
2637
2638 IF_DEBUG (x_check_font (s->f, s->font));
2639 xgcv.font = s->font->fid;
2640 xgcv.graphics_exposures = False;
2641 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2642
2643 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2644 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2645 mask, &xgcv);
2646 else
2647 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2648 = XCreateGC (s->display, s->window, mask, &xgcv);
2649
2650 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2651 }
2652 }
2653
2654
2655 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2656
2657 static void
2658 x_set_mouse_face_gc (s)
2659 struct glyph_string *s;
2660 {
2661 int face_id;
2662 struct face *face;
2663
2664 /* What face has to be used for the mouse face? */
2665 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2666 face = FACE_FROM_ID (s->f, face_id);
2667 if (s->first_glyph->type == CHAR_GLYPH)
2668 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2669 else
2670 face_id = FACE_FOR_CHAR (s->f, face, 0);
2671 s->face = FACE_FROM_ID (s->f, face_id);
2672 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2673
2674 /* If font in this face is same as S->font, use it. */
2675 if (s->font == s->face->font)
2676 s->gc = s->face->gc;
2677 else
2678 {
2679 /* Otherwise construct scratch_cursor_gc with values from FACE
2680 but font FONT. */
2681 XGCValues xgcv;
2682 unsigned long mask;
2683
2684 xgcv.background = s->face->background;
2685 xgcv.foreground = s->face->foreground;
2686 IF_DEBUG (x_check_font (s->f, s->font));
2687 xgcv.font = s->font->fid;
2688 xgcv.graphics_exposures = False;
2689 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2690
2691 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2692 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2693 mask, &xgcv);
2694 else
2695 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2696 = XCreateGC (s->display, s->window, mask, &xgcv);
2697
2698 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2699 }
2700
2701 xassert (s->gc != 0);
2702 }
2703
2704
2705 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2706 Faces to use in the mode line have already been computed when the
2707 matrix was built, so there isn't much to do, here. */
2708
2709 static INLINE void
2710 x_set_mode_line_face_gc (s)
2711 struct glyph_string *s;
2712 {
2713 s->gc = s->face->gc;
2714 }
2715
2716
2717 /* Set S->gc of glyph string S for drawing that glyph string. Set
2718 S->stippled_p to a non-zero value if the face of S has a stipple
2719 pattern. */
2720
2721 static INLINE void
2722 x_set_glyph_string_gc (s)
2723 struct glyph_string *s;
2724 {
2725 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2726
2727 if (s->hl == DRAW_NORMAL_TEXT)
2728 {
2729 s->gc = s->face->gc;
2730 s->stippled_p = s->face->stipple != 0;
2731 }
2732 else if (s->hl == DRAW_INVERSE_VIDEO)
2733 {
2734 x_set_mode_line_face_gc (s);
2735 s->stippled_p = s->face->stipple != 0;
2736 }
2737 else if (s->hl == DRAW_CURSOR)
2738 {
2739 x_set_cursor_gc (s);
2740 s->stippled_p = 0;
2741 }
2742 else if (s->hl == DRAW_MOUSE_FACE)
2743 {
2744 x_set_mouse_face_gc (s);
2745 s->stippled_p = s->face->stipple != 0;
2746 }
2747 else if (s->hl == DRAW_IMAGE_RAISED
2748 || s->hl == DRAW_IMAGE_SUNKEN)
2749 {
2750 s->gc = s->face->gc;
2751 s->stippled_p = s->face->stipple != 0;
2752 }
2753 else
2754 {
2755 s->gc = s->face->gc;
2756 s->stippled_p = s->face->stipple != 0;
2757 }
2758
2759 /* GC must have been set. */
2760 xassert (s->gc != 0);
2761 }
2762
2763
2764 /* Return in *R the clipping rectangle for glyph string S. */
2765
2766 static void
2767 x_get_glyph_string_clip_rect (s, r)
2768 struct glyph_string *s;
2769 XRectangle *r;
2770 {
2771 if (s->row->full_width_p)
2772 {
2773 /* Draw full-width. X coordinates are relative to S->w->left. */
2774 int canon_x = CANON_X_UNIT (s->f);
2775
2776 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2777 r->width = XFASTINT (s->w->width) * canon_x;
2778
2779 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2780 {
2781 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2782 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2783 r->x -= width;
2784 }
2785
2786 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2787
2788 /* Unless displaying a mode or menu bar line, which are always
2789 fully visible, clip to the visible part of the row. */
2790 if (s->w->pseudo_window_p)
2791 r->height = s->row->visible_height;
2792 else
2793 r->height = s->height;
2794 }
2795 else
2796 {
2797 /* This is a text line that may be partially visible. */
2798 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2799 r->width = window_box_width (s->w, s->area);
2800 r->height = s->row->visible_height;
2801 }
2802
2803 /* Don't use S->y for clipping because it doesn't take partially
2804 visible lines into account. For example, it can be negative for
2805 partially visible lines at the top of a window. */
2806 if (!s->row->full_width_p
2807 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2808 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2809 else
2810 r->y = max (0, s->row->y);
2811
2812 /* If drawing a tool-bar window, draw it over the internal border
2813 at the top of the window. */
2814 if (s->w == XWINDOW (s->f->tool_bar_window))
2815 r->y -= s->f->output_data.x->internal_border_width;
2816
2817 /* If S draws overlapping rows, it's sufficient to use the top and
2818 bottom of the window for clipping because this glyph string
2819 intentionally draws over other lines. */
2820 if (s->for_overlaps_p)
2821 {
2822 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2823 r->height = window_text_bottom_y (s->w) - r->y;
2824 }
2825
2826 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2827 }
2828
2829
2830 /* Set clipping for output of glyph string S. S may be part of a mode
2831 line or menu if we don't have X toolkit support. */
2832
2833 static INLINE void
2834 x_set_glyph_string_clipping (s)
2835 struct glyph_string *s;
2836 {
2837 XRectangle r;
2838 x_get_glyph_string_clip_rect (s, &r);
2839 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2840 }
2841
2842
2843 /* Compute left and right overhang of glyph string S. If S is a glyph
2844 string for a composition, assume overhangs don't exist. */
2845
2846 static INLINE void
2847 x_compute_glyph_string_overhangs (s)
2848 struct glyph_string *s;
2849 {
2850 if (s->cmp == NULL
2851 && s->first_glyph->type == CHAR_GLYPH)
2852 {
2853 XCharStruct cs;
2854 int direction, font_ascent, font_descent;
2855 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2856 &font_ascent, &font_descent, &cs);
2857 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2858 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2859 }
2860 }
2861
2862
2863 /* Compute overhangs and x-positions for glyph string S and its
2864 predecessors, or successors. X is the starting x-position for S.
2865 BACKWARD_P non-zero means process predecessors. */
2866
2867 static void
2868 x_compute_overhangs_and_x (s, x, backward_p)
2869 struct glyph_string *s;
2870 int x;
2871 int backward_p;
2872 {
2873 if (backward_p)
2874 {
2875 while (s)
2876 {
2877 x_compute_glyph_string_overhangs (s);
2878 x -= s->width;
2879 s->x = x;
2880 s = s->prev;
2881 }
2882 }
2883 else
2884 {
2885 while (s)
2886 {
2887 x_compute_glyph_string_overhangs (s);
2888 s->x = x;
2889 x += s->width;
2890 s = s->next;
2891 }
2892 }
2893 }
2894
2895
2896 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2897 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2898 assumed to be zero. */
2899
2900 static void
2901 x_get_glyph_overhangs (glyph, f, left, right)
2902 struct glyph *glyph;
2903 struct frame *f;
2904 int *left, *right;
2905 {
2906 *left = *right = 0;
2907
2908 if (glyph->type == CHAR_GLYPH)
2909 {
2910 XFontStruct *font;
2911 struct face *face;
2912 struct font_info *font_info;
2913 XChar2b char2b;
2914 XCharStruct *pcm;
2915
2916 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2917 font = face->font;
2918 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2919 if (font
2920 && (pcm = x_per_char_metric (font, &char2b)))
2921 {
2922 if (pcm->rbearing > pcm->width)
2923 *right = pcm->rbearing - pcm->width;
2924 if (pcm->lbearing < 0)
2925 *left = -pcm->lbearing;
2926 }
2927 }
2928 }
2929
2930
2931 /* Return the index of the first glyph preceding glyph string S that
2932 is overwritten by S because of S's left overhang. Value is -1
2933 if no glyphs are overwritten. */
2934
2935 static int
2936 x_left_overwritten (s)
2937 struct glyph_string *s;
2938 {
2939 int k;
2940
2941 if (s->left_overhang)
2942 {
2943 int x = 0, i;
2944 struct glyph *glyphs = s->row->glyphs[s->area];
2945 int first = s->first_glyph - glyphs;
2946
2947 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2948 x -= glyphs[i].pixel_width;
2949
2950 k = i + 1;
2951 }
2952 else
2953 k = -1;
2954
2955 return k;
2956 }
2957
2958
2959 /* Return the index of the first glyph preceding glyph string S that
2960 is overwriting S because of its right overhang. Value is -1 if no
2961 glyph in front of S overwrites S. */
2962
2963 static int
2964 x_left_overwriting (s)
2965 struct glyph_string *s;
2966 {
2967 int i, k, x;
2968 struct glyph *glyphs = s->row->glyphs[s->area];
2969 int first = s->first_glyph - glyphs;
2970
2971 k = -1;
2972 x = 0;
2973 for (i = first - 1; i >= 0; --i)
2974 {
2975 int left, right;
2976 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2977 if (x + right > 0)
2978 k = i;
2979 x -= glyphs[i].pixel_width;
2980 }
2981
2982 return k;
2983 }
2984
2985
2986 /* Return the index of the last glyph following glyph string S that is
2987 not overwritten by S because of S's right overhang. Value is -1 if
2988 no such glyph is found. */
2989
2990 static int
2991 x_right_overwritten (s)
2992 struct glyph_string *s;
2993 {
2994 int k = -1;
2995
2996 if (s->right_overhang)
2997 {
2998 int x = 0, i;
2999 struct glyph *glyphs = s->row->glyphs[s->area];
3000 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3001 int end = s->row->used[s->area];
3002
3003 for (i = first; i < end && s->right_overhang > x; ++i)
3004 x += glyphs[i].pixel_width;
3005
3006 k = i;
3007 }
3008
3009 return k;
3010 }
3011
3012
3013 /* Return the index of the last glyph following glyph string S that
3014 overwrites S because of its left overhang. Value is negative
3015 if no such glyph is found. */
3016
3017 static int
3018 x_right_overwriting (s)
3019 struct glyph_string *s;
3020 {
3021 int i, k, x;
3022 int end = s->row->used[s->area];
3023 struct glyph *glyphs = s->row->glyphs[s->area];
3024 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3025
3026 k = -1;
3027 x = 0;
3028 for (i = first; i < end; ++i)
3029 {
3030 int left, right;
3031 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3032 if (x - left < 0)
3033 k = i;
3034 x += glyphs[i].pixel_width;
3035 }
3036
3037 return k;
3038 }
3039
3040
3041 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3042
3043 static INLINE void
3044 x_clear_glyph_string_rect (s, x, y, w, h)
3045 struct glyph_string *s;
3046 int x, y, w, h;
3047 {
3048 XGCValues xgcv;
3049 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3050 XSetForeground (s->display, s->gc, xgcv.background);
3051 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3052 XSetForeground (s->display, s->gc, xgcv.foreground);
3053 }
3054
3055
3056 /* Draw the background of glyph_string S. If S->background_filled_p
3057 is non-zero don't draw it. FORCE_P non-zero means draw the
3058 background even if it wouldn't be drawn normally. This is used
3059 when a string preceding S draws into the background of S, or S
3060 contains the first component of a composition. */
3061
3062 static void
3063 x_draw_glyph_string_background (s, force_p)
3064 struct glyph_string *s;
3065 int force_p;
3066 {
3067 /* Nothing to do if background has already been drawn or if it
3068 shouldn't be drawn in the first place. */
3069 if (!s->background_filled_p)
3070 {
3071 if (s->stippled_p)
3072 {
3073 /* Fill background with a stipple pattern. */
3074 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3075 XFillRectangle (s->display, s->window, s->gc, s->x,
3076 s->y + s->face->box_line_width,
3077 s->background_width,
3078 s->height - 2 * s->face->box_line_width);
3079 XSetFillStyle (s->display, s->gc, FillSolid);
3080 s->background_filled_p = 1;
3081 }
3082 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3083 || s->font_not_found_p
3084 || s->extends_to_end_of_line_p
3085 || force_p)
3086 {
3087 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3088 s->background_width,
3089 s->height - 2 * s->face->box_line_width);
3090 s->background_filled_p = 1;
3091 }
3092 }
3093 }
3094
3095
3096 /* Draw the foreground of glyph string S. */
3097
3098 static void
3099 x_draw_glyph_string_foreground (s)
3100 struct glyph_string *s;
3101 {
3102 int i, x;
3103
3104 /* If first glyph of S has a left box line, start drawing the text
3105 of S to the right of that box line. */
3106 if (s->face->box != FACE_NO_BOX
3107 && s->first_glyph->left_box_line_p)
3108 x = s->x + s->face->box_line_width;
3109 else
3110 x = s->x;
3111
3112 /* Draw characters of S as rectangles if S's font could not be
3113 loaded. */
3114 if (s->font_not_found_p)
3115 {
3116 for (i = 0; i < s->nchars; ++i)
3117 {
3118 struct glyph *g = s->first_glyph + i;
3119 XDrawRectangle (s->display, s->window,
3120 s->gc, x, s->y, g->pixel_width - 1,
3121 s->height - 1);
3122 x += g->pixel_width;
3123 }
3124 }
3125 else
3126 {
3127 char *char1b = (char *) s->char2b;
3128 int boff = s->font_info->baseline_offset;
3129
3130 if (s->font_info->vertical_centering)
3131 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3132
3133 /* If we can use 8-bit functions, condense S->char2b. */
3134 if (!s->two_byte_p)
3135 for (i = 0; i < s->nchars; ++i)
3136 char1b[i] = s->char2b[i].byte2;
3137
3138 /* Draw text with XDrawString if background has already been
3139 filled. Otherwise, use XDrawImageString. (Note that
3140 XDrawImageString is usually faster than XDrawString.) Always
3141 use XDrawImageString when drawing the cursor so that there is
3142 no chance that characters under a box cursor are invisible. */
3143 if (s->for_overlaps_p
3144 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3145 {
3146 /* Draw characters with 16-bit or 8-bit functions. */
3147 if (s->two_byte_p)
3148 XDrawString16 (s->display, s->window, s->gc, x,
3149 s->ybase - boff, s->char2b, s->nchars);
3150 else
3151 XDrawString (s->display, s->window, s->gc, x,
3152 s->ybase - boff, char1b, s->nchars);
3153 }
3154 else
3155 {
3156 if (s->two_byte_p)
3157 XDrawImageString16 (s->display, s->window, s->gc, x,
3158 s->ybase - boff, s->char2b, s->nchars);
3159 else
3160 XDrawImageString (s->display, s->window, s->gc, x,
3161 s->ybase - boff, char1b, s->nchars);
3162 }
3163 }
3164 }
3165
3166 /* Draw the foreground of composite glyph string S. */
3167
3168 static void
3169 x_draw_composite_glyph_string_foreground (s)
3170 struct glyph_string *s;
3171 {
3172 int i, x;
3173
3174 /* If first glyph of S has a left box line, start drawing the text
3175 of S to the right of that box line. */
3176 if (s->face->box != FACE_NO_BOX
3177 && s->first_glyph->left_box_line_p)
3178 x = s->x + s->face->box_line_width;
3179 else
3180 x = s->x;
3181
3182 /* S is a glyph string for a composition. S->gidx is the index of
3183 the first character drawn for glyphs of this composition.
3184 S->gidx == 0 means we are drawing the very first character of
3185 this composition. */
3186
3187 /* Draw a rectangle for the composition if the font for the very
3188 first character of the composition could not be loaded. */
3189 if (s->font_not_found_p)
3190 {
3191 if (s->gidx == 0)
3192 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3193 s->width - 1, s->height - 1);
3194 }
3195 else
3196 {
3197 for (i = 0; i < s->nchars; i++, ++s->gidx)
3198 XDrawString16 (s->display, s->window, s->gc,
3199 x + s->cmp->offsets[s->gidx * 2],
3200 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3201 s->char2b + i, 1);
3202 }
3203 }
3204
3205
3206 #ifdef USE_X_TOOLKIT
3207
3208 static struct frame *x_frame_of_widget P_ ((Widget));
3209
3210
3211 /* Return the frame on which widget WIDGET is used.. Abort if frame
3212 cannot be determined. */
3213
3214 static struct frame *
3215 x_frame_of_widget (widget)
3216 Widget widget;
3217 {
3218 struct x_display_info *dpyinfo;
3219 Lisp_Object tail;
3220 struct frame *f;
3221
3222 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3223
3224 /* Find the top-level shell of the widget. Note that this function
3225 can be called when the widget is not yet realized, so XtWindow
3226 (widget) == 0. That's the reason we can't simply use
3227 x_any_window_to_frame. */
3228 while (!XtIsTopLevelShell (widget))
3229 widget = XtParent (widget);
3230
3231 /* Look for a frame with that top-level widget. Allocate the color
3232 on that frame to get the right gamma correction value. */
3233 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3234 if (GC_FRAMEP (XCAR (tail))
3235 && (f = XFRAME (XCAR (tail)),
3236 (f->output_data.nothing != 1
3237 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3238 && f->output_data.x->widget == widget)
3239 return f;
3240
3241 abort ();
3242 }
3243
3244
3245 /* Allocate the color COLOR->pixel on the screen and display of
3246 widget WIDGET in colormap CMAP. If an exact match cannot be
3247 allocated, try the nearest color available. Value is non-zero
3248 if successful. This is called from lwlib. */
3249
3250 int
3251 x_alloc_nearest_color_for_widget (widget, cmap, color)
3252 Widget widget;
3253 Colormap cmap;
3254 XColor *color;
3255 {
3256 struct frame *f = x_frame_of_widget (widget);
3257 return x_alloc_nearest_color (f, cmap, color);
3258 }
3259
3260
3261 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3262 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3263 If this produces the same color as PIXEL, try a color where all RGB
3264 values have DELTA added. Return the allocated color in *PIXEL.
3265 DISPLAY is the X display, CMAP is the colormap to operate on.
3266 Value is non-zero if successful. */
3267
3268 int
3269 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3270 Widget widget;
3271 Display *display;
3272 Colormap cmap;
3273 unsigned long *pixel;
3274 double factor;
3275 int delta;
3276 {
3277 struct frame *f = x_frame_of_widget (widget);
3278 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3279 }
3280
3281
3282 #endif /* USE_X_TOOLKIT */
3283
3284
3285 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3286 CMAP. If an exact match can't be allocated, try the nearest color
3287 available. Value is non-zero if successful. Set *COLOR to the
3288 color allocated. */
3289
3290 int
3291 x_alloc_nearest_color (f, cmap, color)
3292 struct frame *f;
3293 Colormap cmap;
3294 XColor *color;
3295 {
3296 Display *display = FRAME_X_DISPLAY (f);
3297 Screen *screen = FRAME_X_SCREEN (f);
3298 int rc;
3299
3300 gamma_correct (f, color);
3301 rc = XAllocColor (display, cmap, color);
3302 if (rc == 0)
3303 {
3304 /* If we got to this point, the colormap is full, so we're going
3305 to try to get the next closest color. The algorithm used is
3306 a least-squares matching, which is what X uses for closest
3307 color matching with StaticColor visuals. */
3308 int nearest, i;
3309 unsigned long nearest_delta = ~0;
3310 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3311 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3312
3313 for (i = 0; i < ncells; ++i)
3314 cells[i].pixel = i;
3315 XQueryColors (display, cmap, cells, ncells);
3316
3317 for (nearest = i = 0; i < ncells; ++i)
3318 {
3319 long dred = (color->red >> 8) - (cells[i].red >> 8);
3320 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3321 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3322 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3323
3324 if (delta < nearest_delta)
3325 {
3326 nearest = i;
3327 nearest_delta = delta;
3328 }
3329 }
3330
3331 color->red = cells[nearest].red;
3332 color->green = cells[nearest].green;
3333 color->blue = cells[nearest].blue;
3334 rc = XAllocColor (display, cmap, color);
3335 }
3336
3337 #ifdef DEBUG_X_COLORS
3338 if (rc)
3339 register_color (color->pixel);
3340 #endif /* DEBUG_X_COLORS */
3341
3342 return rc;
3343 }
3344
3345
3346 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3347 It's necessary to do this instead of just using PIXEL directly to
3348 get color reference counts right. */
3349
3350 unsigned long
3351 x_copy_color (f, pixel)
3352 struct frame *f;
3353 unsigned long pixel;
3354 {
3355 XColor color;
3356
3357 color.pixel = pixel;
3358 BLOCK_INPUT;
3359 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3360 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3361 UNBLOCK_INPUT;
3362 #ifdef DEBUG_X_COLORS
3363 register_color (pixel);
3364 #endif
3365 return color.pixel;
3366 }
3367
3368
3369 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3370 It's necessary to do this instead of just using PIXEL directly to
3371 get color reference counts right. */
3372
3373 unsigned long
3374 x_copy_dpy_color (dpy, cmap, pixel)
3375 Display *dpy;
3376 Colormap cmap;
3377 unsigned long pixel;
3378 {
3379 XColor color;
3380
3381 color.pixel = pixel;
3382 BLOCK_INPUT;
3383 XQueryColor (dpy, cmap, &color);
3384 XAllocColor (dpy, cmap, &color);
3385 UNBLOCK_INPUT;
3386 #ifdef DEBUG_X_COLORS
3387 register_color (pixel);
3388 #endif
3389 return color.pixel;
3390 }
3391
3392
3393 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3394 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3395 If this produces the same color as PIXEL, try a color where all RGB
3396 values have DELTA added. Return the allocated color in *PIXEL.
3397 DISPLAY is the X display, CMAP is the colormap to operate on.
3398 Value is non-zero if successful. */
3399
3400 static int
3401 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3402 struct frame *f;
3403 Display *display;
3404 Colormap cmap;
3405 unsigned long *pixel;
3406 double factor;
3407 int delta;
3408 {
3409 XColor color, new;
3410 int success_p;
3411
3412 /* Get RGB color values. */
3413 color.pixel = *pixel;
3414 XQueryColor (display, cmap, &color);
3415
3416 /* Change RGB values by specified FACTOR. Avoid overflow! */
3417 xassert (factor >= 0);
3418 new.red = min (0xffff, factor * color.red);
3419 new.green = min (0xffff, factor * color.green);
3420 new.blue = min (0xffff, factor * color.blue);
3421
3422 /* Try to allocate the color. */
3423 success_p = x_alloc_nearest_color (f, cmap, &new);
3424 if (success_p)
3425 {
3426 if (new.pixel == *pixel)
3427 {
3428 /* If we end up with the same color as before, try adding
3429 delta to the RGB values. */
3430 x_free_colors (f, &new.pixel, 1);
3431
3432 new.red = min (0xffff, delta + color.red);
3433 new.green = min (0xffff, delta + color.green);
3434 new.blue = min (0xffff, delta + color.blue);
3435 success_p = x_alloc_nearest_color (f, cmap, &new);
3436 }
3437 else
3438 success_p = 1;
3439 *pixel = new.pixel;
3440 }
3441
3442 return success_p;
3443 }
3444
3445
3446 /* Set up the foreground color for drawing relief lines of glyph
3447 string S. RELIEF is a pointer to a struct relief containing the GC
3448 with which lines will be drawn. Use a color that is FACTOR or
3449 DELTA lighter or darker than the relief's background which is found
3450 in S->f->output_data.x->relief_background. If such a color cannot
3451 be allocated, use DEFAULT_PIXEL, instead. */
3452
3453 static void
3454 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3455 struct frame *f;
3456 struct relief *relief;
3457 double factor;
3458 int delta;
3459 unsigned long default_pixel;
3460 {
3461 XGCValues xgcv;
3462 struct x_output *di = f->output_data.x;
3463 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3464 unsigned long pixel;
3465 unsigned long background = di->relief_background;
3466 Colormap cmap = FRAME_X_COLORMAP (f);
3467 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3468 Display *dpy = FRAME_X_DISPLAY (f);
3469
3470 xgcv.graphics_exposures = False;
3471 xgcv.line_width = 1;
3472
3473 /* Free previously allocated color. The color cell will be reused
3474 when it has been freed as many times as it was allocated, so this
3475 doesn't affect faces using the same colors. */
3476 if (relief->gc
3477 && relief->allocated_p)
3478 {
3479 x_free_colors (f, &relief->pixel, 1);
3480 relief->allocated_p = 0;
3481 }
3482
3483 /* Allocate new color. */
3484 xgcv.foreground = default_pixel;
3485 pixel = background;
3486 if (dpyinfo->n_planes != 1
3487 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3488 {
3489 relief->allocated_p = 1;
3490 xgcv.foreground = relief->pixel = pixel;
3491 }
3492
3493 if (relief->gc == 0)
3494 {
3495 xgcv.stipple = dpyinfo->gray;
3496 mask |= GCStipple;
3497 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3498 }
3499 else
3500 XChangeGC (dpy, relief->gc, mask, &xgcv);
3501 }
3502
3503
3504 /* Set up colors for the relief lines around glyph string S. */
3505
3506 static void
3507 x_setup_relief_colors (s)
3508 struct glyph_string *s;
3509 {
3510 struct x_output *di = s->f->output_data.x;
3511 unsigned long color;
3512
3513 if (s->face->use_box_color_for_shadows_p)
3514 color = s->face->box_color;
3515 else
3516 {
3517 XGCValues xgcv;
3518
3519 /* Get the background color of the face. */
3520 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3521 color = xgcv.background;
3522 }
3523
3524 if (di->white_relief.gc == 0
3525 || color != di->relief_background)
3526 {
3527 di->relief_background = color;
3528 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3529 WHITE_PIX_DEFAULT (s->f));
3530 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3531 BLACK_PIX_DEFAULT (s->f));
3532 }
3533 }
3534
3535
3536 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3537 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3538 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3539 relief. LEFT_P non-zero means draw a relief on the left side of
3540 the rectangle. RIGHT_P non-zero means draw a relief on the right
3541 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3542 when drawing. */
3543
3544 static void
3545 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3546 raised_p, left_p, right_p, clip_rect)
3547 struct frame *f;
3548 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3549 XRectangle *clip_rect;
3550 {
3551 int i;
3552 GC gc;
3553
3554 if (raised_p)
3555 gc = f->output_data.x->white_relief.gc;
3556 else
3557 gc = f->output_data.x->black_relief.gc;
3558 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3559
3560 /* Top. */
3561 for (i = 0; i < width; ++i)
3562 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3563 left_x + i * left_p, top_y + i,
3564 right_x + 1 - i * right_p, top_y + i);
3565
3566 /* Left. */
3567 if (left_p)
3568 for (i = 0; i < width; ++i)
3569 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3570 left_x + i, top_y + i, left_x + i, bottom_y - i);
3571
3572 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3573 if (raised_p)
3574 gc = f->output_data.x->black_relief.gc;
3575 else
3576 gc = f->output_data.x->white_relief.gc;
3577 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3578
3579 /* Bottom. */
3580 for (i = 0; i < width; ++i)
3581 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3582 left_x + i * left_p, bottom_y - i,
3583 right_x + 1 - i * right_p, bottom_y - i);
3584
3585 /* Right. */
3586 if (right_p)
3587 for (i = 0; i < width; ++i)
3588 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3589 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3590
3591 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3592 }
3593
3594
3595 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3596 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3597 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3598 left side of the rectangle. RIGHT_P non-zero means draw a line
3599 on the right side of the rectangle. CLIP_RECT is the clipping
3600 rectangle to use when drawing. */
3601
3602 static void
3603 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3604 left_p, right_p, clip_rect)
3605 struct glyph_string *s;
3606 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3607 XRectangle *clip_rect;
3608 {
3609 XGCValues xgcv;
3610
3611 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3612 XSetForeground (s->display, s->gc, s->face->box_color);
3613 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3614
3615 /* Top. */
3616 XFillRectangle (s->display, s->window, s->gc,
3617 left_x, top_y, right_x - left_x, width);
3618
3619 /* Left. */
3620 if (left_p)
3621 XFillRectangle (s->display, s->window, s->gc,
3622 left_x, top_y, width, bottom_y - top_y);
3623
3624 /* Bottom. */
3625 XFillRectangle (s->display, s->window, s->gc,
3626 left_x, bottom_y - width, right_x - left_x, width);
3627
3628 /* Right. */
3629 if (right_p)
3630 XFillRectangle (s->display, s->window, s->gc,
3631 right_x - width, top_y, width, bottom_y - top_y);
3632
3633 XSetForeground (s->display, s->gc, xgcv.foreground);
3634 XSetClipMask (s->display, s->gc, None);
3635 }
3636
3637
3638 /* Draw a box around glyph string S. */
3639
3640 static void
3641 x_draw_glyph_string_box (s)
3642 struct glyph_string *s;
3643 {
3644 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3645 int left_p, right_p;
3646 struct glyph *last_glyph;
3647 XRectangle clip_rect;
3648
3649 last_x = window_box_right (s->w, s->area);
3650 if (s->row->full_width_p
3651 && !s->w->pseudo_window_p)
3652 {
3653 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3654 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3655 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3656 }
3657
3658 /* The glyph that may have a right box line. */
3659 last_glyph = (s->cmp || s->img
3660 ? s->first_glyph
3661 : s->first_glyph + s->nchars - 1);
3662
3663 width = s->face->box_line_width;
3664 raised_p = s->face->box == FACE_RAISED_BOX;
3665 left_x = s->x;
3666 right_x = ((s->row->full_width_p
3667 ? last_x - 1
3668 : min (last_x, s->x + s->background_width) - 1));
3669 top_y = s->y;
3670 bottom_y = top_y + s->height - 1;
3671
3672 left_p = (s->first_glyph->left_box_line_p
3673 || (s->hl == DRAW_MOUSE_FACE
3674 && (s->prev == NULL
3675 || s->prev->hl != s->hl)));
3676 right_p = (last_glyph->right_box_line_p
3677 || (s->hl == DRAW_MOUSE_FACE
3678 && (s->next == NULL
3679 || s->next->hl != s->hl)));
3680
3681 x_get_glyph_string_clip_rect (s, &clip_rect);
3682
3683 if (s->face->box == FACE_SIMPLE_BOX)
3684 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3685 left_p, right_p, &clip_rect);
3686 else
3687 {
3688 x_setup_relief_colors (s);
3689 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3690 width, raised_p, left_p, right_p, &clip_rect);
3691 }
3692 }
3693
3694
3695 /* Draw foreground of image glyph string S. */
3696
3697 static void
3698 x_draw_image_foreground (s)
3699 struct glyph_string *s;
3700 {
3701 int x;
3702 int y = s->ybase - image_ascent (s->img, s->face);
3703
3704 /* If first glyph of S has a left box line, start drawing it to the
3705 right of that line. */
3706 if (s->face->box != FACE_NO_BOX
3707 && s->first_glyph->left_box_line_p)
3708 x = s->x + s->face->box_line_width;
3709 else
3710 x = s->x;
3711
3712 /* If there is a margin around the image, adjust x- and y-position
3713 by that margin. */
3714 if (s->img->margin)
3715 {
3716 x += s->img->margin;
3717 y += s->img->margin;
3718 }
3719
3720 if (s->img->pixmap)
3721 {
3722 if (s->img->mask)
3723 {
3724 /* We can't set both a clip mask and use XSetClipRectangles
3725 because the latter also sets a clip mask. We also can't
3726 trust on the shape extension to be available
3727 (XShapeCombineRegion). So, compute the rectangle to draw
3728 manually. */
3729 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3730 | GCFunction);
3731 XGCValues xgcv;
3732 XRectangle clip_rect, image_rect, r;
3733
3734 xgcv.clip_mask = s->img->mask;
3735 xgcv.clip_x_origin = x;
3736 xgcv.clip_y_origin = y;
3737 xgcv.function = GXcopy;
3738 XChangeGC (s->display, s->gc, mask, &xgcv);
3739
3740 x_get_glyph_string_clip_rect (s, &clip_rect);
3741 image_rect.x = x;
3742 image_rect.y = y;
3743 image_rect.width = s->img->width;
3744 image_rect.height = s->img->height;
3745 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3746 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3747 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3748 }
3749 else
3750 {
3751 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3752 XGCValues xgcv;
3753 XRectangle clip_rect, image_rect, r;
3754
3755 x_get_glyph_string_clip_rect (s, &clip_rect);
3756 image_rect.x = x;
3757 image_rect.y = y;
3758 image_rect.width = s->img->width;
3759 image_rect.height = s->img->height;
3760 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3761 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3762 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3763
3764 /* When the image has a mask, we can expect that at
3765 least part of a mouse highlight or a block cursor will
3766 be visible. If the image doesn't have a mask, make
3767 a block cursor visible by drawing a rectangle around
3768 the image. I believe it's looking better if we do
3769 nothing here for mouse-face. */
3770 if (s->hl == DRAW_CURSOR)
3771 XDrawRectangle (s->display, s->window, s->gc, x, y,
3772 s->img->width - 1, s->img->height - 1);
3773 }
3774 }
3775 else
3776 /* Draw a rectangle if image could not be loaded. */
3777 XDrawRectangle (s->display, s->window, s->gc, x, y,
3778 s->img->width - 1, s->img->height - 1);
3779 }
3780
3781
3782 /* Draw a relief around the image glyph string S. */
3783
3784 static void
3785 x_draw_image_relief (s)
3786 struct glyph_string *s;
3787 {
3788 int x0, y0, x1, y1, thick, raised_p;
3789 XRectangle r;
3790 int x;
3791 int y = s->ybase - image_ascent (s->img, s->face);
3792
3793 /* If first glyph of S has a left box line, start drawing it to the
3794 right of that line. */
3795 if (s->face->box != FACE_NO_BOX
3796 && s->first_glyph->left_box_line_p)
3797 x = s->x + s->face->box_line_width;
3798 else
3799 x = s->x;
3800
3801 /* If there is a margin around the image, adjust x- and y-position
3802 by that margin. */
3803 if (s->img->margin)
3804 {
3805 x += s->img->margin;
3806 y += s->img->margin;
3807 }
3808
3809 if (s->hl == DRAW_IMAGE_SUNKEN
3810 || s->hl == DRAW_IMAGE_RAISED)
3811 {
3812 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3813 raised_p = s->hl == DRAW_IMAGE_RAISED;
3814 }
3815 else
3816 {
3817 thick = abs (s->img->relief);
3818 raised_p = s->img->relief > 0;
3819 }
3820
3821 x0 = x - thick;
3822 y0 = y - thick;
3823 x1 = x + s->img->width + thick - 1;
3824 y1 = y + s->img->height + thick - 1;
3825
3826 x_setup_relief_colors (s);
3827 x_get_glyph_string_clip_rect (s, &r);
3828 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3829 }
3830
3831
3832 /* Draw the foreground of image glyph string S to PIXMAP. */
3833
3834 static void
3835 x_draw_image_foreground_1 (s, pixmap)
3836 struct glyph_string *s;
3837 Pixmap pixmap;
3838 {
3839 int x;
3840 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3841
3842 /* If first glyph of S has a left box line, start drawing it to the
3843 right of that line. */
3844 if (s->face->box != FACE_NO_BOX
3845 && s->first_glyph->left_box_line_p)
3846 x = s->face->box_line_width;
3847 else
3848 x = 0;
3849
3850 /* If there is a margin around the image, adjust x- and y-position
3851 by that margin. */
3852 if (s->img->margin)
3853 {
3854 x += s->img->margin;
3855 y += s->img->margin;
3856 }
3857
3858 if (s->img->pixmap)
3859 {
3860 if (s->img->mask)
3861 {
3862 /* We can't set both a clip mask and use XSetClipRectangles
3863 because the latter also sets a clip mask. We also can't
3864 trust on the shape extension to be available
3865 (XShapeCombineRegion). So, compute the rectangle to draw
3866 manually. */
3867 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3868 | GCFunction);
3869 XGCValues xgcv;
3870
3871 xgcv.clip_mask = s->img->mask;
3872 xgcv.clip_x_origin = x;
3873 xgcv.clip_y_origin = y;
3874 xgcv.function = GXcopy;
3875 XChangeGC (s->display, s->gc, mask, &xgcv);
3876
3877 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3878 0, 0, s->img->width, s->img->height, x, y);
3879 XSetClipMask (s->display, s->gc, None);
3880 }
3881 else
3882 {
3883 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3884 0, 0, s->img->width, s->img->height, x, y);
3885
3886 /* When the image has a mask, we can expect that at
3887 least part of a mouse highlight or a block cursor will
3888 be visible. If the image doesn't have a mask, make
3889 a block cursor visible by drawing a rectangle around
3890 the image. I believe it's looking better if we do
3891 nothing here for mouse-face. */
3892 if (s->hl == DRAW_CURSOR)
3893 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3894 s->img->width - 1, s->img->height - 1);
3895 }
3896 }
3897 else
3898 /* Draw a rectangle if image could not be loaded. */
3899 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3900 s->img->width - 1, s->img->height - 1);
3901 }
3902
3903
3904 /* Draw part of the background of glyph string S. X, Y, W, and H
3905 give the rectangle to draw. */
3906
3907 static void
3908 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3909 struct glyph_string *s;
3910 int x, y, w, h;
3911 {
3912 if (s->stippled_p)
3913 {
3914 /* Fill background with a stipple pattern. */
3915 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3916 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3917 XSetFillStyle (s->display, s->gc, FillSolid);
3918 }
3919 else
3920 x_clear_glyph_string_rect (s, x, y, w, h);
3921 }
3922
3923
3924 /* Draw image glyph string S.
3925
3926 s->y
3927 s->x +-------------------------
3928 | s->face->box
3929 |
3930 | +-------------------------
3931 | | s->img->margin
3932 | |
3933 | | +-------------------
3934 | | | the image
3935
3936 */
3937
3938 static void
3939 x_draw_image_glyph_string (s)
3940 struct glyph_string *s;
3941 {
3942 int x, y;
3943 int box_line_width = s->face->box_line_width;
3944 int margin = s->img->margin;
3945 int height;
3946 Pixmap pixmap = None;
3947
3948 height = s->height - 2 * box_line_width;
3949
3950 /* Fill background with face under the image. Do it only if row is
3951 taller than image or if image has a clip mask to reduce
3952 flickering. */
3953 s->stippled_p = s->face->stipple != 0;
3954 if (height > s->img->height
3955 || margin
3956 || s->img->mask
3957 || s->img->pixmap == 0
3958 || s->width != s->background_width)
3959 {
3960 if (box_line_width && s->first_glyph->left_box_line_p)
3961 x = s->x + box_line_width;
3962 else
3963 x = s->x;
3964
3965 y = s->y + box_line_width;
3966
3967 if (s->img->mask)
3968 {
3969 /* Create a pixmap as large as the glyph string Fill it with
3970 the background color. Copy the image to it, using its
3971 mask. Copy the temporary pixmap to the display. */
3972 Screen *screen = FRAME_X_SCREEN (s->f);
3973 int depth = DefaultDepthOfScreen (screen);
3974
3975 /* Create a pixmap as large as the glyph string. */
3976 pixmap = XCreatePixmap (s->display, s->window,
3977 s->background_width,
3978 s->height, depth);
3979
3980 /* Don't clip in the following because we're working on the
3981 pixmap. */
3982 XSetClipMask (s->display, s->gc, None);
3983
3984 /* Fill the pixmap with the background color/stipple. */
3985 if (s->stippled_p)
3986 {
3987 /* Fill background with a stipple pattern. */
3988 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3989 XFillRectangle (s->display, pixmap, s->gc,
3990 0, 0, s->background_width, s->height);
3991 XSetFillStyle (s->display, s->gc, FillSolid);
3992 }
3993 else
3994 {
3995 XGCValues xgcv;
3996 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3997 &xgcv);
3998 XSetForeground (s->display, s->gc, xgcv.background);
3999 XFillRectangle (s->display, pixmap, s->gc,
4000 0, 0, s->background_width, s->height);
4001 XSetForeground (s->display, s->gc, xgcv.foreground);
4002 }
4003 }
4004 else
4005 /* Implementation idea: Is it possible to construct a mask?
4006 We could look at the color at the margins of the image, and
4007 say that this color is probably the background color of the
4008 image. */
4009 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4010
4011 s->background_filled_p = 1;
4012 }
4013
4014 /* Draw the foreground. */
4015 if (pixmap != None)
4016 {
4017 x_draw_image_foreground_1 (s, pixmap);
4018 x_set_glyph_string_clipping (s);
4019 XCopyArea (s->display, pixmap, s->window, s->gc,
4020 0, 0, s->background_width, s->height, s->x, s->y);
4021 XFreePixmap (s->display, pixmap);
4022 }
4023 else
4024 x_draw_image_foreground (s);
4025
4026 /* If we must draw a relief around the image, do it. */
4027 if (s->img->relief
4028 || s->hl == DRAW_IMAGE_RAISED
4029 || s->hl == DRAW_IMAGE_SUNKEN)
4030 x_draw_image_relief (s);
4031 }
4032
4033
4034 /* Draw stretch glyph string S. */
4035
4036 static void
4037 x_draw_stretch_glyph_string (s)
4038 struct glyph_string *s;
4039 {
4040 xassert (s->first_glyph->type == STRETCH_GLYPH);
4041 s->stippled_p = s->face->stipple != 0;
4042
4043 if (s->hl == DRAW_CURSOR
4044 && !x_stretch_cursor_p)
4045 {
4046 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4047 as wide as the stretch glyph. */
4048 int width = min (CANON_X_UNIT (s->f), s->background_width);
4049
4050 /* Draw cursor. */
4051 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4052
4053 /* Clear rest using the GC of the original non-cursor face. */
4054 if (width < s->background_width)
4055 {
4056 GC gc = s->face->gc;
4057 int x = s->x + width, y = s->y;
4058 int w = s->background_width - width, h = s->height;
4059 XRectangle r;
4060
4061 x_get_glyph_string_clip_rect (s, &r);
4062 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4063
4064 if (s->face->stipple)
4065 {
4066 /* Fill background with a stipple pattern. */
4067 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4068 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4069 XSetFillStyle (s->display, gc, FillSolid);
4070 }
4071 else
4072 {
4073 XGCValues xgcv;
4074 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4075 XSetForeground (s->display, gc, xgcv.background);
4076 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4077 XSetForeground (s->display, gc, xgcv.foreground);
4078 }
4079 }
4080 }
4081 else
4082 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4083 s->height);
4084
4085 s->background_filled_p = 1;
4086 }
4087
4088
4089 /* Draw glyph string S. */
4090
4091 static void
4092 x_draw_glyph_string (s)
4093 struct glyph_string *s;
4094 {
4095 /* If S draws into the background of its successor, draw the
4096 background of the successor first so that S can draw into it.
4097 This makes S->next use XDrawString instead of XDrawImageString. */
4098 if (s->next && s->right_overhang && !s->for_overlaps_p)
4099 {
4100 xassert (s->next->img == NULL);
4101 x_set_glyph_string_gc (s->next);
4102 x_set_glyph_string_clipping (s->next);
4103 x_draw_glyph_string_background (s->next, 1);
4104 }
4105
4106 /* Set up S->gc, set clipping and draw S. */
4107 x_set_glyph_string_gc (s);
4108 x_set_glyph_string_clipping (s);
4109
4110 switch (s->first_glyph->type)
4111 {
4112 case IMAGE_GLYPH:
4113 x_draw_image_glyph_string (s);
4114 break;
4115
4116 case STRETCH_GLYPH:
4117 x_draw_stretch_glyph_string (s);
4118 break;
4119
4120 case CHAR_GLYPH:
4121 if (s->for_overlaps_p)
4122 s->background_filled_p = 1;
4123 else
4124 x_draw_glyph_string_background (s, 0);
4125 x_draw_glyph_string_foreground (s);
4126 break;
4127
4128 case COMPOSITE_GLYPH:
4129 if (s->for_overlaps_p || s->gidx > 0)
4130 s->background_filled_p = 1;
4131 else
4132 x_draw_glyph_string_background (s, 1);
4133 x_draw_composite_glyph_string_foreground (s);
4134 break;
4135
4136 default:
4137 abort ();
4138 }
4139
4140 if (!s->for_overlaps_p)
4141 {
4142 /* Draw underline. */
4143 if (s->face->underline_p)
4144 {
4145 unsigned long dy, h;
4146
4147 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4148 h = 1;
4149 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4150 dy = s->height - h;
4151
4152 if (s->face->underline_defaulted_p)
4153 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4154 s->width, h);
4155 else
4156 {
4157 XGCValues xgcv;
4158 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4159 XSetForeground (s->display, s->gc, s->face->underline_color);
4160 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4161 s->width, h);
4162 XSetForeground (s->display, s->gc, xgcv.foreground);
4163 }
4164 }
4165
4166 /* Draw overline. */
4167 if (s->face->overline_p)
4168 {
4169 unsigned long dy = 0, h = 1;
4170
4171 if (s->face->overline_color_defaulted_p)
4172 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4173 s->width, h);
4174 else
4175 {
4176 XGCValues xgcv;
4177 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4178 XSetForeground (s->display, s->gc, s->face->overline_color);
4179 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4180 s->width, h);
4181 XSetForeground (s->display, s->gc, xgcv.foreground);
4182 }
4183 }
4184
4185 /* Draw strike-through. */
4186 if (s->face->strike_through_p)
4187 {
4188 unsigned long h = 1;
4189 unsigned long dy = (s->height - h) / 2;
4190
4191 if (s->face->strike_through_color_defaulted_p)
4192 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4193 s->width, h);
4194 else
4195 {
4196 XGCValues xgcv;
4197 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4198 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4199 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4200 s->width, h);
4201 XSetForeground (s->display, s->gc, xgcv.foreground);
4202 }
4203 }
4204
4205 /* Draw relief. */
4206 if (s->face->box != FACE_NO_BOX)
4207 x_draw_glyph_string_box (s);
4208 }
4209
4210 /* Reset clipping. */
4211 XSetClipMask (s->display, s->gc, None);
4212 }
4213
4214
4215 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4216 struct face **, int));
4217
4218
4219 /* Fill glyph string S with composition components specified by S->cmp.
4220
4221 FACES is an array of faces for all components of this composition.
4222 S->gidx is the index of the first component for S.
4223 OVERLAPS_P non-zero means S should draw the foreground only, and
4224 use its physical height for clipping.
4225
4226 Value is the index of a component not in S. */
4227
4228 static int
4229 x_fill_composite_glyph_string (s, faces, overlaps_p)
4230 struct glyph_string *s;
4231 struct face **faces;
4232 int overlaps_p;
4233 {
4234 int i;
4235
4236 xassert (s);
4237
4238 s->for_overlaps_p = overlaps_p;
4239
4240 s->face = faces[s->gidx];
4241 s->font = s->face->font;
4242 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4243
4244 /* For all glyphs of this composition, starting at the offset
4245 S->gidx, until we reach the end of the definition or encounter a
4246 glyph that requires the different face, add it to S. */
4247 ++s->nchars;
4248 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4249 ++s->nchars;
4250
4251 /* All glyph strings for the same composition has the same width,
4252 i.e. the width set for the first component of the composition. */
4253
4254 s->width = s->first_glyph->pixel_width;
4255
4256 /* If the specified font could not be loaded, use the frame's
4257 default font, but record the fact that we couldn't load it in
4258 the glyph string so that we can draw rectangles for the
4259 characters of the glyph string. */
4260 if (s->font == NULL)
4261 {
4262 s->font_not_found_p = 1;
4263 s->font = FRAME_FONT (s->f);
4264 }
4265
4266 /* Adjust base line for subscript/superscript text. */
4267 s->ybase += s->first_glyph->voffset;
4268
4269 xassert (s->face && s->face->gc);
4270
4271 /* This glyph string must always be drawn with 16-bit functions. */
4272 s->two_byte_p = 1;
4273
4274 return s->gidx + s->nchars;
4275 }
4276
4277
4278 /* Fill glyph string S from a sequence of character glyphs.
4279
4280 FACE_ID is the face id of the string. START is the index of the
4281 first glyph to consider, END is the index of the last + 1.
4282 OVERLAPS_P non-zero means S should draw the foreground only, and
4283 use its physical height for clipping.
4284
4285 Value is the index of the first glyph not in S. */
4286
4287 static int
4288 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4289 struct glyph_string *s;
4290 int face_id;
4291 int start, end, overlaps_p;
4292 {
4293 struct glyph *glyph, *last;
4294 int voffset;
4295 int glyph_not_available_p;
4296
4297 xassert (s->f == XFRAME (s->w->frame));
4298 xassert (s->nchars == 0);
4299 xassert (start >= 0 && end > start);
4300
4301 s->for_overlaps_p = overlaps_p,
4302 glyph = s->row->glyphs[s->area] + start;
4303 last = s->row->glyphs[s->area] + end;
4304 voffset = glyph->voffset;
4305
4306 glyph_not_available_p = glyph->glyph_not_available_p;
4307
4308 while (glyph < last
4309 && glyph->type == CHAR_GLYPH
4310 && glyph->voffset == voffset
4311 /* Same face id implies same font, nowadays. */
4312 && glyph->face_id == face_id
4313 && glyph->glyph_not_available_p == glyph_not_available_p)
4314 {
4315 int two_byte_p;
4316
4317 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4318 s->char2b + s->nchars,
4319 &two_byte_p);
4320 s->two_byte_p = two_byte_p;
4321 ++s->nchars;
4322 xassert (s->nchars <= end - start);
4323 s->width += glyph->pixel_width;
4324 ++glyph;
4325 }
4326
4327 s->font = s->face->font;
4328 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4329
4330 /* If the specified font could not be loaded, use the frame's font,
4331 but record the fact that we couldn't load it in
4332 S->font_not_found_p so that we can draw rectangles for the
4333 characters of the glyph string. */
4334 if (s->font == NULL || glyph_not_available_p)
4335 {
4336 s->font_not_found_p = 1;
4337 s->font = FRAME_FONT (s->f);
4338 }
4339
4340 /* Adjust base line for subscript/superscript text. */
4341 s->ybase += voffset;
4342
4343 xassert (s->face && s->face->gc);
4344 return glyph - s->row->glyphs[s->area];
4345 }
4346
4347
4348 /* Fill glyph string S from image glyph S->first_glyph. */
4349
4350 static void
4351 x_fill_image_glyph_string (s)
4352 struct glyph_string *s;
4353 {
4354 xassert (s->first_glyph->type == IMAGE_GLYPH);
4355 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4356 xassert (s->img);
4357 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4358 s->font = s->face->font;
4359 s->width = s->first_glyph->pixel_width;
4360
4361 /* Adjust base line for subscript/superscript text. */
4362 s->ybase += s->first_glyph->voffset;
4363 }
4364
4365
4366 /* Fill glyph string S from a sequence of stretch glyphs.
4367
4368 ROW is the glyph row in which the glyphs are found, AREA is the
4369 area within the row. START is the index of the first glyph to
4370 consider, END is the index of the last + 1.
4371
4372 Value is the index of the first glyph not in S. */
4373
4374 static int
4375 x_fill_stretch_glyph_string (s, row, area, start, end)
4376 struct glyph_string *s;
4377 struct glyph_row *row;
4378 enum glyph_row_area area;
4379 int start, end;
4380 {
4381 struct glyph *glyph, *last;
4382 int voffset, face_id;
4383
4384 xassert (s->first_glyph->type == STRETCH_GLYPH);
4385
4386 glyph = s->row->glyphs[s->area] + start;
4387 last = s->row->glyphs[s->area] + end;
4388 face_id = glyph->face_id;
4389 s->face = FACE_FROM_ID (s->f, face_id);
4390 s->font = s->face->font;
4391 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4392 s->width = glyph->pixel_width;
4393 voffset = glyph->voffset;
4394
4395 for (++glyph;
4396 (glyph < last
4397 && glyph->type == STRETCH_GLYPH
4398 && glyph->voffset == voffset
4399 && glyph->face_id == face_id);
4400 ++glyph)
4401 s->width += glyph->pixel_width;
4402
4403 /* Adjust base line for subscript/superscript text. */
4404 s->ybase += voffset;
4405
4406 xassert (s->face && s->face->gc);
4407 return glyph - s->row->glyphs[s->area];
4408 }
4409
4410
4411 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4412 of XChar2b structures for S; it can't be allocated in
4413 x_init_glyph_string because it must be allocated via `alloca'. W
4414 is the window on which S is drawn. ROW and AREA are the glyph row
4415 and area within the row from which S is constructed. START is the
4416 index of the first glyph structure covered by S. HL is a
4417 face-override for drawing S. */
4418
4419 static void
4420 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4421 struct glyph_string *s;
4422 XChar2b *char2b;
4423 struct window *w;
4424 struct glyph_row *row;
4425 enum glyph_row_area area;
4426 int start;
4427 enum draw_glyphs_face hl;
4428 {
4429 bzero (s, sizeof *s);
4430 s->w = w;
4431 s->f = XFRAME (w->frame);
4432 s->display = FRAME_X_DISPLAY (s->f);
4433 s->window = FRAME_X_WINDOW (s->f);
4434 s->char2b = char2b;
4435 s->hl = hl;
4436 s->row = row;
4437 s->area = area;
4438 s->first_glyph = row->glyphs[area] + start;
4439 s->height = row->height;
4440 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4441
4442 /* Display the internal border below the tool-bar window. */
4443 if (s->w == XWINDOW (s->f->tool_bar_window))
4444 s->y -= s->f->output_data.x->internal_border_width;
4445
4446 s->ybase = s->y + row->ascent;
4447 }
4448
4449
4450 /* Set background width of glyph string S. START is the index of the
4451 first glyph following S. LAST_X is the right-most x-position + 1
4452 in the drawing area. */
4453
4454 static INLINE void
4455 x_set_glyph_string_background_width (s, start, last_x)
4456 struct glyph_string *s;
4457 int start;
4458 int last_x;
4459 {
4460 /* If the face of this glyph string has to be drawn to the end of
4461 the drawing area, set S->extends_to_end_of_line_p. */
4462 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4463
4464 if (start == s->row->used[s->area]
4465 && s->hl == DRAW_NORMAL_TEXT
4466 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4467 || s->face->background != default_face->background
4468 || s->face->stipple != default_face->stipple))
4469 s->extends_to_end_of_line_p = 1;
4470
4471 /* If S extends its face to the end of the line, set its
4472 background_width to the distance to the right edge of the drawing
4473 area. */
4474 if (s->extends_to_end_of_line_p)
4475 s->background_width = last_x - s->x + 1;
4476 else
4477 s->background_width = s->width;
4478 }
4479
4480
4481 /* Add a glyph string for a stretch glyph to the list of strings
4482 between HEAD and TAIL. START is the index of the stretch glyph in
4483 row area AREA of glyph row ROW. END is the index of the last glyph
4484 in that glyph row area. X is the current output position assigned
4485 to the new glyph string constructed. HL overrides that face of the
4486 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4487 is the right-most x-position of the drawing area. */
4488
4489 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4490 and below -- keep them on one line. */
4491 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4492 do \
4493 { \
4494 s = (struct glyph_string *) alloca (sizeof *s); \
4495 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4496 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4497 x_append_glyph_string (&HEAD, &TAIL, s); \
4498 s->x = (X); \
4499 } \
4500 while (0)
4501
4502
4503 /* Add a glyph string for an image glyph to the list of strings
4504 between HEAD and TAIL. START is the index of the image glyph in
4505 row area AREA of glyph row ROW. END is the index of the last glyph
4506 in that glyph row area. X is the current output position assigned
4507 to the new glyph string constructed. HL overrides that face of the
4508 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4509 is the right-most x-position of the drawing area. */
4510
4511 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4512 do \
4513 { \
4514 s = (struct glyph_string *) alloca (sizeof *s); \
4515 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4516 x_fill_image_glyph_string (s); \
4517 x_append_glyph_string (&HEAD, &TAIL, s); \
4518 ++START; \
4519 s->x = (X); \
4520 } \
4521 while (0)
4522
4523
4524 /* Add a glyph string for a sequence of character glyphs to the list
4525 of strings between HEAD and TAIL. START is the index of the first
4526 glyph in row area AREA of glyph row ROW that is part of the new
4527 glyph string. END is the index of the last glyph in that glyph row
4528 area. X is the current output position assigned to the new glyph
4529 string constructed. HL overrides that face of the glyph; e.g. it
4530 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4531 right-most x-position of the drawing area. */
4532
4533 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4534 do \
4535 { \
4536 int c, face_id; \
4537 XChar2b *char2b; \
4538 \
4539 c = (ROW)->glyphs[AREA][START].u.ch; \
4540 face_id = (ROW)->glyphs[AREA][START].face_id; \
4541 \
4542 s = (struct glyph_string *) alloca (sizeof *s); \
4543 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4544 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4545 x_append_glyph_string (&HEAD, &TAIL, s); \
4546 s->x = (X); \
4547 START = x_fill_glyph_string (s, face_id, START, END, \
4548 OVERLAPS_P); \
4549 } \
4550 while (0)
4551
4552
4553 /* Add a glyph string for a composite sequence to the list of strings
4554 between HEAD and TAIL. START is the index of the first glyph in
4555 row area AREA of glyph row ROW that is part of the new glyph
4556 string. END is the index of the last glyph in that glyph row area.
4557 X is the current output position assigned to the new glyph string
4558 constructed. HL overrides that face of the glyph; e.g. it is
4559 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4560 x-position of the drawing area. */
4561
4562 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4563 do { \
4564 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4565 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4566 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4567 struct composition *cmp = composition_table[cmp_id]; \
4568 int glyph_len = cmp->glyph_len; \
4569 XChar2b *char2b; \
4570 struct face **faces; \
4571 struct glyph_string *first_s = NULL; \
4572 int n; \
4573 \
4574 base_face = base_face->ascii_face; \
4575 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4576 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4577 /* At first, fill in `char2b' and `faces'. */ \
4578 for (n = 0; n < glyph_len; n++) \
4579 { \
4580 int c = COMPOSITION_GLYPH (cmp, n); \
4581 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4582 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4583 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4584 this_face_id, char2b + n, 1); \
4585 } \
4586 \
4587 /* Make glyph_strings for each glyph sequence that is drawable by \
4588 the same face, and append them to HEAD/TAIL. */ \
4589 for (n = 0; n < cmp->glyph_len;) \
4590 { \
4591 s = (struct glyph_string *) alloca (sizeof *s); \
4592 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4593 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4594 s->cmp = cmp; \
4595 s->gidx = n; \
4596 s->x = (X); \
4597 \
4598 if (n == 0) \
4599 first_s = s; \
4600 \
4601 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4602 } \
4603 \
4604 ++START; \
4605 s = first_s; \
4606 } while (0)
4607
4608
4609 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4610 of AREA of glyph row ROW on window W between indices START and END.
4611 HL overrides the face for drawing glyph strings, e.g. it is
4612 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4613 x-positions of the drawing area.
4614
4615 This is an ugly monster macro construct because we must use alloca
4616 to allocate glyph strings (because x_draw_glyphs can be called
4617 asynchronously). */
4618
4619 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4620 do \
4621 { \
4622 HEAD = TAIL = NULL; \
4623 while (START < END) \
4624 { \
4625 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4626 switch (first_glyph->type) \
4627 { \
4628 case CHAR_GLYPH: \
4629 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4630 TAIL, HL, X, LAST_X, \
4631 OVERLAPS_P); \
4632 break; \
4633 \
4634 case COMPOSITE_GLYPH: \
4635 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4636 HEAD, TAIL, HL, X, LAST_X,\
4637 OVERLAPS_P); \
4638 break; \
4639 \
4640 case STRETCH_GLYPH: \
4641 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4642 HEAD, TAIL, HL, X, LAST_X); \
4643 break; \
4644 \
4645 case IMAGE_GLYPH: \
4646 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4647 TAIL, HL, X, LAST_X); \
4648 break; \
4649 \
4650 default: \
4651 abort (); \
4652 } \
4653 \
4654 x_set_glyph_string_background_width (s, START, LAST_X); \
4655 (X) += s->width; \
4656 } \
4657 } \
4658 while (0)
4659
4660
4661 /* Draw glyphs between START and END in AREA of ROW on window W,
4662 starting at x-position X. X is relative to AREA in W. HL is a
4663 face-override with the following meaning:
4664
4665 DRAW_NORMAL_TEXT draw normally
4666 DRAW_CURSOR draw in cursor face
4667 DRAW_MOUSE_FACE draw in mouse face.
4668 DRAW_INVERSE_VIDEO draw in mode line face
4669 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4670 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4671
4672 If REAL_START is non-null, return in *REAL_START the real starting
4673 position for display. This can be different from START in case
4674 overlapping glyphs must be displayed. If REAL_END is non-null,
4675 return in *REAL_END the real end position for display. This can be
4676 different from END in case overlapping glyphs must be displayed.
4677
4678 If OVERLAPS_P is non-zero, draw only the foreground of characters
4679 and clip to the physical height of ROW.
4680
4681 Value is the x-position reached, relative to AREA of W. */
4682
4683 static int
4684 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4685 overlaps_p)
4686 struct window *w;
4687 int x;
4688 struct glyph_row *row;
4689 enum glyph_row_area area;
4690 int start, end;
4691 enum draw_glyphs_face hl;
4692 int *real_start, *real_end;
4693 int overlaps_p;
4694 {
4695 struct glyph_string *head, *tail;
4696 struct glyph_string *s;
4697 int last_x, area_width;
4698 int x_reached;
4699 int i, j;
4700
4701 /* Let's rather be paranoid than getting a SEGV. */
4702 end = min (end, row->used[area]);
4703 start = max (0, start);
4704 start = min (end, start);
4705 if (real_start)
4706 *real_start = start;
4707 if (real_end)
4708 *real_end = end;
4709
4710 /* Translate X to frame coordinates. Set last_x to the right
4711 end of the drawing area. */
4712 if (row->full_width_p)
4713 {
4714 /* X is relative to the left edge of W, without scroll bars
4715 or flag areas. */
4716 struct frame *f = XFRAME (w->frame);
4717 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4718 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4719
4720 x += window_left_x;
4721 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4722 last_x = window_left_x + area_width;
4723
4724 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4725 {
4726 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4727 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4728 last_x += width;
4729 else
4730 x -= width;
4731 }
4732
4733 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4734 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4735 }
4736 else
4737 {
4738 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4739 area_width = window_box_width (w, area);
4740 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4741 }
4742
4743 /* Build a doubly-linked list of glyph_string structures between
4744 head and tail from what we have to draw. Note that the macro
4745 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4746 the reason we use a separate variable `i'. */
4747 i = start;
4748 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4749 overlaps_p);
4750 if (tail)
4751 x_reached = tail->x + tail->background_width;
4752 else
4753 x_reached = x;
4754
4755 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4756 the row, redraw some glyphs in front or following the glyph
4757 strings built above. */
4758 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4759 {
4760 int dummy_x = 0;
4761 struct glyph_string *h, *t;
4762
4763 /* Compute overhangs for all glyph strings. */
4764 for (s = head; s; s = s->next)
4765 x_compute_glyph_string_overhangs (s);
4766
4767 /* Prepend glyph strings for glyphs in front of the first glyph
4768 string that are overwritten because of the first glyph
4769 string's left overhang. The background of all strings
4770 prepended must be drawn because the first glyph string
4771 draws over it. */
4772 i = x_left_overwritten (head);
4773 if (i >= 0)
4774 {
4775 j = i;
4776 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4777 DRAW_NORMAL_TEXT, dummy_x, last_x,
4778 overlaps_p);
4779 start = i;
4780 if (real_start)
4781 *real_start = start;
4782 x_compute_overhangs_and_x (t, head->x, 1);
4783 x_prepend_glyph_string_lists (&head, &tail, h, t);
4784 }
4785
4786 /* Prepend glyph strings for glyphs in front of the first glyph
4787 string that overwrite that glyph string because of their
4788 right overhang. For these strings, only the foreground must
4789 be drawn, because it draws over the glyph string at `head'.
4790 The background must not be drawn because this would overwrite
4791 right overhangs of preceding glyphs for which no glyph
4792 strings exist. */
4793 i = x_left_overwriting (head);
4794 if (i >= 0)
4795 {
4796 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4797 DRAW_NORMAL_TEXT, dummy_x, last_x,
4798 overlaps_p);
4799 for (s = h; s; s = s->next)
4800 s->background_filled_p = 1;
4801 if (real_start)
4802 *real_start = i;
4803 x_compute_overhangs_and_x (t, head->x, 1);
4804 x_prepend_glyph_string_lists (&head, &tail, h, t);
4805 }
4806
4807 /* Append glyphs strings for glyphs following the last glyph
4808 string tail that are overwritten by tail. The background of
4809 these strings has to be drawn because tail's foreground draws
4810 over it. */
4811 i = x_right_overwritten (tail);
4812 if (i >= 0)
4813 {
4814 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4815 DRAW_NORMAL_TEXT, x, last_x,
4816 overlaps_p);
4817 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4818 x_append_glyph_string_lists (&head, &tail, h, t);
4819 if (real_end)
4820 *real_end = i;
4821 }
4822
4823 /* Append glyph strings for glyphs following the last glyph
4824 string tail that overwrite tail. The foreground of such
4825 glyphs has to be drawn because it writes into the background
4826 of tail. The background must not be drawn because it could
4827 paint over the foreground of following glyphs. */
4828 i = x_right_overwriting (tail);
4829 if (i >= 0)
4830 {
4831 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4832 DRAW_NORMAL_TEXT, x, last_x,
4833 overlaps_p);
4834 for (s = h; s; s = s->next)
4835 s->background_filled_p = 1;
4836 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4837 x_append_glyph_string_lists (&head, &tail, h, t);
4838 if (real_end)
4839 *real_end = i;
4840 }
4841 }
4842
4843 /* Draw all strings. */
4844 for (s = head; s; s = s->next)
4845 x_draw_glyph_string (s);
4846
4847 /* Value is the x-position up to which drawn, relative to AREA of W.
4848 This doesn't include parts drawn because of overhangs. */
4849 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4850 if (!row->full_width_p)
4851 {
4852 if (area > LEFT_MARGIN_AREA)
4853 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4854 if (area > TEXT_AREA)
4855 x_reached -= window_box_width (w, TEXT_AREA);
4856 }
4857
4858 return x_reached;
4859 }
4860
4861
4862 /* Fix the display of area AREA of overlapping row ROW in window W. */
4863
4864 static void
4865 x_fix_overlapping_area (w, row, area)
4866 struct window *w;
4867 struct glyph_row *row;
4868 enum glyph_row_area area;
4869 {
4870 int i, x;
4871
4872 BLOCK_INPUT;
4873
4874 if (area == LEFT_MARGIN_AREA)
4875 x = 0;
4876 else if (area == TEXT_AREA)
4877 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4878 else
4879 x = (window_box_width (w, LEFT_MARGIN_AREA)
4880 + window_box_width (w, TEXT_AREA));
4881
4882 for (i = 0; i < row->used[area];)
4883 {
4884 if (row->glyphs[area][i].overlaps_vertically_p)
4885 {
4886 int start = i, start_x = x;
4887
4888 do
4889 {
4890 x += row->glyphs[area][i].pixel_width;
4891 ++i;
4892 }
4893 while (i < row->used[area]
4894 && row->glyphs[area][i].overlaps_vertically_p);
4895
4896 x_draw_glyphs (w, start_x, row, area, start, i,
4897 (row->inverse_p
4898 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4899 NULL, NULL, 1);
4900 }
4901 else
4902 {
4903 x += row->glyphs[area][i].pixel_width;
4904 ++i;
4905 }
4906 }
4907
4908 UNBLOCK_INPUT;
4909 }
4910
4911
4912 /* Output LEN glyphs starting at START at the nominal cursor position.
4913 Advance the nominal cursor over the text. The global variable
4914 updated_window contains the window being updated, updated_row is
4915 the glyph row being updated, and updated_area is the area of that
4916 row being updated. */
4917
4918 static void
4919 x_write_glyphs (start, len)
4920 struct glyph *start;
4921 int len;
4922 {
4923 int x, hpos, real_start, real_end;
4924
4925 xassert (updated_window && updated_row);
4926 BLOCK_INPUT;
4927
4928 /* Write glyphs. */
4929
4930 hpos = start - updated_row->glyphs[updated_area];
4931 x = x_draw_glyphs (updated_window, output_cursor.x,
4932 updated_row, updated_area,
4933 hpos, hpos + len,
4934 (updated_row->inverse_p
4935 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4936 &real_start, &real_end, 0);
4937
4938 /* If we drew over the cursor, note that it is not visible any more. */
4939 note_overwritten_text_cursor (updated_window, real_start,
4940 real_end - real_start);
4941
4942 UNBLOCK_INPUT;
4943
4944 /* Advance the output cursor. */
4945 output_cursor.hpos += len;
4946 output_cursor.x = x;
4947 }
4948
4949
4950 /* Insert LEN glyphs from START at the nominal cursor position. */
4951
4952 static void
4953 x_insert_glyphs (start, len)
4954 struct glyph *start;
4955 register int len;
4956 {
4957 struct frame *f;
4958 struct window *w;
4959 int line_height, shift_by_width, shifted_region_width;
4960 struct glyph_row *row;
4961 struct glyph *glyph;
4962 int frame_x, frame_y, hpos, real_start, real_end;
4963
4964 xassert (updated_window && updated_row);
4965 BLOCK_INPUT;
4966 w = updated_window;
4967 f = XFRAME (WINDOW_FRAME (w));
4968
4969 /* Get the height of the line we are in. */
4970 row = updated_row;
4971 line_height = row->height;
4972
4973 /* Get the width of the glyphs to insert. */
4974 shift_by_width = 0;
4975 for (glyph = start; glyph < start + len; ++glyph)
4976 shift_by_width += glyph->pixel_width;
4977
4978 /* Get the width of the region to shift right. */
4979 shifted_region_width = (window_box_width (w, updated_area)
4980 - output_cursor.x
4981 - shift_by_width);
4982
4983 /* Shift right. */
4984 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4985 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4986 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4987 f->output_data.x->normal_gc,
4988 frame_x, frame_y,
4989 shifted_region_width, line_height,
4990 frame_x + shift_by_width, frame_y);
4991
4992 /* Write the glyphs. */
4993 hpos = start - row->glyphs[updated_area];
4994 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4995 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4996 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4997
4998 /* Advance the output cursor. */
4999 output_cursor.hpos += len;
5000 output_cursor.x += shift_by_width;
5001 UNBLOCK_INPUT;
5002 }
5003
5004
5005 /* Delete N glyphs at the nominal cursor position. Not implemented
5006 for X frames. */
5007
5008 static void
5009 x_delete_glyphs (n)
5010 register int n;
5011 {
5012 abort ();
5013 }
5014
5015
5016 /* Erase the current text line from the nominal cursor position
5017 (inclusive) to pixel column TO_X (exclusive). The idea is that
5018 everything from TO_X onward is already erased.
5019
5020 TO_X is a pixel position relative to updated_area of
5021 updated_window. TO_X == -1 means clear to the end of this area. */
5022
5023 static void
5024 x_clear_end_of_line (to_x)
5025 int to_x;
5026 {
5027 struct frame *f;
5028 struct window *w = updated_window;
5029 int max_x, min_y, max_y;
5030 int from_x, from_y, to_y;
5031
5032 xassert (updated_window && updated_row);
5033 f = XFRAME (w->frame);
5034
5035 if (updated_row->full_width_p)
5036 {
5037 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5038 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5039 && !w->pseudo_window_p)
5040 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5041 }
5042 else
5043 max_x = window_box_width (w, updated_area);
5044 max_y = window_text_bottom_y (w);
5045
5046 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5047 of window. For TO_X > 0, truncate to end of drawing area. */
5048 if (to_x == 0)
5049 return;
5050 else if (to_x < 0)
5051 to_x = max_x;
5052 else
5053 to_x = min (to_x, max_x);
5054
5055 to_y = min (max_y, output_cursor.y + updated_row->height);
5056
5057 /* Notice if the cursor will be cleared by this operation. */
5058 if (!updated_row->full_width_p)
5059 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5060
5061 from_x = output_cursor.x;
5062
5063 /* Translate to frame coordinates. */
5064 if (updated_row->full_width_p)
5065 {
5066 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5067 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5068 }
5069 else
5070 {
5071 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5072 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5073 }
5074
5075 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5076 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5077 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5078
5079 /* Prevent inadvertently clearing to end of the X window. */
5080 if (to_x > from_x && to_y > from_y)
5081 {
5082 BLOCK_INPUT;
5083 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5084 from_x, from_y, to_x - from_x, to_y - from_y,
5085 False);
5086 UNBLOCK_INPUT;
5087 }
5088 }
5089
5090
5091 /* Clear entire frame. If updating_frame is non-null, clear that
5092 frame. Otherwise clear the selected frame. */
5093
5094 static void
5095 x_clear_frame ()
5096 {
5097 struct frame *f;
5098
5099 if (updating_frame)
5100 f = updating_frame;
5101 else
5102 f = SELECTED_FRAME ();
5103
5104 /* Clearing the frame will erase any cursor, so mark them all as no
5105 longer visible. */
5106 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5107 output_cursor.hpos = output_cursor.vpos = 0;
5108 output_cursor.x = -1;
5109
5110 /* We don't set the output cursor here because there will always
5111 follow an explicit cursor_to. */
5112 BLOCK_INPUT;
5113 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5114
5115 /* We have to clear the scroll bars, too. If we have changed
5116 colors or something like that, then they should be notified. */
5117 x_scroll_bar_clear (f);
5118
5119 XFlush (FRAME_X_DISPLAY (f));
5120 UNBLOCK_INPUT;
5121 }
5122
5123
5124 \f
5125 /* Invert the middle quarter of the frame for .15 sec. */
5126
5127 /* We use the select system call to do the waiting, so we have to make
5128 sure it's available. If it isn't, we just won't do visual bells. */
5129
5130 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5131
5132
5133 /* Subtract the `struct timeval' values X and Y, storing the result in
5134 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5135
5136 static int
5137 timeval_subtract (result, x, y)
5138 struct timeval *result, x, y;
5139 {
5140 /* Perform the carry for the later subtraction by updating y. This
5141 is safer because on some systems the tv_sec member is unsigned. */
5142 if (x.tv_usec < y.tv_usec)
5143 {
5144 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5145 y.tv_usec -= 1000000 * nsec;
5146 y.tv_sec += nsec;
5147 }
5148
5149 if (x.tv_usec - y.tv_usec > 1000000)
5150 {
5151 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5152 y.tv_usec += 1000000 * nsec;
5153 y.tv_sec -= nsec;
5154 }
5155
5156 /* Compute the time remaining to wait. tv_usec is certainly
5157 positive. */
5158 result->tv_sec = x.tv_sec - y.tv_sec;
5159 result->tv_usec = x.tv_usec - y.tv_usec;
5160
5161 /* Return indication of whether the result should be considered
5162 negative. */
5163 return x.tv_sec < y.tv_sec;
5164 }
5165
5166 void
5167 XTflash (f)
5168 struct frame *f;
5169 {
5170 BLOCK_INPUT;
5171
5172 {
5173 GC gc;
5174
5175 /* Create a GC that will use the GXxor function to flip foreground
5176 pixels into background pixels. */
5177 {
5178 XGCValues values;
5179
5180 values.function = GXxor;
5181 values.foreground = (f->output_data.x->foreground_pixel
5182 ^ f->output_data.x->background_pixel);
5183
5184 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5185 GCFunction | GCForeground, &values);
5186 }
5187
5188 {
5189 /* Get the height not including a menu bar widget. */
5190 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5191 /* Height of each line to flash. */
5192 int flash_height = FRAME_LINE_HEIGHT (f);
5193 /* These will be the left and right margins of the rectangles. */
5194 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5195 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5196
5197 int width;
5198
5199 /* Don't flash the area between a scroll bar and the frame
5200 edge it is next to. */
5201 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5202 {
5203 case vertical_scroll_bar_left:
5204 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5205 break;
5206
5207 case vertical_scroll_bar_right:
5208 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5209 break;
5210
5211 default:
5212 break;
5213 }
5214
5215 width = flash_right - flash_left;
5216
5217 /* If window is tall, flash top and bottom line. */
5218 if (height > 3 * FRAME_LINE_HEIGHT (f))
5219 {
5220 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5221 flash_left,
5222 (FRAME_INTERNAL_BORDER_WIDTH (f)
5223 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5224 width, flash_height);
5225 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5226 flash_left,
5227 (height - flash_height
5228 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5229 width, flash_height);
5230 }
5231 else
5232 /* If it is short, flash it all. */
5233 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5234 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5235 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5236
5237 x_flush (f);
5238
5239 {
5240 struct timeval wakeup;
5241
5242 EMACS_GET_TIME (wakeup);
5243
5244 /* Compute time to wait until, propagating carry from usecs. */
5245 wakeup.tv_usec += 150000;
5246 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5247 wakeup.tv_usec %= 1000000;
5248
5249 /* Keep waiting until past the time wakeup. */
5250 while (1)
5251 {
5252 struct timeval timeout;
5253
5254 EMACS_GET_TIME (timeout);
5255
5256 /* In effect, timeout = wakeup - timeout.
5257 Break if result would be negative. */
5258 if (timeval_subtract (&timeout, wakeup, timeout))
5259 break;
5260
5261 /* Try to wait that long--but we might wake up sooner. */
5262 select (0, NULL, NULL, NULL, &timeout);
5263 }
5264 }
5265
5266 /* If window is tall, flash top and bottom line. */
5267 if (height > 3 * FRAME_LINE_HEIGHT (f))
5268 {
5269 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5270 flash_left,
5271 (FRAME_INTERNAL_BORDER_WIDTH (f)
5272 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5273 width, flash_height);
5274 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5275 flash_left,
5276 (height - flash_height
5277 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5278 width, flash_height);
5279 }
5280 else
5281 /* If it is short, flash it all. */
5282 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5283 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5284 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5285
5286 XFreeGC (FRAME_X_DISPLAY (f), gc);
5287 x_flush (f);
5288 }
5289 }
5290
5291 UNBLOCK_INPUT;
5292 }
5293
5294 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5295
5296
5297 /* Make audible bell. */
5298
5299 void
5300 XTring_bell ()
5301 {
5302 struct frame *f = SELECTED_FRAME ();
5303
5304 if (FRAME_X_DISPLAY (f))
5305 {
5306 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5307 if (visible_bell)
5308 XTflash (f);
5309 else
5310 #endif
5311 {
5312 BLOCK_INPUT;
5313 XBell (FRAME_X_DISPLAY (f), 0);
5314 XFlush (FRAME_X_DISPLAY (f));
5315 UNBLOCK_INPUT;
5316 }
5317 }
5318 }
5319
5320 \f
5321 /* Specify how many text lines, from the top of the window,
5322 should be affected by insert-lines and delete-lines operations.
5323 This, and those operations, are used only within an update
5324 that is bounded by calls to x_update_begin and x_update_end. */
5325
5326 static void
5327 XTset_terminal_window (n)
5328 register int n;
5329 {
5330 /* This function intentionally left blank. */
5331 }
5332
5333
5334 \f
5335 /***********************************************************************
5336 Line Dance
5337 ***********************************************************************/
5338
5339 /* Perform an insert-lines or delete-lines operation, inserting N
5340 lines or deleting -N lines at vertical position VPOS. */
5341
5342 static void
5343 x_ins_del_lines (vpos, n)
5344 int vpos, n;
5345 {
5346 abort ();
5347 }
5348
5349
5350 /* Scroll part of the display as described by RUN. */
5351
5352 static void
5353 x_scroll_run (w, run)
5354 struct window *w;
5355 struct run *run;
5356 {
5357 struct frame *f = XFRAME (w->frame);
5358 int x, y, width, height, from_y, to_y, bottom_y;
5359
5360 /* Get frame-relative bounding box of the text display area of W,
5361 without mode lines. Include in this box the flags areas to the
5362 left and right of W. */
5363 window_box (w, -1, &x, &y, &width, &height);
5364 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5365 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5366
5367 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5368 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5369 bottom_y = y + height;
5370
5371 if (to_y < from_y)
5372 {
5373 /* Scrolling up. Make sure we don't copy part of the mode
5374 line at the bottom. */
5375 if (from_y + run->height > bottom_y)
5376 height = bottom_y - from_y;
5377 else
5378 height = run->height;
5379 }
5380 else
5381 {
5382 /* Scolling down. Make sure we don't copy over the mode line.
5383 at the bottom. */
5384 if (to_y + run->height > bottom_y)
5385 height = bottom_y - to_y;
5386 else
5387 height = run->height;
5388 }
5389
5390 BLOCK_INPUT;
5391
5392 /* Cursor off. Will be switched on again in x_update_window_end. */
5393 updated_window = w;
5394 x_clear_cursor (w);
5395
5396 XCopyArea (FRAME_X_DISPLAY (f),
5397 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5398 f->output_data.x->normal_gc,
5399 x, from_y,
5400 width, height,
5401 x, to_y);
5402
5403 UNBLOCK_INPUT;
5404 }
5405
5406
5407 \f
5408 /***********************************************************************
5409 Exposure Events
5410 ***********************************************************************/
5411
5412 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5413 corner of the exposed rectangle. W and H are width and height of
5414 the exposed area. All are pixel values. W or H zero means redraw
5415 the entire frame. */
5416
5417 static void
5418 expose_frame (f, x, y, w, h)
5419 struct frame *f;
5420 int x, y, w, h;
5421 {
5422 XRectangle r;
5423
5424 TRACE ((stderr, "expose_frame "));
5425
5426 /* No need to redraw if frame will be redrawn soon. */
5427 if (FRAME_GARBAGED_P (f))
5428 {
5429 TRACE ((stderr, " garbaged\n"));
5430 return;
5431 }
5432
5433 /* If basic faces haven't been realized yet, there is no point in
5434 trying to redraw anything. This can happen when we get an expose
5435 event while Emacs is starting, e.g. by moving another window. */
5436 if (FRAME_FACE_CACHE (f) == NULL
5437 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5438 {
5439 TRACE ((stderr, " no faces\n"));
5440 return;
5441 }
5442
5443 if (w == 0 || h == 0)
5444 {
5445 r.x = r.y = 0;
5446 r.width = CANON_X_UNIT (f) * f->width;
5447 r.height = CANON_Y_UNIT (f) * f->height;
5448 }
5449 else
5450 {
5451 r.x = x;
5452 r.y = y;
5453 r.width = w;
5454 r.height = h;
5455 }
5456
5457 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5458 expose_window_tree (XWINDOW (f->root_window), &r);
5459
5460 if (WINDOWP (f->tool_bar_window))
5461 {
5462 struct window *w = XWINDOW (f->tool_bar_window);
5463 XRectangle window_rect;
5464 XRectangle intersection_rect;
5465 int window_x, window_y, window_width, window_height;
5466
5467
5468 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5469 window_rect.x = window_x;
5470 window_rect.y = window_y;
5471 window_rect.width = window_width;
5472 window_rect.height = window_height;
5473
5474 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5475 expose_window (w, &intersection_rect);
5476 }
5477
5478 #ifndef USE_X_TOOLKIT
5479 if (WINDOWP (f->menu_bar_window))
5480 {
5481 struct window *w = XWINDOW (f->menu_bar_window);
5482 XRectangle window_rect;
5483 XRectangle intersection_rect;
5484 int window_x, window_y, window_width, window_height;
5485
5486
5487 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5488 window_rect.x = window_x;
5489 window_rect.y = window_y;
5490 window_rect.width = window_width;
5491 window_rect.height = window_height;
5492
5493 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5494 expose_window (w, &intersection_rect);
5495 }
5496 #endif /* not USE_X_TOOLKIT */
5497 }
5498
5499
5500 /* Redraw (parts) of all windows in the window tree rooted at W that
5501 intersect R. R contains frame pixel coordinates. */
5502
5503 static void
5504 expose_window_tree (w, r)
5505 struct window *w;
5506 XRectangle *r;
5507 {
5508 while (w)
5509 {
5510 if (!NILP (w->hchild))
5511 expose_window_tree (XWINDOW (w->hchild), r);
5512 else if (!NILP (w->vchild))
5513 expose_window_tree (XWINDOW (w->vchild), r);
5514 else
5515 {
5516 XRectangle window_rect;
5517 XRectangle intersection_rect;
5518 struct frame *f = XFRAME (w->frame);
5519 int window_x, window_y, window_width, window_height;
5520
5521 /* Frame-relative pixel rectangle of W. */
5522 window_box (w, -1, &window_x, &window_y, &window_width,
5523 &window_height);
5524 window_rect.x
5525 = (window_x
5526 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5527 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5528 window_rect.y = window_y;
5529 window_rect.width
5530 = (window_width
5531 + FRAME_X_FLAGS_AREA_WIDTH (f)
5532 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5533 window_rect.height
5534 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5535
5536 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5537 expose_window (w, &intersection_rect);
5538 }
5539
5540 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5541 }
5542 }
5543
5544
5545 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5546 which intersects rectangle R. R is in window-relative coordinates. */
5547
5548 static void
5549 expose_area (w, row, r, area)
5550 struct window *w;
5551 struct glyph_row *row;
5552 XRectangle *r;
5553 enum glyph_row_area area;
5554 {
5555 int x;
5556 struct glyph *first = row->glyphs[area];
5557 struct glyph *end = row->glyphs[area] + row->used[area];
5558 struct glyph *last;
5559 int first_x;
5560
5561 /* Set x to the window-relative start position for drawing glyphs of
5562 AREA. The first glyph of the text area can be partially visible.
5563 The first glyphs of other areas cannot. */
5564 if (area == LEFT_MARGIN_AREA)
5565 x = 0;
5566 else if (area == TEXT_AREA)
5567 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5568 else
5569 x = (window_box_width (w, LEFT_MARGIN_AREA)
5570 + window_box_width (w, TEXT_AREA));
5571
5572 if (area == TEXT_AREA && row->fill_line_p)
5573 /* If row extends face to end of line write the whole line. */
5574 x_draw_glyphs (w, x, row, area,
5575 0, row->used[area],
5576 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5577 NULL, NULL, 0);
5578 else
5579 {
5580 /* Find the first glyph that must be redrawn. */
5581 while (first < end
5582 && x + first->pixel_width < r->x)
5583 {
5584 x += first->pixel_width;
5585 ++first;
5586 }
5587
5588 /* Find the last one. */
5589 last = first;
5590 first_x = x;
5591 while (last < end
5592 && x < r->x + r->width)
5593 {
5594 x += last->pixel_width;
5595 ++last;
5596 }
5597
5598 /* Repaint. */
5599 if (last > first)
5600 x_draw_glyphs (w, first_x, row, area,
5601 first - row->glyphs[area],
5602 last - row->glyphs[area],
5603 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5604 NULL, NULL, 0);
5605 }
5606 }
5607
5608
5609 /* Redraw the parts of the glyph row ROW on window W intersecting
5610 rectangle R. R is in window-relative coordinates. */
5611
5612 static void
5613 expose_line (w, row, r)
5614 struct window *w;
5615 struct glyph_row *row;
5616 XRectangle *r;
5617 {
5618 xassert (row->enabled_p);
5619
5620 if (row->mode_line_p || w->pseudo_window_p)
5621 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5622 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5623 NULL, NULL, 0);
5624 else
5625 {
5626 if (row->used[LEFT_MARGIN_AREA])
5627 expose_area (w, row, r, LEFT_MARGIN_AREA);
5628 if (row->used[TEXT_AREA])
5629 expose_area (w, row, r, TEXT_AREA);
5630 if (row->used[RIGHT_MARGIN_AREA])
5631 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5632 x_draw_row_bitmaps (w, row);
5633 }
5634 }
5635
5636
5637 /* Return non-zero if W's cursor intersects rectangle R. */
5638
5639 static int
5640 x_phys_cursor_in_rect_p (w, r)
5641 struct window *w;
5642 XRectangle *r;
5643 {
5644 XRectangle cr, result;
5645 struct glyph *cursor_glyph;
5646
5647 cursor_glyph = get_phys_cursor_glyph (w);
5648 if (cursor_glyph)
5649 {
5650 cr.x = w->phys_cursor.x;
5651 cr.y = w->phys_cursor.y;
5652 cr.width = cursor_glyph->pixel_width;
5653 cr.height = w->phys_cursor_height;
5654 return x_intersect_rectangles (&cr, r, &result);
5655 }
5656 else
5657 return 0;
5658 }
5659
5660
5661 /* Redraw a rectangle of window W. R is a rectangle in window
5662 relative coordinates. Call this function with input blocked. */
5663
5664 static void
5665 expose_window (w, r)
5666 struct window *w;
5667 XRectangle *r;
5668 {
5669 struct glyph_row *row;
5670 int y;
5671 int yb = window_text_bottom_y (w);
5672 int cursor_cleared_p;
5673
5674 /* If window is not yet fully initialized, do nothing. This can
5675 happen when toolkit scroll bars are used and a window is split.
5676 Reconfiguring the scroll bar will generate an expose for a newly
5677 created window. */
5678 if (w->current_matrix == NULL)
5679 return;
5680
5681 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5682 r->x, r->y, r->width, r->height));
5683
5684 /* Convert to window coordinates. */
5685 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5686 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5687
5688 /* Turn off the cursor. */
5689 if (!w->pseudo_window_p
5690 && x_phys_cursor_in_rect_p (w, r))
5691 {
5692 x_clear_cursor (w);
5693 cursor_cleared_p = 1;
5694 }
5695 else
5696 cursor_cleared_p = 0;
5697
5698 /* Find the first row intersecting the rectangle R. */
5699 row = w->current_matrix->rows;
5700 y = 0;
5701 while (row->enabled_p
5702 && y < yb
5703 && y + row->height < r->y)
5704 {
5705 y += row->height;
5706 ++row;
5707 }
5708
5709 /* Display the text in the rectangle, one text line at a time. */
5710 while (row->enabled_p
5711 && y < yb
5712 && y < r->y + r->height)
5713 {
5714 expose_line (w, row, r);
5715 y += row->height;
5716 ++row;
5717 }
5718
5719 /* Display the mode line if there is one. */
5720 if (WINDOW_WANTS_MODELINE_P (w)
5721 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5722 row->enabled_p)
5723 && row->y < r->y + r->height)
5724 expose_line (w, row, r);
5725
5726 if (!w->pseudo_window_p)
5727 {
5728 /* Draw border between windows. */
5729 x_draw_vertical_border (w);
5730
5731 /* Turn the cursor on again. */
5732 if (cursor_cleared_p)
5733 x_update_window_cursor (w, 1);
5734 }
5735 }
5736
5737
5738 /* Determine the intersection of two rectangles R1 and R2. Return
5739 the intersection in *RESULT. Value is non-zero if RESULT is not
5740 empty. */
5741
5742 static int
5743 x_intersect_rectangles (r1, r2, result)
5744 XRectangle *r1, *r2, *result;
5745 {
5746 XRectangle *left, *right;
5747 XRectangle *upper, *lower;
5748 int intersection_p = 0;
5749
5750 /* Rearrange so that R1 is the left-most rectangle. */
5751 if (r1->x < r2->x)
5752 left = r1, right = r2;
5753 else
5754 left = r2, right = r1;
5755
5756 /* X0 of the intersection is right.x0, if this is inside R1,
5757 otherwise there is no intersection. */
5758 if (right->x <= left->x + left->width)
5759 {
5760 result->x = right->x;
5761
5762 /* The right end of the intersection is the minimum of the
5763 the right ends of left and right. */
5764 result->width = (min (left->x + left->width, right->x + right->width)
5765 - result->x);
5766
5767 /* Same game for Y. */
5768 if (r1->y < r2->y)
5769 upper = r1, lower = r2;
5770 else
5771 upper = r2, lower = r1;
5772
5773 /* The upper end of the intersection is lower.y0, if this is inside
5774 of upper. Otherwise, there is no intersection. */
5775 if (lower->y <= upper->y + upper->height)
5776 {
5777 result->y = lower->y;
5778
5779 /* The lower end of the intersection is the minimum of the lower
5780 ends of upper and lower. */
5781 result->height = (min (lower->y + lower->height,
5782 upper->y + upper->height)
5783 - result->y);
5784 intersection_p = 1;
5785 }
5786 }
5787
5788 return intersection_p;
5789 }
5790
5791
5792
5793
5794 \f
5795 static void
5796 frame_highlight (f)
5797 struct frame *f;
5798 {
5799 /* We used to only do this if Vx_no_window_manager was non-nil, but
5800 the ICCCM (section 4.1.6) says that the window's border pixmap
5801 and border pixel are window attributes which are "private to the
5802 client", so we can always change it to whatever we want. */
5803 BLOCK_INPUT;
5804 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5805 f->output_data.x->border_pixel);
5806 UNBLOCK_INPUT;
5807 x_update_cursor (f, 1);
5808 }
5809
5810 static void
5811 frame_unhighlight (f)
5812 struct frame *f;
5813 {
5814 /* We used to only do this if Vx_no_window_manager was non-nil, but
5815 the ICCCM (section 4.1.6) says that the window's border pixmap
5816 and border pixel are window attributes which are "private to the
5817 client", so we can always change it to whatever we want. */
5818 BLOCK_INPUT;
5819 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5820 f->output_data.x->border_tile);
5821 UNBLOCK_INPUT;
5822 x_update_cursor (f, 1);
5823 }
5824
5825 /* The focus has changed. Update the frames as necessary to reflect
5826 the new situation. Note that we can't change the selected frame
5827 here, because the Lisp code we are interrupting might become confused.
5828 Each event gets marked with the frame in which it occurred, so the
5829 Lisp code can tell when the switch took place by examining the events. */
5830
5831 static void
5832 x_new_focus_frame (dpyinfo, frame)
5833 struct x_display_info *dpyinfo;
5834 struct frame *frame;
5835 {
5836 struct frame *old_focus = dpyinfo->x_focus_frame;
5837
5838 if (frame != dpyinfo->x_focus_frame)
5839 {
5840 /* Set this before calling other routines, so that they see
5841 the correct value of x_focus_frame. */
5842 dpyinfo->x_focus_frame = frame;
5843
5844 if (old_focus && old_focus->auto_lower)
5845 x_lower_frame (old_focus);
5846
5847 #if 0
5848 selected_frame = frame;
5849 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5850 selected_frame);
5851 Fselect_window (selected_frame->selected_window);
5852 choose_minibuf_frame ();
5853 #endif /* ! 0 */
5854
5855 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5856 pending_autoraise_frame = dpyinfo->x_focus_frame;
5857 else
5858 pending_autoraise_frame = 0;
5859 }
5860
5861 x_frame_rehighlight (dpyinfo);
5862 }
5863
5864 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5865
5866 void
5867 x_mouse_leave (dpyinfo)
5868 struct x_display_info *dpyinfo;
5869 {
5870 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5871 }
5872
5873 /* The focus has changed, or we have redirected a frame's focus to
5874 another frame (this happens when a frame uses a surrogate
5875 mini-buffer frame). Shift the highlight as appropriate.
5876
5877 The FRAME argument doesn't necessarily have anything to do with which
5878 frame is being highlighted or un-highlighted; we only use it to find
5879 the appropriate X display info. */
5880
5881 static void
5882 XTframe_rehighlight (frame)
5883 struct frame *frame;
5884 {
5885 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5886 }
5887
5888 static void
5889 x_frame_rehighlight (dpyinfo)
5890 struct x_display_info *dpyinfo;
5891 {
5892 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5893
5894 if (dpyinfo->x_focus_frame)
5895 {
5896 dpyinfo->x_highlight_frame
5897 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5898 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5899 : dpyinfo->x_focus_frame);
5900 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
5901 {
5902 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5903 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
5904 }
5905 }
5906 else
5907 dpyinfo->x_highlight_frame = 0;
5908
5909 if (dpyinfo->x_highlight_frame != old_highlight)
5910 {
5911 if (old_highlight)
5912 frame_unhighlight (old_highlight);
5913 if (dpyinfo->x_highlight_frame)
5914 frame_highlight (dpyinfo->x_highlight_frame);
5915 }
5916 }
5917
5918
5919 \f
5920 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5921
5922 /* Initialize mode_switch_bit and modifier_meaning. */
5923 static void
5924 x_find_modifier_meanings (dpyinfo)
5925 struct x_display_info *dpyinfo;
5926 {
5927 int min_code, max_code;
5928 KeySym *syms;
5929 int syms_per_code;
5930 XModifierKeymap *mods;
5931
5932 dpyinfo->meta_mod_mask = 0;
5933 dpyinfo->shift_lock_mask = 0;
5934 dpyinfo->alt_mod_mask = 0;
5935 dpyinfo->super_mod_mask = 0;
5936 dpyinfo->hyper_mod_mask = 0;
5937
5938 #ifdef HAVE_X11R4
5939 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5940 #else
5941 min_code = dpyinfo->display->min_keycode;
5942 max_code = dpyinfo->display->max_keycode;
5943 #endif
5944
5945 syms = XGetKeyboardMapping (dpyinfo->display,
5946 min_code, max_code - min_code + 1,
5947 &syms_per_code);
5948 mods = XGetModifierMapping (dpyinfo->display);
5949
5950 /* Scan the modifier table to see which modifier bits the Meta and
5951 Alt keysyms are on. */
5952 {
5953 int row, col; /* The row and column in the modifier table. */
5954
5955 for (row = 3; row < 8; row++)
5956 for (col = 0; col < mods->max_keypermod; col++)
5957 {
5958 KeyCode code
5959 = mods->modifiermap[(row * mods->max_keypermod) + col];
5960
5961 /* Zeroes are used for filler. Skip them. */
5962 if (code == 0)
5963 continue;
5964
5965 /* Are any of this keycode's keysyms a meta key? */
5966 {
5967 int code_col;
5968
5969 for (code_col = 0; code_col < syms_per_code; code_col++)
5970 {
5971 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5972
5973 switch (sym)
5974 {
5975 case XK_Meta_L:
5976 case XK_Meta_R:
5977 dpyinfo->meta_mod_mask |= (1 << row);
5978 break;
5979
5980 case XK_Alt_L:
5981 case XK_Alt_R:
5982 dpyinfo->alt_mod_mask |= (1 << row);
5983 break;
5984
5985 case XK_Hyper_L:
5986 case XK_Hyper_R:
5987 dpyinfo->hyper_mod_mask |= (1 << row);
5988 break;
5989
5990 case XK_Super_L:
5991 case XK_Super_R:
5992 dpyinfo->super_mod_mask |= (1 << row);
5993 break;
5994
5995 case XK_Shift_Lock:
5996 /* Ignore this if it's not on the lock modifier. */
5997 if ((1 << row) == LockMask)
5998 dpyinfo->shift_lock_mask = LockMask;
5999 break;
6000 }
6001 }
6002 }
6003 }
6004 }
6005
6006 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6007 if (! dpyinfo->meta_mod_mask)
6008 {
6009 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6010 dpyinfo->alt_mod_mask = 0;
6011 }
6012
6013 /* If some keys are both alt and meta,
6014 make them just meta, not alt. */
6015 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6016 {
6017 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6018 }
6019
6020 XFree ((char *) syms);
6021 XFreeModifiermap (mods);
6022 }
6023
6024 /* Convert between the modifier bits X uses and the modifier bits
6025 Emacs uses. */
6026
6027 static unsigned int
6028 x_x_to_emacs_modifiers (dpyinfo, state)
6029 struct x_display_info *dpyinfo;
6030 unsigned int state;
6031 {
6032 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6033 | ((state & ControlMask) ? ctrl_modifier : 0)
6034 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6035 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6036 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6037 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6038 }
6039
6040 static unsigned int
6041 x_emacs_to_x_modifiers (dpyinfo, state)
6042 struct x_display_info *dpyinfo;
6043 unsigned int state;
6044 {
6045 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6046 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6047 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6048 | ((state & shift_modifier) ? ShiftMask : 0)
6049 | ((state & ctrl_modifier) ? ControlMask : 0)
6050 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6051 }
6052
6053 /* Convert a keysym to its name. */
6054
6055 char *
6056 x_get_keysym_name (keysym)
6057 KeySym keysym;
6058 {
6059 char *value;
6060
6061 BLOCK_INPUT;
6062 value = XKeysymToString (keysym);
6063 UNBLOCK_INPUT;
6064
6065 return value;
6066 }
6067
6068
6069 \f
6070 /* Mouse clicks and mouse movement. Rah. */
6071
6072 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6073 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6074 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6075 not force the value into range. */
6076
6077 void
6078 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6079 FRAME_PTR f;
6080 register int pix_x, pix_y;
6081 register int *x, *y;
6082 XRectangle *bounds;
6083 int noclip;
6084 {
6085 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6086 even for negative values. */
6087 if (pix_x < 0)
6088 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6089 if (pix_y < 0)
6090 pix_y -= (f)->output_data.x->line_height - 1;
6091
6092 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6093 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6094
6095 if (bounds)
6096 {
6097 bounds->width = FONT_WIDTH (f->output_data.x->font);
6098 bounds->height = f->output_data.x->line_height;
6099 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6100 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6101 }
6102
6103 if (!noclip)
6104 {
6105 if (pix_x < 0)
6106 pix_x = 0;
6107 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6108 pix_x = FRAME_WINDOW_WIDTH (f);
6109
6110 if (pix_y < 0)
6111 pix_y = 0;
6112 else if (pix_y > f->height)
6113 pix_y = f->height;
6114 }
6115
6116 *x = pix_x;
6117 *y = pix_y;
6118 }
6119
6120
6121 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6122 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6123 can't tell the positions because W's display is not up to date,
6124 return 0. */
6125
6126 int
6127 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6128 struct window *w;
6129 int hpos, vpos;
6130 int *frame_x, *frame_y;
6131 {
6132 int success_p;
6133
6134 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6135 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6136
6137 if (display_completed)
6138 {
6139 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6140 struct glyph *glyph = row->glyphs[TEXT_AREA];
6141 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6142
6143 *frame_y = row->y;
6144 *frame_x = row->x;
6145 while (glyph < end)
6146 {
6147 *frame_x += glyph->pixel_width;
6148 ++glyph;
6149 }
6150
6151 success_p = 1;
6152 }
6153 else
6154 {
6155 *frame_y = *frame_x = 0;
6156 success_p = 0;
6157 }
6158
6159 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6160 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6161 return success_p;
6162 }
6163
6164
6165 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6166
6167 If the event is a button press, then note that we have grabbed
6168 the mouse. */
6169
6170 static Lisp_Object
6171 construct_mouse_click (result, event, f)
6172 struct input_event *result;
6173 XButtonEvent *event;
6174 struct frame *f;
6175 {
6176 /* Make the event type no_event; we'll change that when we decide
6177 otherwise. */
6178 result->kind = mouse_click;
6179 result->code = event->button - Button1;
6180 result->timestamp = event->time;
6181 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6182 event->state)
6183 | (event->type == ButtonRelease
6184 ? up_modifier
6185 : down_modifier));
6186
6187 XSETINT (result->x, event->x);
6188 XSETINT (result->y, event->y);
6189 XSETFRAME (result->frame_or_window, f);
6190 result->arg = Qnil;
6191 return Qnil;
6192 }
6193
6194 \f
6195 /* Function to report a mouse movement to the mainstream Emacs code.
6196 The input handler calls this.
6197
6198 We have received a mouse movement event, which is given in *event.
6199 If the mouse is over a different glyph than it was last time, tell
6200 the mainstream emacs code by setting mouse_moved. If not, ask for
6201 another motion event, so we can check again the next time it moves. */
6202
6203 static XMotionEvent last_mouse_motion_event;
6204 static Lisp_Object last_mouse_motion_frame;
6205
6206 static void
6207 note_mouse_movement (frame, event)
6208 FRAME_PTR frame;
6209 XMotionEvent *event;
6210 {
6211 last_mouse_movement_time = event->time;
6212 last_mouse_motion_event = *event;
6213 XSETFRAME (last_mouse_motion_frame, frame);
6214
6215 if (event->window != FRAME_X_WINDOW (frame))
6216 {
6217 frame->mouse_moved = 1;
6218 last_mouse_scroll_bar = Qnil;
6219 note_mouse_highlight (frame, -1, -1);
6220 }
6221
6222 /* Has the mouse moved off the glyph it was on at the last sighting? */
6223 else if (event->x < last_mouse_glyph.x
6224 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6225 || event->y < last_mouse_glyph.y
6226 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6227 {
6228 frame->mouse_moved = 1;
6229 last_mouse_scroll_bar = Qnil;
6230 note_mouse_highlight (frame, event->x, event->y);
6231 }
6232 }
6233
6234 /* This is used for debugging, to turn off note_mouse_highlight. */
6235
6236 int disable_mouse_highlight;
6237
6238
6239 \f
6240 /************************************************************************
6241 Mouse Face
6242 ************************************************************************/
6243
6244 /* Find the glyph under window-relative coordinates X/Y in window W.
6245 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6246 strings. Return in *HPOS and *VPOS the row and column number of
6247 the glyph found. Return in *AREA the glyph area containing X.
6248 Value is a pointer to the glyph found or null if X/Y is not on
6249 text, or we can't tell because W's current matrix is not up to
6250 date. */
6251
6252 static struct glyph *
6253 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6254 struct window *w;
6255 int x, y;
6256 int *hpos, *vpos, *area;
6257 {
6258 struct glyph *glyph, *end;
6259 struct glyph_row *row = NULL;
6260 int x0, i, left_area_width;
6261
6262 /* Find row containing Y. Give up if some row is not enabled. */
6263 for (i = 0; i < w->current_matrix->nrows; ++i)
6264 {
6265 row = MATRIX_ROW (w->current_matrix, i);
6266 if (!row->enabled_p)
6267 return NULL;
6268 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6269 break;
6270 }
6271
6272 *vpos = i;
6273 *hpos = 0;
6274
6275 /* Give up if Y is not in the window. */
6276 if (i == w->current_matrix->nrows)
6277 return NULL;
6278
6279 /* Get the glyph area containing X. */
6280 if (w->pseudo_window_p)
6281 {
6282 *area = TEXT_AREA;
6283 x0 = 0;
6284 }
6285 else
6286 {
6287 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6288 if (x < left_area_width)
6289 {
6290 *area = LEFT_MARGIN_AREA;
6291 x0 = 0;
6292 }
6293 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6294 {
6295 *area = TEXT_AREA;
6296 x0 = row->x + left_area_width;
6297 }
6298 else
6299 {
6300 *area = RIGHT_MARGIN_AREA;
6301 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6302 }
6303 }
6304
6305 /* Find glyph containing X. */
6306 glyph = row->glyphs[*area];
6307 end = glyph + row->used[*area];
6308 while (glyph < end)
6309 {
6310 if (x < x0 + glyph->pixel_width)
6311 {
6312 if (w->pseudo_window_p)
6313 break;
6314 else if (BUFFERP (glyph->object))
6315 break;
6316 }
6317
6318 x0 += glyph->pixel_width;
6319 ++glyph;
6320 }
6321
6322 if (glyph == end)
6323 return NULL;
6324
6325 *hpos = glyph - row->glyphs[*area];
6326 return glyph;
6327 }
6328
6329
6330 /* Convert frame-relative x/y to coordinates relative to window W.
6331 Takes pseudo-windows into account. */
6332
6333 static void
6334 frame_to_window_pixel_xy (w, x, y)
6335 struct window *w;
6336 int *x, *y;
6337 {
6338 if (w->pseudo_window_p)
6339 {
6340 /* A pseudo-window is always full-width, and starts at the
6341 left edge of the frame, plus a frame border. */
6342 struct frame *f = XFRAME (w->frame);
6343 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6344 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6345 }
6346 else
6347 {
6348 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6349 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6350 }
6351 }
6352
6353
6354 /* Take proper action when mouse has moved to the mode or top line of
6355 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6356 mode line. X is relative to the start of the text display area of
6357 W, so the width of bitmap areas and scroll bars must be subtracted
6358 to get a position relative to the start of the mode line. */
6359
6360 static void
6361 note_mode_line_highlight (w, x, mode_line_p)
6362 struct window *w;
6363 int x, mode_line_p;
6364 {
6365 struct frame *f = XFRAME (w->frame);
6366 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6367 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6368 struct glyph_row *row;
6369
6370 if (mode_line_p)
6371 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6372 else
6373 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6374
6375 if (row->enabled_p)
6376 {
6377 struct glyph *glyph, *end;
6378 Lisp_Object help, map;
6379 int x0;
6380
6381 /* Find the glyph under X. */
6382 glyph = row->glyphs[TEXT_AREA];
6383 end = glyph + row->used[TEXT_AREA];
6384 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6385 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6386 while (glyph < end
6387 && x >= x0 + glyph->pixel_width)
6388 {
6389 x0 += glyph->pixel_width;
6390 ++glyph;
6391 }
6392
6393 if (glyph < end
6394 && STRINGP (glyph->object)
6395 && XSTRING (glyph->object)->intervals
6396 && glyph->charpos >= 0
6397 && glyph->charpos < XSTRING (glyph->object)->size)
6398 {
6399 /* If we're on a string with `help-echo' text property,
6400 arrange for the help to be displayed. This is done by
6401 setting the global variable help_echo to the help string. */
6402 help = Fget_text_property (make_number (glyph->charpos),
6403 Qhelp_echo, glyph->object);
6404 if (!NILP (help))
6405 {
6406 help_echo = help;
6407 XSETWINDOW (help_echo_window, w);
6408 help_echo_object = glyph->object;
6409 help_echo_pos = glyph->charpos;
6410 }
6411
6412 /* Change the mouse pointer according to what is under X/Y. */
6413 map = Fget_text_property (make_number (glyph->charpos),
6414 Qlocal_map, glyph->object);
6415 if (!NILP (Fkeymapp (map)))
6416 cursor = f->output_data.x->nontext_cursor;
6417 else
6418 {
6419 map = Fget_text_property (make_number (glyph->charpos),
6420 Qkeymap, glyph->object);
6421 if (!NILP (Fkeymapp (map)))
6422 cursor = f->output_data.x->nontext_cursor;
6423 }
6424 }
6425 }
6426
6427 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6428 }
6429
6430
6431 /* Take proper action when the mouse has moved to position X, Y on
6432 frame F as regards highlighting characters that have mouse-face
6433 properties. Also de-highlighting chars where the mouse was before.
6434 X and Y can be negative or out of range. */
6435
6436 static void
6437 note_mouse_highlight (f, x, y)
6438 struct frame *f;
6439 int x, y;
6440 {
6441 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6442 int portion;
6443 Lisp_Object window;
6444 struct window *w;
6445
6446 /* When a menu is active, don't highlight because this looks odd. */
6447 #ifdef USE_X_TOOLKIT
6448 if (popup_activated ())
6449 return;
6450 #endif
6451
6452 if (disable_mouse_highlight
6453 || !f->glyphs_initialized_p)
6454 return;
6455
6456 dpyinfo->mouse_face_mouse_x = x;
6457 dpyinfo->mouse_face_mouse_y = y;
6458 dpyinfo->mouse_face_mouse_frame = f;
6459
6460 if (dpyinfo->mouse_face_defer)
6461 return;
6462
6463 if (gc_in_progress)
6464 {
6465 dpyinfo->mouse_face_deferred_gc = 1;
6466 return;
6467 }
6468
6469 /* Which window is that in? */
6470 window = window_from_coordinates (f, x, y, &portion, 1);
6471
6472 /* If we were displaying active text in another window, clear that. */
6473 if (! EQ (window, dpyinfo->mouse_face_window))
6474 clear_mouse_face (dpyinfo);
6475
6476 /* Not on a window -> return. */
6477 if (!WINDOWP (window))
6478 return;
6479
6480 /* Convert to window-relative pixel coordinates. */
6481 w = XWINDOW (window);
6482 frame_to_window_pixel_xy (w, &x, &y);
6483
6484 /* Handle tool-bar window differently since it doesn't display a
6485 buffer. */
6486 if (EQ (window, f->tool_bar_window))
6487 {
6488 note_tool_bar_highlight (f, x, y);
6489 return;
6490 }
6491
6492 if (portion == 1 || portion == 3)
6493 {
6494 /* Mouse is on the mode or top line. */
6495 note_mode_line_highlight (w, x, portion == 1);
6496 return;
6497 }
6498 else
6499 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6500 f->output_data.x->text_cursor);
6501
6502 /* Are we in a window whose display is up to date?
6503 And verify the buffer's text has not changed. */
6504 if (/* Within text portion of the window. */
6505 portion == 0
6506 && EQ (w->window_end_valid, w->buffer)
6507 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6508 && (XFASTINT (w->last_overlay_modified)
6509 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6510 {
6511 int hpos, vpos, pos, i, area;
6512 struct glyph *glyph;
6513
6514 /* Find the glyph under X/Y. */
6515 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6516
6517 /* Clear mouse face if X/Y not over text. */
6518 if (glyph == NULL
6519 || area != TEXT_AREA
6520 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6521 {
6522 clear_mouse_face (dpyinfo);
6523 return;
6524 }
6525
6526 pos = glyph->charpos;
6527 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6528
6529 /* Check for mouse-face and help-echo. */
6530 {
6531 Lisp_Object mouse_face, overlay, position;
6532 Lisp_Object *overlay_vec;
6533 int len, noverlays;
6534 struct buffer *obuf;
6535 int obegv, ozv;
6536
6537 /* If we get an out-of-range value, return now; avoid an error. */
6538 if (pos > BUF_Z (XBUFFER (w->buffer)))
6539 return;
6540
6541 /* Make the window's buffer temporarily current for
6542 overlays_at and compute_char_face. */
6543 obuf = current_buffer;
6544 current_buffer = XBUFFER (w->buffer);
6545 obegv = BEGV;
6546 ozv = ZV;
6547 BEGV = BEG;
6548 ZV = Z;
6549
6550 /* Is this char mouse-active or does it have help-echo? */
6551 XSETINT (position, pos);
6552
6553 /* Put all the overlays we want in a vector in overlay_vec.
6554 Store the length in len. If there are more than 10, make
6555 enough space for all, and try again. */
6556 len = 10;
6557 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6558 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6559 if (noverlays > len)
6560 {
6561 len = noverlays;
6562 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6563 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6564 }
6565
6566 /* Sort overlays into increasing priority order. */
6567 noverlays = sort_overlays (overlay_vec, noverlays, w);
6568
6569 /* Check mouse-face highlighting. */
6570 if (! (EQ (window, dpyinfo->mouse_face_window)
6571 && vpos >= dpyinfo->mouse_face_beg_row
6572 && vpos <= dpyinfo->mouse_face_end_row
6573 && (vpos > dpyinfo->mouse_face_beg_row
6574 || hpos >= dpyinfo->mouse_face_beg_col)
6575 && (vpos < dpyinfo->mouse_face_end_row
6576 || hpos < dpyinfo->mouse_face_end_col
6577 || dpyinfo->mouse_face_past_end)))
6578 {
6579 /* Clear the display of the old active region, if any. */
6580 clear_mouse_face (dpyinfo);
6581
6582 /* Find the highest priority overlay that has a mouse-face prop. */
6583 overlay = Qnil;
6584 for (i = noverlays - 1; i >= 0; --i)
6585 {
6586 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6587 if (!NILP (mouse_face))
6588 {
6589 overlay = overlay_vec[i];
6590 break;
6591 }
6592 }
6593
6594 /* If no overlay applies, get a text property. */
6595 if (NILP (overlay))
6596 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6597
6598 /* Handle the overlay case. */
6599 if (! NILP (overlay))
6600 {
6601 /* Find the range of text around this char that
6602 should be active. */
6603 Lisp_Object before, after;
6604 int ignore;
6605
6606 before = Foverlay_start (overlay);
6607 after = Foverlay_end (overlay);
6608 /* Record this as the current active region. */
6609 fast_find_position (w, XFASTINT (before),
6610 &dpyinfo->mouse_face_beg_col,
6611 &dpyinfo->mouse_face_beg_row,
6612 &dpyinfo->mouse_face_beg_x,
6613 &dpyinfo->mouse_face_beg_y);
6614 dpyinfo->mouse_face_past_end
6615 = !fast_find_position (w, XFASTINT (after),
6616 &dpyinfo->mouse_face_end_col,
6617 &dpyinfo->mouse_face_end_row,
6618 &dpyinfo->mouse_face_end_x,
6619 &dpyinfo->mouse_face_end_y);
6620 dpyinfo->mouse_face_window = window;
6621 dpyinfo->mouse_face_face_id
6622 = face_at_buffer_position (w, pos, 0, 0,
6623 &ignore, pos + 1, 1);
6624
6625 /* Display it as active. */
6626 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6627 }
6628 /* Handle the text property case. */
6629 else if (! NILP (mouse_face))
6630 {
6631 /* Find the range of text around this char that
6632 should be active. */
6633 Lisp_Object before, after, beginning, end;
6634 int ignore;
6635
6636 beginning = Fmarker_position (w->start);
6637 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6638 - XFASTINT (w->window_end_pos)));
6639 before
6640 = Fprevious_single_property_change (make_number (pos + 1),
6641 Qmouse_face,
6642 w->buffer, beginning);
6643 after
6644 = Fnext_single_property_change (position, Qmouse_face,
6645 w->buffer, end);
6646 /* Record this as the current active region. */
6647 fast_find_position (w, XFASTINT (before),
6648 &dpyinfo->mouse_face_beg_col,
6649 &dpyinfo->mouse_face_beg_row,
6650 &dpyinfo->mouse_face_beg_x,
6651 &dpyinfo->mouse_face_beg_y);
6652 dpyinfo->mouse_face_past_end
6653 = !fast_find_position (w, XFASTINT (after),
6654 &dpyinfo->mouse_face_end_col,
6655 &dpyinfo->mouse_face_end_row,
6656 &dpyinfo->mouse_face_end_x,
6657 &dpyinfo->mouse_face_end_y);
6658 dpyinfo->mouse_face_window = window;
6659 dpyinfo->mouse_face_face_id
6660 = face_at_buffer_position (w, pos, 0, 0,
6661 &ignore, pos + 1, 1);
6662
6663 /* Display it as active. */
6664 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6665 }
6666 }
6667
6668 /* Look for a `help-echo' property. */
6669 {
6670 Lisp_Object help, overlay;
6671
6672 /* Check overlays first. */
6673 help = Qnil;
6674 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6675 {
6676 overlay = overlay_vec[i];
6677 help = Foverlay_get (overlay, Qhelp_echo);
6678 }
6679
6680 if (!NILP (help))
6681 {
6682 help_echo = help;
6683 help_echo_window = window;
6684 help_echo_object = overlay;
6685 help_echo_pos = pos;
6686 }
6687 else
6688 {
6689 /* Try text properties. */
6690 if ((STRINGP (glyph->object)
6691 && glyph->charpos >= 0
6692 && glyph->charpos < XSTRING (glyph->object)->size)
6693 || (BUFFERP (glyph->object)
6694 && glyph->charpos >= BEGV
6695 && glyph->charpos < ZV))
6696 help = Fget_text_property (make_number (glyph->charpos),
6697 Qhelp_echo, glyph->object);
6698
6699 if (!NILP (help))
6700 {
6701 help_echo = help;
6702 help_echo_window = window;
6703 help_echo_object = glyph->object;
6704 help_echo_pos = glyph->charpos;
6705 }
6706 }
6707 }
6708
6709 BEGV = obegv;
6710 ZV = ozv;
6711 current_buffer = obuf;
6712 }
6713 }
6714 }
6715
6716 static void
6717 redo_mouse_highlight ()
6718 {
6719 if (!NILP (last_mouse_motion_frame)
6720 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6721 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6722 last_mouse_motion_event.x,
6723 last_mouse_motion_event.y);
6724 }
6725
6726
6727 \f
6728 /***********************************************************************
6729 Tool-bars
6730 ***********************************************************************/
6731
6732 static int x_tool_bar_item P_ ((struct frame *, int, int,
6733 struct glyph **, int *, int *, int *));
6734
6735 /* Tool-bar item index of the item on which a mouse button was pressed
6736 or -1. */
6737
6738 static int last_tool_bar_item;
6739
6740
6741 /* Get information about the tool-bar item at position X/Y on frame F.
6742 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6743 the current matrix of the tool-bar window of F, or NULL if not
6744 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6745 item in F->current_tool_bar_items. Value is
6746
6747 -1 if X/Y is not on a tool-bar item
6748 0 if X/Y is on the same item that was highlighted before.
6749 1 otherwise. */
6750
6751 static int
6752 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6753 struct frame *f;
6754 int x, y;
6755 struct glyph **glyph;
6756 int *hpos, *vpos, *prop_idx;
6757 {
6758 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6759 struct window *w = XWINDOW (f->tool_bar_window);
6760 int area;
6761
6762 /* Find the glyph under X/Y. */
6763 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6764 if (*glyph == NULL)
6765 return -1;
6766
6767 /* Get the start of this tool-bar item's properties in
6768 f->current_tool_bar_items. */
6769 if (!tool_bar_item_info (f, *glyph, prop_idx))
6770 return -1;
6771
6772 /* Is mouse on the highlighted item? */
6773 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6774 && *vpos >= dpyinfo->mouse_face_beg_row
6775 && *vpos <= dpyinfo->mouse_face_end_row
6776 && (*vpos > dpyinfo->mouse_face_beg_row
6777 || *hpos >= dpyinfo->mouse_face_beg_col)
6778 && (*vpos < dpyinfo->mouse_face_end_row
6779 || *hpos < dpyinfo->mouse_face_end_col
6780 || dpyinfo->mouse_face_past_end))
6781 return 0;
6782
6783 return 1;
6784 }
6785
6786
6787 /* Handle mouse button event on the tool-bar of frame F, at
6788 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6789 or ButtonRelase. */
6790
6791 static void
6792 x_handle_tool_bar_click (f, button_event)
6793 struct frame *f;
6794 XButtonEvent *button_event;
6795 {
6796 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6797 struct window *w = XWINDOW (f->tool_bar_window);
6798 int hpos, vpos, prop_idx;
6799 struct glyph *glyph;
6800 Lisp_Object enabled_p;
6801 int x = button_event->x;
6802 int y = button_event->y;
6803
6804 /* If not on the highlighted tool-bar item, return. */
6805 frame_to_window_pixel_xy (w, &x, &y);
6806 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6807 return;
6808
6809 /* If item is disabled, do nothing. */
6810 enabled_p = (XVECTOR (f->current_tool_bar_items)
6811 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6812 if (NILP (enabled_p))
6813 return;
6814
6815 if (button_event->type == ButtonPress)
6816 {
6817 /* Show item in pressed state. */
6818 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6819 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6820 last_tool_bar_item = prop_idx;
6821 }
6822 else
6823 {
6824 Lisp_Object key, frame;
6825 struct input_event event;
6826
6827 /* Show item in released state. */
6828 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6829 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6830
6831 key = (XVECTOR (f->current_tool_bar_items)
6832 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6833
6834 XSETFRAME (frame, f);
6835 event.kind = TOOL_BAR_EVENT;
6836 event.frame_or_window = frame;
6837 event.arg = frame;
6838 kbd_buffer_store_event (&event);
6839
6840 event.kind = TOOL_BAR_EVENT;
6841 event.frame_or_window = frame;
6842 event.arg = key;
6843 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6844 button_event->state);
6845 kbd_buffer_store_event (&event);
6846 last_tool_bar_item = -1;
6847 }
6848 }
6849
6850
6851 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6852 tool-bar window-relative coordinates X/Y. Called from
6853 note_mouse_highlight. */
6854
6855 static void
6856 note_tool_bar_highlight (f, x, y)
6857 struct frame *f;
6858 int x, y;
6859 {
6860 Lisp_Object window = f->tool_bar_window;
6861 struct window *w = XWINDOW (window);
6862 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6863 int hpos, vpos;
6864 struct glyph *glyph;
6865 struct glyph_row *row;
6866 int i;
6867 Lisp_Object enabled_p;
6868 int prop_idx;
6869 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6870 int mouse_down_p, rc;
6871
6872 /* Function note_mouse_highlight is called with negative x(y
6873 values when mouse moves outside of the frame. */
6874 if (x <= 0 || y <= 0)
6875 {
6876 clear_mouse_face (dpyinfo);
6877 return;
6878 }
6879
6880 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6881 if (rc < 0)
6882 {
6883 /* Not on tool-bar item. */
6884 clear_mouse_face (dpyinfo);
6885 return;
6886 }
6887 else if (rc == 0)
6888 /* On same tool-bar item as before. */
6889 goto set_help_echo;
6890
6891 clear_mouse_face (dpyinfo);
6892
6893 /* Mouse is down, but on different tool-bar item? */
6894 mouse_down_p = (dpyinfo->grabbed
6895 && f == last_mouse_frame
6896 && FRAME_LIVE_P (f));
6897 if (mouse_down_p
6898 && last_tool_bar_item != prop_idx)
6899 return;
6900
6901 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6902 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6903
6904 /* If tool-bar item is not enabled, don't highlight it. */
6905 enabled_p = (XVECTOR (f->current_tool_bar_items)
6906 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6907 if (!NILP (enabled_p))
6908 {
6909 /* Compute the x-position of the glyph. In front and past the
6910 image is a space. We include this is the highlighted area. */
6911 row = MATRIX_ROW (w->current_matrix, vpos);
6912 for (i = x = 0; i < hpos; ++i)
6913 x += row->glyphs[TEXT_AREA][i].pixel_width;
6914
6915 /* Record this as the current active region. */
6916 dpyinfo->mouse_face_beg_col = hpos;
6917 dpyinfo->mouse_face_beg_row = vpos;
6918 dpyinfo->mouse_face_beg_x = x;
6919 dpyinfo->mouse_face_beg_y = row->y;
6920 dpyinfo->mouse_face_past_end = 0;
6921
6922 dpyinfo->mouse_face_end_col = hpos + 1;
6923 dpyinfo->mouse_face_end_row = vpos;
6924 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6925 dpyinfo->mouse_face_end_y = row->y;
6926 dpyinfo->mouse_face_window = window;
6927 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6928
6929 /* Display it as active. */
6930 show_mouse_face (dpyinfo, draw);
6931 dpyinfo->mouse_face_image_state = draw;
6932 }
6933
6934 set_help_echo:
6935
6936 /* Set help_echo to a help string.to display for this tool-bar item.
6937 XTread_socket does the rest. */
6938 help_echo_object = help_echo_window = Qnil;
6939 help_echo_pos = -1;
6940 help_echo = (XVECTOR (f->current_tool_bar_items)
6941 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6942 if (NILP (help_echo))
6943 help_echo = (XVECTOR (f->current_tool_bar_items)
6944 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6945 }
6946
6947
6948 \f
6949 /* Find the glyph matrix position of buffer position POS in window W.
6950 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6951 current glyphs must be up to date. If POS is above window start
6952 return (0, 0, 0, 0). If POS is after end of W, return end of
6953 last line in W. */
6954
6955 static int
6956 fast_find_position (w, pos, hpos, vpos, x, y)
6957 struct window *w;
6958 int pos;
6959 int *hpos, *vpos, *x, *y;
6960 {
6961 int i;
6962 int lastcol;
6963 int maybe_next_line_p = 0;
6964 int line_start_position;
6965 int yb = window_text_bottom_y (w);
6966 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6967 struct glyph_row *best_row = row;
6968 int row_vpos = 0, best_row_vpos = 0;
6969 int current_x;
6970
6971 while (row->y < yb)
6972 {
6973 if (row->used[TEXT_AREA])
6974 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6975 else
6976 line_start_position = 0;
6977
6978 if (line_start_position > pos)
6979 break;
6980 /* If the position sought is the end of the buffer,
6981 don't include the blank lines at the bottom of the window. */
6982 else if (line_start_position == pos
6983 && pos == BUF_ZV (XBUFFER (w->buffer)))
6984 {
6985 maybe_next_line_p = 1;
6986 break;
6987 }
6988 else if (line_start_position > 0)
6989 {
6990 best_row = row;
6991 best_row_vpos = row_vpos;
6992 }
6993
6994 if (row->y + row->height >= yb)
6995 break;
6996
6997 ++row;
6998 ++row_vpos;
6999 }
7000
7001 /* Find the right column within BEST_ROW. */
7002 lastcol = 0;
7003 current_x = best_row->x;
7004 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7005 {
7006 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7007 int charpos;
7008
7009 charpos = glyph->charpos;
7010 if (charpos == pos)
7011 {
7012 *hpos = i;
7013 *vpos = best_row_vpos;
7014 *x = current_x;
7015 *y = best_row->y;
7016 return 1;
7017 }
7018 else if (charpos > pos)
7019 break;
7020 else if (charpos > 0)
7021 lastcol = i;
7022
7023 current_x += glyph->pixel_width;
7024 }
7025
7026 /* If we're looking for the end of the buffer,
7027 and we didn't find it in the line we scanned,
7028 use the start of the following line. */
7029 if (maybe_next_line_p)
7030 {
7031 ++best_row;
7032 ++best_row_vpos;
7033 lastcol = 0;
7034 current_x = best_row->x;
7035 }
7036
7037 *vpos = best_row_vpos;
7038 *hpos = lastcol + 1;
7039 *x = current_x;
7040 *y = best_row->y;
7041 return 0;
7042 }
7043
7044
7045 /* Display the active region described by mouse_face_*
7046 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7047
7048 static void
7049 show_mouse_face (dpyinfo, draw)
7050 struct x_display_info *dpyinfo;
7051 enum draw_glyphs_face draw;
7052 {
7053 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7054 struct frame *f = XFRAME (WINDOW_FRAME (w));
7055 int i;
7056 int cursor_off_p = 0;
7057 struct cursor_pos saved_cursor;
7058
7059 saved_cursor = output_cursor;
7060
7061 /* If window is in the process of being destroyed, don't bother
7062 to do anything. */
7063 if (w->current_matrix == NULL)
7064 goto set_x_cursor;
7065
7066 /* Recognize when we are called to operate on rows that don't exist
7067 anymore. This can happen when a window is split. */
7068 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7069 goto set_x_cursor;
7070
7071 set_output_cursor (&w->phys_cursor);
7072
7073 /* Note that mouse_face_beg_row etc. are window relative. */
7074 for (i = dpyinfo->mouse_face_beg_row;
7075 i <= dpyinfo->mouse_face_end_row;
7076 i++)
7077 {
7078 int start_hpos, end_hpos, start_x;
7079 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7080
7081 /* Don't do anything if row doesn't have valid contents. */
7082 if (!row->enabled_p)
7083 continue;
7084
7085 /* For all but the first row, the highlight starts at column 0. */
7086 if (i == dpyinfo->mouse_face_beg_row)
7087 {
7088 start_hpos = dpyinfo->mouse_face_beg_col;
7089 start_x = dpyinfo->mouse_face_beg_x;
7090 }
7091 else
7092 {
7093 start_hpos = 0;
7094 start_x = 0;
7095 }
7096
7097 if (i == dpyinfo->mouse_face_end_row)
7098 end_hpos = dpyinfo->mouse_face_end_col;
7099 else
7100 end_hpos = row->used[TEXT_AREA];
7101
7102 /* If the cursor's in the text we are about to rewrite, turn the
7103 cursor off. */
7104 if (!w->pseudo_window_p
7105 && i == output_cursor.vpos
7106 && output_cursor.hpos >= start_hpos - 1
7107 && output_cursor.hpos <= end_hpos)
7108 {
7109 x_update_window_cursor (w, 0);
7110 cursor_off_p = 1;
7111 }
7112
7113 if (end_hpos > start_hpos)
7114 {
7115 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7116 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7117 start_hpos, end_hpos, draw, NULL, NULL, 0);
7118 }
7119 }
7120
7121 /* If we turned the cursor off, turn it back on. */
7122 if (cursor_off_p)
7123 x_display_cursor (w, 1,
7124 output_cursor.hpos, output_cursor.vpos,
7125 output_cursor.x, output_cursor.y);
7126
7127 output_cursor = saved_cursor;
7128
7129 set_x_cursor:
7130
7131 /* Change the mouse cursor. */
7132 if (draw == DRAW_NORMAL_TEXT)
7133 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7134 f->output_data.x->text_cursor);
7135 else if (draw == DRAW_MOUSE_FACE)
7136 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7137 f->output_data.x->cross_cursor);
7138 else
7139 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7140 f->output_data.x->nontext_cursor);
7141 }
7142
7143 /* Clear out the mouse-highlighted active region.
7144 Redraw it un-highlighted first. */
7145
7146 void
7147 clear_mouse_face (dpyinfo)
7148 struct x_display_info *dpyinfo;
7149 {
7150 if (tip_frame)
7151 return;
7152
7153 if (! NILP (dpyinfo->mouse_face_window))
7154 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7155
7156 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7157 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7158 dpyinfo->mouse_face_window = Qnil;
7159 }
7160
7161
7162 /* Clear any mouse-face on window W. This function is part of the
7163 redisplay interface, and is called from try_window_id and similar
7164 functions to ensure the mouse-highlight is off. */
7165
7166 static void
7167 x_clear_mouse_face (w)
7168 struct window *w;
7169 {
7170 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7171 Lisp_Object window;
7172
7173 XSETWINDOW (window, w);
7174 if (EQ (window, dpyinfo->mouse_face_window))
7175 clear_mouse_face (dpyinfo);
7176 }
7177
7178
7179 /* Just discard the mouse face information for frame F, if any.
7180 This is used when the size of F is changed. */
7181
7182 void
7183 cancel_mouse_face (f)
7184 FRAME_PTR f;
7185 {
7186 Lisp_Object window;
7187 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7188
7189 window = dpyinfo->mouse_face_window;
7190 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7191 {
7192 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7193 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7194 dpyinfo->mouse_face_window = Qnil;
7195 }
7196 }
7197 \f
7198 static struct scroll_bar *x_window_to_scroll_bar ();
7199 static void x_scroll_bar_report_motion ();
7200
7201 /* Return the current position of the mouse.
7202 *fp should be a frame which indicates which display to ask about.
7203
7204 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7205 and *part to the frame, window, and scroll bar part that the mouse
7206 is over. Set *x and *y to the portion and whole of the mouse's
7207 position on the scroll bar.
7208
7209 If the mouse movement started elsewhere, set *fp to the frame the
7210 mouse is on, *bar_window to nil, and *x and *y to the character cell
7211 the mouse is over.
7212
7213 Set *time to the server time-stamp for the time at which the mouse
7214 was at this position.
7215
7216 Don't store anything if we don't have a valid set of values to report.
7217
7218 This clears the mouse_moved flag, so we can wait for the next mouse
7219 movement. */
7220
7221 static void
7222 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7223 FRAME_PTR *fp;
7224 int insist;
7225 Lisp_Object *bar_window;
7226 enum scroll_bar_part *part;
7227 Lisp_Object *x, *y;
7228 unsigned long *time;
7229 {
7230 FRAME_PTR f1;
7231
7232 BLOCK_INPUT;
7233
7234 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7235 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7236 else
7237 {
7238 Window root;
7239 int root_x, root_y;
7240
7241 Window dummy_window;
7242 int dummy;
7243
7244 Lisp_Object frame, tail;
7245
7246 /* Clear the mouse-moved flag for every frame on this display. */
7247 FOR_EACH_FRAME (tail, frame)
7248 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7249 XFRAME (frame)->mouse_moved = 0;
7250
7251 last_mouse_scroll_bar = Qnil;
7252
7253 /* Figure out which root window we're on. */
7254 XQueryPointer (FRAME_X_DISPLAY (*fp),
7255 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7256
7257 /* The root window which contains the pointer. */
7258 &root,
7259
7260 /* Trash which we can't trust if the pointer is on
7261 a different screen. */
7262 &dummy_window,
7263
7264 /* The position on that root window. */
7265 &root_x, &root_y,
7266
7267 /* More trash we can't trust. */
7268 &dummy, &dummy,
7269
7270 /* Modifier keys and pointer buttons, about which
7271 we don't care. */
7272 (unsigned int *) &dummy);
7273
7274 /* Now we have a position on the root; find the innermost window
7275 containing the pointer. */
7276 {
7277 Window win, child;
7278 int win_x, win_y;
7279 int parent_x = 0, parent_y = 0;
7280 int count;
7281
7282 win = root;
7283
7284 /* XTranslateCoordinates can get errors if the window
7285 structure is changing at the same time this function
7286 is running. So at least we must not crash from them. */
7287
7288 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7289
7290 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7291 && FRAME_LIVE_P (last_mouse_frame))
7292 {
7293 /* If mouse was grabbed on a frame, give coords for that frame
7294 even if the mouse is now outside it. */
7295 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7296
7297 /* From-window, to-window. */
7298 root, FRAME_X_WINDOW (last_mouse_frame),
7299
7300 /* From-position, to-position. */
7301 root_x, root_y, &win_x, &win_y,
7302
7303 /* Child of win. */
7304 &child);
7305 f1 = last_mouse_frame;
7306 }
7307 else
7308 {
7309 while (1)
7310 {
7311 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7312
7313 /* From-window, to-window. */
7314 root, win,
7315
7316 /* From-position, to-position. */
7317 root_x, root_y, &win_x, &win_y,
7318
7319 /* Child of win. */
7320 &child);
7321
7322 if (child == None || child == win)
7323 break;
7324
7325 win = child;
7326 parent_x = win_x;
7327 parent_y = win_y;
7328 }
7329
7330 /* Now we know that:
7331 win is the innermost window containing the pointer
7332 (XTC says it has no child containing the pointer),
7333 win_x and win_y are the pointer's position in it
7334 (XTC did this the last time through), and
7335 parent_x and parent_y are the pointer's position in win's parent.
7336 (They are what win_x and win_y were when win was child.
7337 If win is the root window, it has no parent, and
7338 parent_{x,y} are invalid, but that's okay, because we'll
7339 never use them in that case.) */
7340
7341 /* Is win one of our frames? */
7342 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7343 }
7344
7345 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7346 f1 = 0;
7347
7348 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7349
7350 /* If not, is it one of our scroll bars? */
7351 if (! f1)
7352 {
7353 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7354
7355 if (bar)
7356 {
7357 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7358 win_x = parent_x;
7359 win_y = parent_y;
7360 }
7361 }
7362
7363 if (f1 == 0 && insist > 0)
7364 f1 = SELECTED_FRAME ();
7365
7366 if (f1)
7367 {
7368 /* Ok, we found a frame. Store all the values.
7369 last_mouse_glyph is a rectangle used to reduce the
7370 generation of mouse events. To not miss any motion
7371 events, we must divide the frame into rectangles of the
7372 size of the smallest character that could be displayed
7373 on it, i.e. into the same rectangles that matrices on
7374 the frame are divided into. */
7375
7376 #if OLD_REDISPLAY_CODE
7377 int ignore1, ignore2;
7378 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7379 &last_mouse_glyph,
7380 FRAME_X_DISPLAY_INFO (f1)->grabbed
7381 || insist);
7382 #else
7383 {
7384 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7385 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7386 int x = win_x;
7387 int y = win_y;
7388
7389 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7390 round down even for negative values. */
7391 if (x < 0)
7392 x -= width - 1;
7393 if (y < 0)
7394 y -= height - 1;
7395
7396 last_mouse_glyph.width = width;
7397 last_mouse_glyph.height = height;
7398 last_mouse_glyph.x = (x + width - 1) / width * width;
7399 last_mouse_glyph.y = (y + height - 1) / height * height;
7400 }
7401 #endif
7402
7403 *bar_window = Qnil;
7404 *part = 0;
7405 *fp = f1;
7406 XSETINT (*x, win_x);
7407 XSETINT (*y, win_y);
7408 *time = last_mouse_movement_time;
7409 }
7410 }
7411 }
7412
7413 UNBLOCK_INPUT;
7414 }
7415
7416
7417 #ifdef USE_X_TOOLKIT
7418
7419 /* Atimer callback function for TIMER. Called every 0.1s to process
7420 Xt timeouts, if needed. We must avoid calling XtAppPending as
7421 much as possible because that function does an implicit XFlush
7422 that slows us down. */
7423
7424 static void
7425 x_process_timeouts (timer)
7426 struct atimer *timer;
7427 {
7428 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7429 {
7430 BLOCK_INPUT;
7431 while (XtAppPending (Xt_app_con) & XtIMTimer)
7432 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7433 UNBLOCK_INPUT;
7434 }
7435 }
7436
7437 #endif /* USE_X_TOOLKIT */
7438
7439 \f
7440 /* Scroll bar support. */
7441
7442 /* Given an X window ID, find the struct scroll_bar which manages it.
7443 This can be called in GC, so we have to make sure to strip off mark
7444 bits. */
7445
7446 static struct scroll_bar *
7447 x_window_to_scroll_bar (window_id)
7448 Window window_id;
7449 {
7450 Lisp_Object tail;
7451
7452 for (tail = Vframe_list;
7453 XGCTYPE (tail) == Lisp_Cons;
7454 tail = XCDR (tail))
7455 {
7456 Lisp_Object frame, bar, condemned;
7457
7458 frame = XCAR (tail);
7459 /* All elements of Vframe_list should be frames. */
7460 if (! GC_FRAMEP (frame))
7461 abort ();
7462
7463 /* Scan this frame's scroll bar list for a scroll bar with the
7464 right window ID. */
7465 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7466 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7467 /* This trick allows us to search both the ordinary and
7468 condemned scroll bar lists with one loop. */
7469 ! GC_NILP (bar) || (bar = condemned,
7470 condemned = Qnil,
7471 ! GC_NILP (bar));
7472 bar = XSCROLL_BAR (bar)->next)
7473 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7474 return XSCROLL_BAR (bar);
7475 }
7476
7477 return 0;
7478 }
7479
7480
7481 \f
7482 /************************************************************************
7483 Toolkit scroll bars
7484 ************************************************************************/
7485
7486 #if USE_TOOLKIT_SCROLL_BARS
7487
7488 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7489 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7490 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7491 struct scroll_bar *));
7492 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7493 int, int, int));
7494
7495
7496 /* Id of action hook installed for scroll bars. */
7497
7498 static XtActionHookId action_hook_id;
7499
7500 /* Lisp window being scrolled. Set when starting to interact with
7501 a toolkit scroll bar, reset to nil when ending the interaction. */
7502
7503 static Lisp_Object window_being_scrolled;
7504
7505 /* Last scroll bar part sent in xm_scroll_callback. */
7506
7507 static int last_scroll_bar_part;
7508
7509 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7510 that movements of 1/20 of the screen size are mapped to up/down. */
7511
7512 static Boolean xaw3d_arrow_scroll;
7513
7514 /* Whether the drag scrolling maintains the mouse at the top of the
7515 thumb. If not, resizing the thumb needs to be done more carefully
7516 to avoid jerkyness. */
7517
7518 static Boolean xaw3d_pick_top;
7519
7520
7521 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7522 bars are used.. The hook is responsible for detecting when
7523 the user ends an interaction with the scroll bar, and generates
7524 a `end-scroll' scroll_bar_click' event if so. */
7525
7526 static void
7527 xt_action_hook (widget, client_data, action_name, event, params,
7528 num_params)
7529 Widget widget;
7530 XtPointer client_data;
7531 String action_name;
7532 XEvent *event;
7533 String *params;
7534 Cardinal *num_params;
7535 {
7536 int scroll_bar_p;
7537 char *end_action;
7538
7539 #ifdef USE_MOTIF
7540 scroll_bar_p = XmIsScrollBar (widget);
7541 end_action = "Release";
7542 #else /* !USE_MOTIF i.e. use Xaw */
7543 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7544 end_action = "EndScroll";
7545 #endif /* USE_MOTIF */
7546
7547 if (scroll_bar_p
7548 && strcmp (action_name, end_action) == 0
7549 && WINDOWP (window_being_scrolled))
7550 {
7551 struct window *w;
7552
7553 x_send_scroll_bar_event (window_being_scrolled,
7554 scroll_bar_end_scroll, 0, 0);
7555 w = XWINDOW (window_being_scrolled);
7556 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7557 window_being_scrolled = Qnil;
7558 last_scroll_bar_part = -1;
7559
7560 /* Xt timeouts no longer needed. */
7561 toolkit_scroll_bar_interaction = 0;
7562 }
7563 }
7564
7565
7566 /* Send a client message with message type Xatom_Scrollbar for a
7567 scroll action to the frame of WINDOW. PART is a value identifying
7568 the part of the scroll bar that was clicked on. PORTION is the
7569 amount to scroll of a whole of WHOLE. */
7570
7571 static void
7572 x_send_scroll_bar_event (window, part, portion, whole)
7573 Lisp_Object window;
7574 int part, portion, whole;
7575 {
7576 XEvent event;
7577 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7578 struct frame *f = XFRAME (XWINDOW (window)->frame);
7579
7580 /* Construct a ClientMessage event to send to the frame. */
7581 ev->type = ClientMessage;
7582 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7583 ev->display = FRAME_X_DISPLAY (f);
7584 ev->window = FRAME_X_WINDOW (f);
7585 ev->format = 32;
7586 ev->data.l[0] = (long) XFASTINT (window);
7587 ev->data.l[1] = (long) part;
7588 ev->data.l[2] = (long) 0;
7589 ev->data.l[3] = (long) portion;
7590 ev->data.l[4] = (long) whole;
7591
7592 /* Make Xt timeouts work while the scroll bar is active. */
7593 toolkit_scroll_bar_interaction = 1;
7594
7595 /* Setting the event mask to zero means that the message will
7596 be sent to the client that created the window, and if that
7597 window no longer exists, no event will be sent. */
7598 BLOCK_INPUT;
7599 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7600 UNBLOCK_INPUT;
7601 }
7602
7603
7604 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7605 in *IEVENT. */
7606
7607 static void
7608 x_scroll_bar_to_input_event (event, ievent)
7609 XEvent *event;
7610 struct input_event *ievent;
7611 {
7612 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7613 Lisp_Object window;
7614 struct frame *f;
7615
7616 XSETFASTINT (window, ev->data.l[0]);
7617 f = XFRAME (XWINDOW (window)->frame);
7618
7619 ievent->kind = scroll_bar_click;
7620 ievent->frame_or_window = window;
7621 ievent->arg = Qnil;
7622 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7623 ievent->part = ev->data.l[1];
7624 ievent->code = ev->data.l[2];
7625 ievent->x = make_number ((int) ev->data.l[3]);
7626 ievent->y = make_number ((int) ev->data.l[4]);
7627 ievent->modifiers = 0;
7628 }
7629
7630
7631 #ifdef USE_MOTIF
7632
7633 /* Minimum and maximum values used for Motif scroll bars. */
7634
7635 #define XM_SB_MIN 1
7636 #define XM_SB_MAX 10000000
7637 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7638
7639
7640 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7641 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7642 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7643
7644 static void
7645 xm_scroll_callback (widget, client_data, call_data)
7646 Widget widget;
7647 XtPointer client_data, call_data;
7648 {
7649 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7650 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7651 double percent;
7652 int part = -1, whole = 0, portion = 0;
7653
7654 switch (cs->reason)
7655 {
7656 case XmCR_DECREMENT:
7657 bar->dragging = Qnil;
7658 part = scroll_bar_up_arrow;
7659 break;
7660
7661 case XmCR_INCREMENT:
7662 bar->dragging = Qnil;
7663 part = scroll_bar_down_arrow;
7664 break;
7665
7666 case XmCR_PAGE_DECREMENT:
7667 bar->dragging = Qnil;
7668 part = scroll_bar_above_handle;
7669 break;
7670
7671 case XmCR_PAGE_INCREMENT:
7672 bar->dragging = Qnil;
7673 part = scroll_bar_below_handle;
7674 break;
7675
7676 case XmCR_TO_TOP:
7677 bar->dragging = Qnil;
7678 part = scroll_bar_to_top;
7679 break;
7680
7681 case XmCR_TO_BOTTOM:
7682 bar->dragging = Qnil;
7683 part = scroll_bar_to_bottom;
7684 break;
7685
7686 case XmCR_DRAG:
7687 {
7688 int slider_size;
7689 int dragging_down_p = (INTEGERP (bar->dragging)
7690 && XINT (bar->dragging) <= cs->value);
7691
7692 /* Get the slider size. */
7693 BLOCK_INPUT;
7694 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7695 UNBLOCK_INPUT;
7696
7697 /* At the max position of the scroll bar, do a line-wise
7698 movement. Without doing anything, the LessTif scroll bar
7699 calls us with the same cs->value again and again. If we
7700 want to make sure that we can reach the end of the buffer,
7701 we have to do something.
7702
7703 Implementation note: setting bar->dragging always to
7704 cs->value gives a smoother movement at the max position.
7705 Setting it to nil when doing line-wise movement gives
7706 a better slider behavior. */
7707
7708 if (cs->value + slider_size == XM_SB_MAX
7709 || (dragging_down_p
7710 && last_scroll_bar_part == scroll_bar_down_arrow))
7711 {
7712 part = scroll_bar_down_arrow;
7713 bar->dragging = Qnil;
7714 }
7715 else
7716 {
7717 whole = XM_SB_RANGE;
7718 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7719 part = scroll_bar_handle;
7720 bar->dragging = make_number (cs->value);
7721 }
7722 }
7723 break;
7724
7725 case XmCR_VALUE_CHANGED:
7726 break;
7727 };
7728
7729 if (part >= 0)
7730 {
7731 window_being_scrolled = bar->window;
7732 last_scroll_bar_part = part;
7733 x_send_scroll_bar_event (bar->window, part, portion, whole);
7734 }
7735 }
7736
7737
7738 #else /* !USE_MOTIF, i.e. Xaw. */
7739
7740
7741 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7742 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7743 scroll bar struct. CALL_DATA is a pointer to a float saying where
7744 the thumb is. */
7745
7746 static void
7747 xaw_jump_callback (widget, client_data, call_data)
7748 Widget widget;
7749 XtPointer client_data, call_data;
7750 {
7751 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7752 float top = *(float *) call_data;
7753 float shown;
7754 int whole, portion, height;
7755 int part;
7756
7757 /* Get the size of the thumb, a value between 0 and 1. */
7758 BLOCK_INPUT;
7759 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7760 UNBLOCK_INPUT;
7761
7762 whole = 10000000;
7763 portion = shown < 1 ? top * whole : 0;
7764
7765 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7766 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7767 the bottom, so we force the scrolling whenever we see that we're
7768 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7769 we try to ensure that we always stay two pixels away from the
7770 bottom). */
7771 part = scroll_bar_down_arrow;
7772 else
7773 part = scroll_bar_handle;
7774
7775 window_being_scrolled = bar->window;
7776 bar->dragging = make_number (portion);
7777 last_scroll_bar_part = part;
7778 x_send_scroll_bar_event (bar->window, part, portion, whole);
7779 }
7780
7781
7782 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7783 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7784 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7785 the scroll bar. CALL_DATA is an integer specifying the action that
7786 has taken place. It's magnitude is in the range 0..height of the
7787 scroll bar. Negative values mean scroll towards buffer start.
7788 Values < height of scroll bar mean line-wise movement. */
7789
7790 static void
7791 xaw_scroll_callback (widget, client_data, call_data)
7792 Widget widget;
7793 XtPointer client_data, call_data;
7794 {
7795 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7796 int position = (int) call_data;
7797 Dimension height;
7798 int part;
7799
7800 /* Get the height of the scroll bar. */
7801 BLOCK_INPUT;
7802 XtVaGetValues (widget, XtNheight, &height, NULL);
7803 UNBLOCK_INPUT;
7804
7805 if (abs (position) >= height)
7806 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7807
7808 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7809 it maps line-movement to call_data = max(5, height/20). */
7810 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7811 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
7812 else
7813 part = scroll_bar_move_ratio;
7814
7815 window_being_scrolled = bar->window;
7816 bar->dragging = Qnil;
7817 last_scroll_bar_part = part;
7818 x_send_scroll_bar_event (bar->window, part, position, height);
7819 }
7820
7821
7822 #endif /* not USE_MOTIF */
7823
7824
7825 /* Create the widget for scroll bar BAR on frame F. Record the widget
7826 and X window of the scroll bar in BAR. */
7827
7828 static void
7829 x_create_toolkit_scroll_bar (f, bar)
7830 struct frame *f;
7831 struct scroll_bar *bar;
7832 {
7833 Window xwindow;
7834 Widget widget;
7835 Arg av[20];
7836 int ac = 0;
7837 char *scroll_bar_name = "verticalScrollBar";
7838 unsigned long pixel;
7839
7840 BLOCK_INPUT;
7841
7842 #ifdef USE_MOTIF
7843 /* LessTif 0.85, problems:
7844
7845 1. When the mouse if over the scroll bar, the scroll bar will
7846 get keyboard events. I didn't find a way to turn this off.
7847
7848 2. Do we have to explicitly set the cursor to get an arrow
7849 cursor (see below)? */
7850
7851 /* Set resources. Create the widget. */
7852 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7853 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7854 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7855 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7856 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7857 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7858 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7859
7860 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7861 if (pixel != -1)
7862 {
7863 XtSetArg (av[ac], XmNforeground, pixel);
7864 ++ac;
7865 }
7866
7867 pixel = f->output_data.x->scroll_bar_background_pixel;
7868 if (pixel != -1)
7869 {
7870 XtSetArg (av[ac], XmNbackground, pixel);
7871 ++ac;
7872 }
7873
7874 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7875 scroll_bar_name, av, ac);
7876
7877 /* Add one callback for everything that can happen. */
7878 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7879 (XtPointer) bar);
7880 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7881 (XtPointer) bar);
7882 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7883 (XtPointer) bar);
7884 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7885 (XtPointer) bar);
7886 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7887 (XtPointer) bar);
7888 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7889 (XtPointer) bar);
7890 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7891 (XtPointer) bar);
7892
7893 /* Realize the widget. Only after that is the X window created. */
7894 XtRealizeWidget (widget);
7895
7896 /* Set the cursor to an arrow. I didn't find a resource to do that.
7897 And I'm wondering why it hasn't an arrow cursor by default. */
7898 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7899 f->output_data.x->nontext_cursor);
7900
7901 #else /* !USE_MOTIF i.e. use Xaw */
7902
7903 /* Set resources. Create the widget. The background of the
7904 Xaw3d scroll bar widget is a little bit light for my taste.
7905 We don't alter it here to let users change it according
7906 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7907 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7908 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7909 /* For smoother scrolling with Xaw3d -sm */
7910 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7911 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7912
7913 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7914 if (pixel != -1)
7915 {
7916 XtSetArg (av[ac], XtNforeground, pixel);
7917 ++ac;
7918 }
7919
7920 pixel = f->output_data.x->scroll_bar_background_pixel;
7921 if (pixel != -1)
7922 {
7923 XtSetArg (av[ac], XtNbackground, pixel);
7924 ++ac;
7925 }
7926
7927 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7928 f->output_data.x->edit_widget, av, ac);
7929
7930 {
7931 char *initial = "";
7932 char *val = initial;
7933 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7934 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7935 if (val == initial)
7936 { /* ARROW_SCROLL */
7937 xaw3d_arrow_scroll = True;
7938 /* Isn't that just a personal preference ? -sm */
7939 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7940 }
7941 }
7942
7943 /* Define callbacks. */
7944 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7945 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
7946 (XtPointer) bar);
7947
7948 /* Realize the widget. Only after that is the X window created. */
7949 XtRealizeWidget (widget);
7950
7951 #endif /* !USE_MOTIF */
7952
7953 /* Install an action hook that let's us detect when the user
7954 finishes interacting with a scroll bar. */
7955 if (action_hook_id == 0)
7956 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7957
7958 /* Remember X window and widget in the scroll bar vector. */
7959 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7960 xwindow = XtWindow (widget);
7961 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7962
7963 UNBLOCK_INPUT;
7964 }
7965
7966
7967 /* Set the thumb size and position of scroll bar BAR. We are currently
7968 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7969
7970 static void
7971 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7972 struct scroll_bar *bar;
7973 int portion, position, whole;
7974 {
7975 float top, shown;
7976 Widget widget = SCROLL_BAR_X_WIDGET (bar);
7977
7978 if (whole == 0)
7979 top = 0, shown = 1;
7980 else
7981 {
7982 top = (float) position / whole;
7983 shown = (float) portion / whole;
7984 }
7985
7986 BLOCK_INPUT;
7987
7988 #ifdef USE_MOTIF
7989 {
7990 int size, value;
7991 Boolean arrow1_selected, arrow2_selected;
7992 unsigned char flags;
7993 XmScrollBarWidget sb;
7994
7995 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7996 is the scroll bar's maximum and MIN is the scroll bar's minimum
7997 value. */
7998 size = shown * XM_SB_RANGE;
7999 size = min (size, XM_SB_RANGE);
8000 size = max (size, 1);
8001
8002 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8003 value = top * XM_SB_RANGE;
8004 value = min (value, XM_SB_MAX - size);
8005 value = max (value, XM_SB_MIN);
8006
8007 /* LessTif: Calling XmScrollBarSetValues after an increment or
8008 decrement turns off auto-repeat LessTif-internally. This can
8009 be seen in ScrollBar.c which resets Arrow1Selected and
8010 Arrow2Selected. It also sets internal flags so that LessTif
8011 believes the mouse is in the slider. We either have to change
8012 our code, or work around that by accessing private data. */
8013
8014 sb = (XmScrollBarWidget) widget;
8015 arrow1_selected = sb->scrollBar.arrow1_selected;
8016 arrow2_selected = sb->scrollBar.arrow2_selected;
8017 flags = sb->scrollBar.flags;
8018
8019 if (NILP (bar->dragging))
8020 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8021 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8022 /* This has the negative side effect that the slider value is
8023 not what it would be if we scrolled here using line-wise or
8024 page-wise movement. */
8025 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8026 else
8027 {
8028 /* If currently dragging, only update the slider size.
8029 This reduces flicker effects. */
8030 int old_value, old_size, increment, page_increment;
8031
8032 XmScrollBarGetValues (widget, &old_value, &old_size,
8033 &increment, &page_increment);
8034 XmScrollBarSetValues (widget, old_value,
8035 min (size, XM_SB_RANGE - old_value),
8036 0, 0, False);
8037 }
8038
8039 sb->scrollBar.arrow1_selected = arrow1_selected;
8040 sb->scrollBar.arrow2_selected = arrow2_selected;
8041 sb->scrollBar.flags = flags;
8042 }
8043 #else /* !USE_MOTIF i.e. use Xaw */
8044 {
8045 float old_top, old_shown;
8046 Dimension height;
8047 XtVaGetValues (widget,
8048 XtNtopOfThumb, &old_top,
8049 XtNshown, &old_shown,
8050 XtNheight, &height,
8051 NULL);
8052
8053 /* Massage the top+shown values. */
8054 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8055 top = max (0, min (1, top));
8056 else
8057 top = old_top;
8058 /* Keep two pixels available for moving the thumb down. */
8059 shown = max (0, min (1 - top - (2.0 / height), shown));
8060
8061 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8062 check that your system's configuration file contains a define
8063 for `NARROWPROTO'. See s/freebsd.h for an example. */
8064 if (top != old_top || shown != old_shown)
8065 {
8066 if (NILP (bar->dragging))
8067 XawScrollbarSetThumb (widget, top, shown);
8068 else
8069 {
8070 #ifdef HAVE_XAW3D
8071 ScrollbarWidget sb = (ScrollbarWidget) widget;
8072 int scroll_mode = 0;
8073
8074 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8075 if (xaw3d_arrow_scroll)
8076 {
8077 /* Xaw3d stupidly ignores resize requests while dragging
8078 so we have to make it believe it's not in dragging mode. */
8079 scroll_mode = sb->scrollbar.scroll_mode;
8080 if (scroll_mode == 2)
8081 sb->scrollbar.scroll_mode = 0;
8082 }
8083 #endif
8084 /* Try to make the scrolling a tad smoother. */
8085 if (!xaw3d_pick_top)
8086 shown = min (shown, old_shown);
8087
8088 XawScrollbarSetThumb (widget, top, shown);
8089
8090 #ifdef HAVE_XAW3D
8091 if (xaw3d_arrow_scroll && scroll_mode == 2)
8092 sb->scrollbar.scroll_mode = scroll_mode;
8093 #endif
8094 }
8095 }
8096 }
8097 #endif /* !USE_MOTIF */
8098
8099 UNBLOCK_INPUT;
8100 }
8101
8102 #endif /* USE_TOOLKIT_SCROLL_BARS */
8103
8104
8105 \f
8106 /************************************************************************
8107 Scroll bars, general
8108 ************************************************************************/
8109
8110 /* Create a scroll bar and return the scroll bar vector for it. W is
8111 the Emacs window on which to create the scroll bar. TOP, LEFT,
8112 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8113 scroll bar. */
8114
8115 static struct scroll_bar *
8116 x_scroll_bar_create (w, top, left, width, height)
8117 struct window *w;
8118 int top, left, width, height;
8119 {
8120 struct frame *f = XFRAME (w->frame);
8121 struct scroll_bar *bar
8122 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8123
8124 BLOCK_INPUT;
8125
8126 #if USE_TOOLKIT_SCROLL_BARS
8127 x_create_toolkit_scroll_bar (f, bar);
8128 #else /* not USE_TOOLKIT_SCROLL_BARS */
8129 {
8130 XSetWindowAttributes a;
8131 unsigned long mask;
8132 Window window;
8133
8134 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8135 if (a.background_pixel == -1)
8136 a.background_pixel = f->output_data.x->background_pixel;
8137
8138 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8139 | ButtonMotionMask | PointerMotionHintMask
8140 | ExposureMask);
8141 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8142
8143 mask = (CWBackPixel | CWEventMask | CWCursor);
8144
8145 /* Clear the area of W that will serve as a scroll bar. This is
8146 for the case that a window has been split horizontally. In
8147 this case, no clear_frame is generated to reduce flickering. */
8148 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8149 left, top, width,
8150 window_box_height (w), False);
8151
8152 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8153 /* Position and size of scroll bar. */
8154 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8155 top,
8156 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8157 height,
8158 /* Border width, depth, class, and visual. */
8159 0,
8160 CopyFromParent,
8161 CopyFromParent,
8162 CopyFromParent,
8163 /* Attributes. */
8164 mask, &a);
8165 SET_SCROLL_BAR_X_WINDOW (bar, window);
8166 }
8167 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8168
8169 XSETWINDOW (bar->window, w);
8170 XSETINT (bar->top, top);
8171 XSETINT (bar->left, left);
8172 XSETINT (bar->width, width);
8173 XSETINT (bar->height, height);
8174 XSETINT (bar->start, 0);
8175 XSETINT (bar->end, 0);
8176 bar->dragging = Qnil;
8177
8178 /* Add bar to its frame's list of scroll bars. */
8179 bar->next = FRAME_SCROLL_BARS (f);
8180 bar->prev = Qnil;
8181 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8182 if (!NILP (bar->next))
8183 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8184
8185 /* Map the window/widget. */
8186 #if USE_TOOLKIT_SCROLL_BARS
8187 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8188 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8189 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8190 top,
8191 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8192 height, 0);
8193 #else /* not USE_TOOLKIT_SCROLL_BARS */
8194 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8195 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8196
8197 UNBLOCK_INPUT;
8198 return bar;
8199 }
8200
8201
8202 /* Draw BAR's handle in the proper position.
8203
8204 If the handle is already drawn from START to END, don't bother
8205 redrawing it, unless REBUILD is non-zero; in that case, always
8206 redraw it. (REBUILD is handy for drawing the handle after expose
8207 events.)
8208
8209 Normally, we want to constrain the start and end of the handle to
8210 fit inside its rectangle, but if the user is dragging the scroll
8211 bar handle, we want to let them drag it down all the way, so that
8212 the bar's top is as far down as it goes; otherwise, there's no way
8213 to move to the very end of the buffer. */
8214
8215 #ifndef USE_TOOLKIT_SCROLL_BARS
8216
8217 static void
8218 x_scroll_bar_set_handle (bar, start, end, rebuild)
8219 struct scroll_bar *bar;
8220 int start, end;
8221 int rebuild;
8222 {
8223 int dragging = ! NILP (bar->dragging);
8224 Window w = SCROLL_BAR_X_WINDOW (bar);
8225 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8226 GC gc = f->output_data.x->normal_gc;
8227
8228 /* If the display is already accurate, do nothing. */
8229 if (! rebuild
8230 && start == XINT (bar->start)
8231 && end == XINT (bar->end))
8232 return;
8233
8234 BLOCK_INPUT;
8235
8236 {
8237 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8238 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8239 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8240
8241 /* Make sure the values are reasonable, and try to preserve
8242 the distance between start and end. */
8243 {
8244 int length = end - start;
8245
8246 if (start < 0)
8247 start = 0;
8248 else if (start > top_range)
8249 start = top_range;
8250 end = start + length;
8251
8252 if (end < start)
8253 end = start;
8254 else if (end > top_range && ! dragging)
8255 end = top_range;
8256 }
8257
8258 /* Store the adjusted setting in the scroll bar. */
8259 XSETINT (bar->start, start);
8260 XSETINT (bar->end, end);
8261
8262 /* Clip the end position, just for display. */
8263 if (end > top_range)
8264 end = top_range;
8265
8266 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8267 below top positions, to make sure the handle is always at least
8268 that many pixels tall. */
8269 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8270
8271 /* Draw the empty space above the handle. Note that we can't clear
8272 zero-height areas; that means "clear to end of window." */
8273 if (0 < start)
8274 XClearArea (FRAME_X_DISPLAY (f), w,
8275
8276 /* x, y, width, height, and exposures. */
8277 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8278 VERTICAL_SCROLL_BAR_TOP_BORDER,
8279 inside_width, start,
8280 False);
8281
8282 /* Change to proper foreground color if one is specified. */
8283 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8284 XSetForeground (FRAME_X_DISPLAY (f), gc,
8285 f->output_data.x->scroll_bar_foreground_pixel);
8286
8287 /* Draw the handle itself. */
8288 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8289
8290 /* x, y, width, height */
8291 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8292 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8293 inside_width, end - start);
8294
8295 /* Restore the foreground color of the GC if we changed it above. */
8296 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8297 XSetForeground (FRAME_X_DISPLAY (f), gc,
8298 f->output_data.x->foreground_pixel);
8299
8300 /* Draw the empty space below the handle. Note that we can't
8301 clear zero-height areas; that means "clear to end of window." */
8302 if (end < inside_height)
8303 XClearArea (FRAME_X_DISPLAY (f), w,
8304
8305 /* x, y, width, height, and exposures. */
8306 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8307 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8308 inside_width, inside_height - end,
8309 False);
8310
8311 }
8312
8313 UNBLOCK_INPUT;
8314 }
8315
8316 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8317
8318 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8319 nil. */
8320
8321 static void
8322 x_scroll_bar_remove (bar)
8323 struct scroll_bar *bar;
8324 {
8325 BLOCK_INPUT;
8326
8327 #if USE_TOOLKIT_SCROLL_BARS
8328 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8329 #else /* not USE_TOOLKIT_SCROLL_BARS */
8330 {
8331 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8332 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8333 }
8334 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8335
8336 /* Disassociate this scroll bar from its window. */
8337 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8338
8339 UNBLOCK_INPUT;
8340 }
8341
8342
8343 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8344 that we are displaying PORTION characters out of a total of WHOLE
8345 characters, starting at POSITION. If WINDOW has no scroll bar,
8346 create one. */
8347
8348 static void
8349 XTset_vertical_scroll_bar (w, portion, whole, position)
8350 struct window *w;
8351 int portion, whole, position;
8352 {
8353 struct frame *f = XFRAME (w->frame);
8354 struct scroll_bar *bar;
8355 int top, height, left, sb_left, width, sb_width;
8356 int window_x, window_y, window_width, window_height;
8357
8358 /* Get window dimensions. */
8359 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8360 top = window_y;
8361 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8362 height = window_height;
8363
8364 /* Compute the left edge of the scroll bar area. */
8365 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8366 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8367 else
8368 left = XFASTINT (w->left);
8369 left *= CANON_X_UNIT (f);
8370 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8371
8372 /* Compute the width of the scroll bar which might be less than
8373 the width of the area reserved for the scroll bar. */
8374 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8375 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8376 else
8377 sb_width = width;
8378
8379 /* Compute the left edge of the scroll bar. */
8380 #ifdef USE_TOOLKIT_SCROLL_BARS
8381 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8382 sb_left = left + width - sb_width - (width - sb_width) / 2;
8383 else
8384 sb_left = left + (width - sb_width) / 2;
8385 #else
8386 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8387 sb_left = left + width - sb_width;
8388 else
8389 sb_left = left;
8390 #endif
8391
8392 /* Does the scroll bar exist yet? */
8393 if (NILP (w->vertical_scroll_bar))
8394 {
8395 BLOCK_INPUT;
8396 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8397 left, top, width, height, False);
8398 UNBLOCK_INPUT;
8399 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8400 }
8401 else
8402 {
8403 /* It may just need to be moved and resized. */
8404 unsigned int mask = 0;
8405
8406 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8407
8408 BLOCK_INPUT;
8409
8410 if (sb_left != XINT (bar->left))
8411 mask |= CWX;
8412 if (top != XINT (bar->top))
8413 mask |= CWY;
8414 if (sb_width != XINT (bar->width))
8415 mask |= CWWidth;
8416 if (height != XINT (bar->height))
8417 mask |= CWHeight;
8418
8419 #ifdef USE_TOOLKIT_SCROLL_BARS
8420
8421 /* Since toolkit scroll bars are smaller than the space reserved
8422 for them on the frame, we have to clear "under" them. */
8423 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8424 left, top, width, height, False);
8425
8426 /* Move/size the scroll bar widget. */
8427 if (mask)
8428 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8429 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8430 top,
8431 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8432 height, 0);
8433
8434 #else /* not USE_TOOLKIT_SCROLL_BARS */
8435
8436 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8437 {
8438 /* Clear areas not covered by the scroll bar. This makes sure a
8439 previous mode line display is cleared after C-x 2 C-x 1, for
8440 example. Non-toolkit scroll bars are as wide as the area
8441 reserved for scroll bars - trim at both sides. */
8442 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8443 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8444 height, False);
8445 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8446 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8447 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8448 height, False);
8449 }
8450
8451 /* Move/size the scroll bar window. */
8452 if (mask)
8453 {
8454 XWindowChanges wc;
8455
8456 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8457 wc.y = top;
8458 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8459 wc.height = height;
8460 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8461 mask, &wc);
8462 }
8463
8464 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8465
8466 /* Remember new settings. */
8467 XSETINT (bar->left, sb_left);
8468 XSETINT (bar->top, top);
8469 XSETINT (bar->width, sb_width);
8470 XSETINT (bar->height, height);
8471
8472 UNBLOCK_INPUT;
8473 }
8474
8475 #if USE_TOOLKIT_SCROLL_BARS
8476 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8477 #else /* not USE_TOOLKIT_SCROLL_BARS */
8478 /* Set the scroll bar's current state, unless we're currently being
8479 dragged. */
8480 if (NILP (bar->dragging))
8481 {
8482 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8483
8484 if (whole == 0)
8485 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8486 else
8487 {
8488 int start = ((double) position * top_range) / whole;
8489 int end = ((double) (position + portion) * top_range) / whole;
8490 x_scroll_bar_set_handle (bar, start, end, 0);
8491 }
8492 }
8493 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8494
8495 XSETVECTOR (w->vertical_scroll_bar, bar);
8496 }
8497
8498
8499 /* The following three hooks are used when we're doing a thorough
8500 redisplay of the frame. We don't explicitly know which scroll bars
8501 are going to be deleted, because keeping track of when windows go
8502 away is a real pain - "Can you say set-window-configuration, boys
8503 and girls?" Instead, we just assert at the beginning of redisplay
8504 that *all* scroll bars are to be removed, and then save a scroll bar
8505 from the fiery pit when we actually redisplay its window. */
8506
8507 /* Arrange for all scroll bars on FRAME to be removed at the next call
8508 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8509 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8510
8511 static void
8512 XTcondemn_scroll_bars (frame)
8513 FRAME_PTR frame;
8514 {
8515 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8516 while (! NILP (FRAME_SCROLL_BARS (frame)))
8517 {
8518 Lisp_Object bar;
8519 bar = FRAME_SCROLL_BARS (frame);
8520 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8521 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8522 XSCROLL_BAR (bar)->prev = Qnil;
8523 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8524 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8525 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8526 }
8527 }
8528
8529 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8530 Note that WINDOW isn't necessarily condemned at all. */
8531 static void
8532 XTredeem_scroll_bar (window)
8533 struct window *window;
8534 {
8535 struct scroll_bar *bar;
8536
8537 /* We can't redeem this window's scroll bar if it doesn't have one. */
8538 if (NILP (window->vertical_scroll_bar))
8539 abort ();
8540
8541 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8542
8543 /* Unlink it from the condemned list. */
8544 {
8545 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8546
8547 if (NILP (bar->prev))
8548 {
8549 /* If the prev pointer is nil, it must be the first in one of
8550 the lists. */
8551 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8552 /* It's not condemned. Everything's fine. */
8553 return;
8554 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8555 window->vertical_scroll_bar))
8556 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8557 else
8558 /* If its prev pointer is nil, it must be at the front of
8559 one or the other! */
8560 abort ();
8561 }
8562 else
8563 XSCROLL_BAR (bar->prev)->next = bar->next;
8564
8565 if (! NILP (bar->next))
8566 XSCROLL_BAR (bar->next)->prev = bar->prev;
8567
8568 bar->next = FRAME_SCROLL_BARS (f);
8569 bar->prev = Qnil;
8570 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8571 if (! NILP (bar->next))
8572 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8573 }
8574 }
8575
8576 /* Remove all scroll bars on FRAME that haven't been saved since the
8577 last call to `*condemn_scroll_bars_hook'. */
8578
8579 static void
8580 XTjudge_scroll_bars (f)
8581 FRAME_PTR f;
8582 {
8583 Lisp_Object bar, next;
8584
8585 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8586
8587 /* Clear out the condemned list now so we won't try to process any
8588 more events on the hapless scroll bars. */
8589 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8590
8591 for (; ! NILP (bar); bar = next)
8592 {
8593 struct scroll_bar *b = XSCROLL_BAR (bar);
8594
8595 x_scroll_bar_remove (b);
8596
8597 next = b->next;
8598 b->next = b->prev = Qnil;
8599 }
8600
8601 /* Now there should be no references to the condemned scroll bars,
8602 and they should get garbage-collected. */
8603 }
8604
8605
8606 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8607 is a no-op when using toolkit scroll bars.
8608
8609 This may be called from a signal handler, so we have to ignore GC
8610 mark bits. */
8611
8612 static void
8613 x_scroll_bar_expose (bar, event)
8614 struct scroll_bar *bar;
8615 XEvent *event;
8616 {
8617 #ifndef USE_TOOLKIT_SCROLL_BARS
8618
8619 Window w = SCROLL_BAR_X_WINDOW (bar);
8620 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8621 GC gc = f->output_data.x->normal_gc;
8622 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8623
8624 BLOCK_INPUT;
8625
8626 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8627
8628 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8629 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8630
8631 /* x, y, width, height */
8632 0, 0,
8633 XINT (bar->width) - 1 - width_trim - width_trim,
8634 XINT (bar->height) - 1);
8635
8636 UNBLOCK_INPUT;
8637
8638 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8639 }
8640
8641 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8642 is set to something other than no_event, it is enqueued.
8643
8644 This may be called from a signal handler, so we have to ignore GC
8645 mark bits. */
8646
8647 #ifndef USE_TOOLKIT_SCROLL_BARS
8648
8649 static void
8650 x_scroll_bar_handle_click (bar, event, emacs_event)
8651 struct scroll_bar *bar;
8652 XEvent *event;
8653 struct input_event *emacs_event;
8654 {
8655 if (! GC_WINDOWP (bar->window))
8656 abort ();
8657
8658 emacs_event->kind = scroll_bar_click;
8659 emacs_event->code = event->xbutton.button - Button1;
8660 emacs_event->modifiers
8661 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8662 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8663 event->xbutton.state)
8664 | (event->type == ButtonRelease
8665 ? up_modifier
8666 : down_modifier));
8667 emacs_event->frame_or_window = bar->window;
8668 emacs_event->arg = Qnil;
8669 emacs_event->timestamp = event->xbutton.time;
8670 {
8671 #if 0
8672 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8673 int internal_height
8674 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8675 #endif
8676 int top_range
8677 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8678 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8679
8680 if (y < 0) y = 0;
8681 if (y > top_range) y = top_range;
8682
8683 if (y < XINT (bar->start))
8684 emacs_event->part = scroll_bar_above_handle;
8685 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8686 emacs_event->part = scroll_bar_handle;
8687 else
8688 emacs_event->part = scroll_bar_below_handle;
8689
8690 /* Just because the user has clicked on the handle doesn't mean
8691 they want to drag it. Lisp code needs to be able to decide
8692 whether or not we're dragging. */
8693 #if 0
8694 /* If the user has just clicked on the handle, record where they're
8695 holding it. */
8696 if (event->type == ButtonPress
8697 && emacs_event->part == scroll_bar_handle)
8698 XSETINT (bar->dragging, y - XINT (bar->start));
8699 #endif
8700
8701 /* If the user has released the handle, set it to its final position. */
8702 if (event->type == ButtonRelease
8703 && ! NILP (bar->dragging))
8704 {
8705 int new_start = y - XINT (bar->dragging);
8706 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8707
8708 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8709 bar->dragging = Qnil;
8710 }
8711
8712 /* Same deal here as the other #if 0. */
8713 #if 0
8714 /* Clicks on the handle are always reported as occurring at the top of
8715 the handle. */
8716 if (emacs_event->part == scroll_bar_handle)
8717 emacs_event->x = bar->start;
8718 else
8719 XSETINT (emacs_event->x, y);
8720 #else
8721 XSETINT (emacs_event->x, y);
8722 #endif
8723
8724 XSETINT (emacs_event->y, top_range);
8725 }
8726 }
8727
8728 /* Handle some mouse motion while someone is dragging the scroll bar.
8729
8730 This may be called from a signal handler, so we have to ignore GC
8731 mark bits. */
8732
8733 static void
8734 x_scroll_bar_note_movement (bar, event)
8735 struct scroll_bar *bar;
8736 XEvent *event;
8737 {
8738 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8739
8740 last_mouse_movement_time = event->xmotion.time;
8741
8742 f->mouse_moved = 1;
8743 XSETVECTOR (last_mouse_scroll_bar, bar);
8744
8745 /* If we're dragging the bar, display it. */
8746 if (! GC_NILP (bar->dragging))
8747 {
8748 /* Where should the handle be now? */
8749 int new_start = event->xmotion.y - XINT (bar->dragging);
8750
8751 if (new_start != XINT (bar->start))
8752 {
8753 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8754
8755 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8756 }
8757 }
8758 }
8759
8760 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8761
8762 /* Return information to the user about the current position of the mouse
8763 on the scroll bar. */
8764
8765 static void
8766 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8767 FRAME_PTR *fp;
8768 Lisp_Object *bar_window;
8769 enum scroll_bar_part *part;
8770 Lisp_Object *x, *y;
8771 unsigned long *time;
8772 {
8773 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8774 Window w = SCROLL_BAR_X_WINDOW (bar);
8775 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8776 int win_x, win_y;
8777 Window dummy_window;
8778 int dummy_coord;
8779 unsigned int dummy_mask;
8780
8781 BLOCK_INPUT;
8782
8783 /* Get the mouse's position relative to the scroll bar window, and
8784 report that. */
8785 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8786
8787 /* Root, child, root x and root y. */
8788 &dummy_window, &dummy_window,
8789 &dummy_coord, &dummy_coord,
8790
8791 /* Position relative to scroll bar. */
8792 &win_x, &win_y,
8793
8794 /* Mouse buttons and modifier keys. */
8795 &dummy_mask))
8796 ;
8797 else
8798 {
8799 #if 0
8800 int inside_height
8801 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8802 #endif
8803 int top_range
8804 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8805
8806 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8807
8808 if (! NILP (bar->dragging))
8809 win_y -= XINT (bar->dragging);
8810
8811 if (win_y < 0)
8812 win_y = 0;
8813 if (win_y > top_range)
8814 win_y = top_range;
8815
8816 *fp = f;
8817 *bar_window = bar->window;
8818
8819 if (! NILP (bar->dragging))
8820 *part = scroll_bar_handle;
8821 else if (win_y < XINT (bar->start))
8822 *part = scroll_bar_above_handle;
8823 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8824 *part = scroll_bar_handle;
8825 else
8826 *part = scroll_bar_below_handle;
8827
8828 XSETINT (*x, win_y);
8829 XSETINT (*y, top_range);
8830
8831 f->mouse_moved = 0;
8832 last_mouse_scroll_bar = Qnil;
8833 }
8834
8835 *time = last_mouse_movement_time;
8836
8837 UNBLOCK_INPUT;
8838 }
8839
8840
8841 /* The screen has been cleared so we may have changed foreground or
8842 background colors, and the scroll bars may need to be redrawn.
8843 Clear out the scroll bars, and ask for expose events, so we can
8844 redraw them. */
8845
8846 void
8847 x_scroll_bar_clear (f)
8848 FRAME_PTR f;
8849 {
8850 #ifndef USE_TOOLKIT_SCROLL_BARS
8851 Lisp_Object bar;
8852
8853 /* We can have scroll bars even if this is 0,
8854 if we just turned off scroll bar mode.
8855 But in that case we should not clear them. */
8856 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8857 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8858 bar = XSCROLL_BAR (bar)->next)
8859 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8860 0, 0, 0, 0, True);
8861 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8862 }
8863
8864 /* This processes Expose events from the menu-bar specific X event
8865 loop in xmenu.c. This allows to redisplay the frame if necessary
8866 when handling menu-bar or pop-up items. */
8867
8868 int
8869 process_expose_from_menu (event)
8870 XEvent event;
8871 {
8872 FRAME_PTR f;
8873 struct x_display_info *dpyinfo;
8874 int frame_exposed_p = 0;
8875
8876 BLOCK_INPUT;
8877
8878 dpyinfo = x_display_info_for_display (event.xexpose.display);
8879 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8880 if (f)
8881 {
8882 if (f->async_visible == 0)
8883 {
8884 f->async_visible = 1;
8885 f->async_iconified = 0;
8886 f->output_data.x->has_been_visible = 1;
8887 SET_FRAME_GARBAGED (f);
8888 }
8889 else
8890 {
8891 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8892 event.xexpose.x, event.xexpose.y,
8893 event.xexpose.width, event.xexpose.height);
8894 frame_exposed_p = 1;
8895 }
8896 }
8897 else
8898 {
8899 struct scroll_bar *bar
8900 = x_window_to_scroll_bar (event.xexpose.window);
8901
8902 if (bar)
8903 x_scroll_bar_expose (bar, &event);
8904 }
8905
8906 UNBLOCK_INPUT;
8907 return frame_exposed_p;
8908 }
8909 \f
8910 /* Define a queue to save up SelectionRequest events for later handling. */
8911
8912 struct selection_event_queue
8913 {
8914 XEvent event;
8915 struct selection_event_queue *next;
8916 };
8917
8918 static struct selection_event_queue *queue;
8919
8920 /* Nonzero means queue up certain events--don't process them yet. */
8921
8922 static int x_queue_selection_requests;
8923
8924 /* Queue up an X event *EVENT, to be processed later. */
8925
8926 static void
8927 x_queue_event (f, event)
8928 FRAME_PTR f;
8929 XEvent *event;
8930 {
8931 struct selection_event_queue *queue_tmp
8932 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
8933
8934 if (queue_tmp != NULL)
8935 {
8936 queue_tmp->event = *event;
8937 queue_tmp->next = queue;
8938 queue = queue_tmp;
8939 }
8940 }
8941
8942 /* Take all the queued events and put them back
8943 so that they get processed afresh. */
8944
8945 static void
8946 x_unqueue_events (display)
8947 Display *display;
8948 {
8949 while (queue != NULL)
8950 {
8951 struct selection_event_queue *queue_tmp = queue;
8952 XPutBackEvent (display, &queue_tmp->event);
8953 queue = queue_tmp->next;
8954 xfree ((char *)queue_tmp);
8955 }
8956 }
8957
8958 /* Start queuing SelectionRequest events. */
8959
8960 void
8961 x_start_queuing_selection_requests (display)
8962 Display *display;
8963 {
8964 x_queue_selection_requests++;
8965 }
8966
8967 /* Stop queuing SelectionRequest events. */
8968
8969 void
8970 x_stop_queuing_selection_requests (display)
8971 Display *display;
8972 {
8973 x_queue_selection_requests--;
8974 x_unqueue_events (display);
8975 }
8976 \f
8977 /* The main X event-reading loop - XTread_socket. */
8978
8979 /* Time stamp of enter window event. This is only used by XTread_socket,
8980 but we have to put it out here, since static variables within functions
8981 sometimes don't work. */
8982
8983 static Time enter_timestamp;
8984
8985 /* This holds the state XLookupString needs to implement dead keys
8986 and other tricks known as "compose processing". _X Window System_
8987 says that a portable program can't use this, but Stephen Gildea assures
8988 me that letting the compiler initialize it to zeros will work okay.
8989
8990 This must be defined outside of XTread_socket, for the same reasons
8991 given for enter_time stamp, above. */
8992
8993 static XComposeStatus compose_status;
8994
8995 /* Record the last 100 characters stored
8996 to help debug the loss-of-chars-during-GC problem. */
8997
8998 static int temp_index;
8999 static short temp_buffer[100];
9000
9001 /* Set this to nonzero to fake an "X I/O error"
9002 on a particular display. */
9003
9004 struct x_display_info *XTread_socket_fake_io_error;
9005
9006 /* When we find no input here, we occasionally do a no-op command
9007 to verify that the X server is still running and we can still talk with it.
9008 We try all the open displays, one by one.
9009 This variable is used for cycling thru the displays. */
9010
9011 static struct x_display_info *next_noop_dpyinfo;
9012
9013 #define SET_SAVED_MENU_EVENT(size) \
9014 do \
9015 { \
9016 if (f->output_data.x->saved_menu_event == 0) \
9017 f->output_data.x->saved_menu_event \
9018 = (XEvent *) xmalloc (sizeof (XEvent)); \
9019 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9020 if (numchars >= 1) \
9021 { \
9022 bufp->kind = menu_bar_activate_event; \
9023 XSETFRAME (bufp->frame_or_window, f); \
9024 bufp->arg = Qnil; \
9025 bufp++; \
9026 count++; \
9027 numchars--; \
9028 } \
9029 } \
9030 while (0)
9031
9032 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9033 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9034
9035 /* Read events coming from the X server.
9036 This routine is called by the SIGIO handler.
9037 We return as soon as there are no more events to be read.
9038
9039 Events representing keys are stored in buffer BUFP,
9040 which can hold up to NUMCHARS characters.
9041 We return the number of characters stored into the buffer,
9042 thus pretending to be `read'.
9043
9044 EXPECTED is nonzero if the caller knows input is available. */
9045
9046 int
9047 XTread_socket (sd, bufp, numchars, expected)
9048 register int sd;
9049 /* register */ struct input_event *bufp;
9050 /* register */ int numchars;
9051 int expected;
9052 {
9053 int count = 0;
9054 int nbytes = 0;
9055 XEvent event;
9056 struct frame *f;
9057 int event_found = 0;
9058 struct x_display_info *dpyinfo;
9059 struct coding_system coding;
9060
9061 if (interrupt_input_blocked)
9062 {
9063 interrupt_input_pending = 1;
9064 return -1;
9065 }
9066
9067 interrupt_input_pending = 0;
9068 BLOCK_INPUT;
9069
9070 /* So people can tell when we have read the available input. */
9071 input_signal_count++;
9072
9073 if (numchars <= 0)
9074 abort (); /* Don't think this happens. */
9075
9076 ++handling_signal;
9077
9078 /* The input should be decoded if it is from XIM. Currently the
9079 locale of XIM is the same as that of the system. So, we can use
9080 Vlocale_coding_system which is initialized properly at Emacs
9081 startup time. */
9082 setup_coding_system (Vlocale_coding_system, &coding);
9083 coding.src_multibyte = 0;
9084 coding.dst_multibyte = 1;
9085 /* The input is converted to events, thus we can't handle
9086 composition. Anyway, there's no XIM that gives us composition
9087 information. */
9088 coding.composing = COMPOSITION_DISABLED;
9089
9090 /* Find the display we are supposed to read input for.
9091 It's the one communicating on descriptor SD. */
9092 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9093 {
9094 #if 0 /* This ought to be unnecessary; let's verify it. */
9095 #ifdef FIOSNBIO
9096 /* If available, Xlib uses FIOSNBIO to make the socket
9097 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9098 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9099 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9100 fcntl (dpyinfo->connection, F_SETFL, 0);
9101 #endif /* ! defined (FIOSNBIO) */
9102 #endif
9103
9104 #if 0 /* This code can't be made to work, with multiple displays,
9105 and appears not to be used on any system any more.
9106 Also keyboard.c doesn't turn O_NDELAY on and off
9107 for X connections. */
9108 #ifndef SIGIO
9109 #ifndef HAVE_SELECT
9110 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9111 {
9112 extern int read_alarm_should_throw;
9113 read_alarm_should_throw = 1;
9114 XPeekEvent (dpyinfo->display, &event);
9115 read_alarm_should_throw = 0;
9116 }
9117 #endif /* HAVE_SELECT */
9118 #endif /* SIGIO */
9119 #endif
9120
9121 /* For debugging, this gives a way to fake an I/O error. */
9122 if (dpyinfo == XTread_socket_fake_io_error)
9123 {
9124 XTread_socket_fake_io_error = 0;
9125 x_io_error_quitter (dpyinfo->display);
9126 }
9127
9128 while (XPending (dpyinfo->display))
9129 {
9130 XNextEvent (dpyinfo->display, &event);
9131
9132 #ifdef HAVE_X_I18N
9133 {
9134 /* Filter events for the current X input method.
9135 XFilterEvent returns non-zero if the input method has
9136 consumed the event. We pass the frame's X window to
9137 XFilterEvent because that's the one for which the IC
9138 was created. */
9139 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9140 event.xclient.window);
9141 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9142 break;
9143 }
9144 #endif
9145 event_found = 1;
9146
9147 switch (event.type)
9148 {
9149 case ClientMessage:
9150 {
9151 if (event.xclient.message_type
9152 == dpyinfo->Xatom_wm_protocols
9153 && event.xclient.format == 32)
9154 {
9155 if (event.xclient.data.l[0]
9156 == dpyinfo->Xatom_wm_take_focus)
9157 {
9158 /* Use x_any_window_to_frame because this
9159 could be the shell widget window
9160 if the frame has no title bar. */
9161 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9162 #ifdef HAVE_X_I18N
9163 /* Not quite sure this is needed -pd */
9164 if (f && FRAME_XIC (f))
9165 XSetICFocus (FRAME_XIC (f));
9166 #endif
9167 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9168 instructs the WM to set the input focus automatically for
9169 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9170 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9171 it has set the focus. So, XSetInputFocus below is not
9172 needed.
9173
9174 The call to XSetInputFocus below has also caused trouble. In
9175 cases where the XSetInputFocus done by the WM and the one
9176 below are temporally close (on a fast machine), the call
9177 below can generate additional FocusIn events which confuse
9178 Emacs. */
9179
9180 /* Since we set WM_TAKE_FOCUS, we must call
9181 XSetInputFocus explicitly. But not if f is null,
9182 since that might be an event for a deleted frame. */
9183 if (f)
9184 {
9185 Display *d = event.xclient.display;
9186 /* Catch and ignore errors, in case window has been
9187 iconified by a window manager such as GWM. */
9188 int count = x_catch_errors (d);
9189 XSetInputFocus (d, event.xclient.window,
9190 /* The ICCCM says this is
9191 the only valid choice. */
9192 RevertToParent,
9193 event.xclient.data.l[1]);
9194 /* This is needed to detect the error
9195 if there is an error. */
9196 XSync (d, False);
9197 x_uncatch_errors (d, count);
9198 }
9199 /* Not certain about handling scroll bars here */
9200 #endif /* 0 */
9201 }
9202 else if (event.xclient.data.l[0]
9203 == dpyinfo->Xatom_wm_save_yourself)
9204 {
9205 /* Save state modify the WM_COMMAND property to
9206 something which can reinstate us. This notifies
9207 the session manager, who's looking for such a
9208 PropertyNotify. Can restart processing when
9209 a keyboard or mouse event arrives. */
9210 if (numchars > 0)
9211 {
9212 f = x_top_window_to_frame (dpyinfo,
9213 event.xclient.window);
9214
9215 /* This is just so we only give real data once
9216 for a single Emacs process. */
9217 if (f == SELECTED_FRAME ())
9218 XSetCommand (FRAME_X_DISPLAY (f),
9219 event.xclient.window,
9220 initial_argv, initial_argc);
9221 else if (f)
9222 XSetCommand (FRAME_X_DISPLAY (f),
9223 event.xclient.window,
9224 0, 0);
9225 }
9226 }
9227 else if (event.xclient.data.l[0]
9228 == dpyinfo->Xatom_wm_delete_window)
9229 {
9230 struct frame *f
9231 = x_any_window_to_frame (dpyinfo,
9232 event.xclient.window);
9233
9234 if (f)
9235 {
9236 if (numchars == 0)
9237 abort ();
9238
9239 bufp->kind = delete_window_event;
9240 XSETFRAME (bufp->frame_or_window, f);
9241 bufp->arg = Qnil;
9242 bufp++;
9243
9244 count += 1;
9245 numchars -= 1;
9246 }
9247 }
9248 }
9249 else if (event.xclient.message_type
9250 == dpyinfo->Xatom_wm_configure_denied)
9251 {
9252 }
9253 else if (event.xclient.message_type
9254 == dpyinfo->Xatom_wm_window_moved)
9255 {
9256 int new_x, new_y;
9257 struct frame *f
9258 = x_window_to_frame (dpyinfo, event.xclient.window);
9259
9260 new_x = event.xclient.data.s[0];
9261 new_y = event.xclient.data.s[1];
9262
9263 if (f)
9264 {
9265 f->output_data.x->left_pos = new_x;
9266 f->output_data.x->top_pos = new_y;
9267 }
9268 }
9269 #ifdef HACK_EDITRES
9270 else if (event.xclient.message_type
9271 == dpyinfo->Xatom_editres)
9272 {
9273 struct frame *f
9274 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9275 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9276 &event, NULL);
9277 }
9278 #endif /* HACK_EDITRES */
9279 else if ((event.xclient.message_type
9280 == dpyinfo->Xatom_DONE)
9281 || (event.xclient.message_type
9282 == dpyinfo->Xatom_PAGE))
9283 {
9284 /* Ghostview job completed. Kill it. We could
9285 reply with "Next" if we received "Page", but we
9286 currently never do because we are interested in
9287 images, only, which should have 1 page. */
9288 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9289 struct frame *f
9290 = x_window_to_frame (dpyinfo, event.xclient.window);
9291 x_kill_gs_process (pixmap, f);
9292 expose_frame (f, 0, 0, 0, 0);
9293 }
9294 #ifdef USE_TOOLKIT_SCROLL_BARS
9295 /* Scroll bar callbacks send a ClientMessage from which
9296 we construct an input_event. */
9297 else if (event.xclient.message_type
9298 == dpyinfo->Xatom_Scrollbar)
9299 {
9300 x_scroll_bar_to_input_event (&event, bufp);
9301 ++bufp, ++count, --numchars;
9302 goto out;
9303 }
9304 #endif /* USE_TOOLKIT_SCROLL_BARS */
9305 else
9306 goto OTHER;
9307 }
9308 break;
9309
9310 case SelectionNotify:
9311 #ifdef USE_X_TOOLKIT
9312 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9313 goto OTHER;
9314 #endif /* not USE_X_TOOLKIT */
9315 x_handle_selection_notify (&event.xselection);
9316 break;
9317
9318 case SelectionClear: /* Someone has grabbed ownership. */
9319 #ifdef USE_X_TOOLKIT
9320 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9321 goto OTHER;
9322 #endif /* USE_X_TOOLKIT */
9323 {
9324 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9325
9326 if (numchars == 0)
9327 abort ();
9328
9329 bufp->kind = selection_clear_event;
9330 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9331 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9332 SELECTION_EVENT_TIME (bufp) = eventp->time;
9333 bufp->frame_or_window = Qnil;
9334 bufp->arg = Qnil;
9335 bufp++;
9336
9337 count += 1;
9338 numchars -= 1;
9339 }
9340 break;
9341
9342 case SelectionRequest: /* Someone wants our selection. */
9343 #ifdef USE_X_TOOLKIT
9344 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9345 goto OTHER;
9346 #endif /* USE_X_TOOLKIT */
9347 if (x_queue_selection_requests)
9348 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9349 &event);
9350 else
9351 {
9352 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9353
9354 if (numchars == 0)
9355 abort ();
9356
9357 bufp->kind = selection_request_event;
9358 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9359 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9360 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9361 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9362 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9363 SELECTION_EVENT_TIME (bufp) = eventp->time;
9364 bufp->frame_or_window = Qnil;
9365 bufp->arg = Qnil;
9366 bufp++;
9367
9368 count += 1;
9369 numchars -= 1;
9370 }
9371 break;
9372
9373 case PropertyNotify:
9374 #ifdef USE_X_TOOLKIT
9375 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9376 goto OTHER;
9377 #endif /* not USE_X_TOOLKIT */
9378 x_handle_property_notify (&event.xproperty);
9379 break;
9380
9381 case ReparentNotify:
9382 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9383 if (f)
9384 {
9385 int x, y;
9386 f->output_data.x->parent_desc = event.xreparent.parent;
9387 x_real_positions (f, &x, &y);
9388 f->output_data.x->left_pos = x;
9389 f->output_data.x->top_pos = y;
9390 }
9391 break;
9392
9393 case Expose:
9394 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9395 if (f)
9396 {
9397 if (f->async_visible == 0)
9398 {
9399 f->async_visible = 1;
9400 f->async_iconified = 0;
9401 f->output_data.x->has_been_visible = 1;
9402 SET_FRAME_GARBAGED (f);
9403 }
9404 else
9405 expose_frame (x_window_to_frame (dpyinfo,
9406 event.xexpose.window),
9407 event.xexpose.x, event.xexpose.y,
9408 event.xexpose.width, event.xexpose.height);
9409 }
9410 else
9411 {
9412 #ifdef USE_TOOLKIT_SCROLL_BARS
9413 /* Dispatch event to the widget. */
9414 goto OTHER;
9415 #else /* not USE_TOOLKIT_SCROLL_BARS */
9416 struct scroll_bar *bar
9417 = x_window_to_scroll_bar (event.xexpose.window);
9418
9419 if (bar)
9420 x_scroll_bar_expose (bar, &event);
9421 #ifdef USE_X_TOOLKIT
9422 else
9423 goto OTHER;
9424 #endif /* USE_X_TOOLKIT */
9425 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9426 }
9427 break;
9428
9429 case GraphicsExpose: /* This occurs when an XCopyArea's
9430 source area was obscured or not
9431 available.*/
9432 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9433 if (f)
9434 {
9435 expose_frame (f,
9436 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9437 event.xgraphicsexpose.width,
9438 event.xgraphicsexpose.height);
9439 }
9440 #ifdef USE_X_TOOLKIT
9441 else
9442 goto OTHER;
9443 #endif /* USE_X_TOOLKIT */
9444 break;
9445
9446 case NoExpose: /* This occurs when an XCopyArea's
9447 source area was completely
9448 available */
9449 break;
9450
9451 case UnmapNotify:
9452 /* Redo the mouse-highlight after the tooltip has gone. */
9453 if (event.xmap.window == tip_window)
9454 {
9455 tip_window = 0;
9456 redo_mouse_highlight ();
9457 }
9458
9459 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9460 if (f) /* F may no longer exist if
9461 the frame was deleted. */
9462 {
9463 /* While a frame is unmapped, display generation is
9464 disabled; you don't want to spend time updating a
9465 display that won't ever be seen. */
9466 f->async_visible = 0;
9467 /* We can't distinguish, from the event, whether the window
9468 has become iconified or invisible. So assume, if it
9469 was previously visible, than now it is iconified.
9470 But x_make_frame_invisible clears both
9471 the visible flag and the iconified flag;
9472 and that way, we know the window is not iconified now. */
9473 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9474 {
9475 f->async_iconified = 1;
9476
9477 bufp->kind = iconify_event;
9478 XSETFRAME (bufp->frame_or_window, f);
9479 bufp->arg = Qnil;
9480 bufp++;
9481 count++;
9482 numchars--;
9483 }
9484 }
9485 goto OTHER;
9486
9487 case MapNotify:
9488 if (event.xmap.window == tip_window)
9489 /* The tooltip has been drawn already. Avoid
9490 the SET_FRAME_GARBAGED below. */
9491 goto OTHER;
9492
9493 /* We use x_top_window_to_frame because map events can
9494 come for sub-windows and they don't mean that the
9495 frame is visible. */
9496 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9497 if (f)
9498 {
9499 f->async_visible = 1;
9500 f->async_iconified = 0;
9501 f->output_data.x->has_been_visible = 1;
9502
9503 /* wait_reading_process_input will notice this and update
9504 the frame's display structures. */
9505 SET_FRAME_GARBAGED (f);
9506
9507 if (f->iconified)
9508 {
9509 bufp->kind = deiconify_event;
9510 XSETFRAME (bufp->frame_or_window, f);
9511 bufp->arg = Qnil;
9512 bufp++;
9513 count++;
9514 numchars--;
9515 }
9516 else if (! NILP (Vframe_list)
9517 && ! NILP (XCDR (Vframe_list)))
9518 /* Force a redisplay sooner or later
9519 to update the frame titles
9520 in case this is the second frame. */
9521 record_asynch_buffer_change ();
9522 }
9523 goto OTHER;
9524
9525 case KeyPress:
9526 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9527
9528 #ifdef USE_MOTIF
9529 /* I couldn't find a way to prevent LessTif scroll bars
9530 from consuming key events. */
9531 if (f == 0)
9532 {
9533 Widget widget = XtWindowToWidget (dpyinfo->display,
9534 event.xkey.window);
9535 if (widget && XmIsScrollBar (widget))
9536 {
9537 widget = XtParent (widget);
9538 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9539 }
9540 }
9541 #endif /* USE_MOTIF */
9542
9543 if (f != 0)
9544 {
9545 KeySym keysym, orig_keysym;
9546 /* al%imercury@uunet.uu.net says that making this 81
9547 instead of 80 fixed a bug whereby meta chars made
9548 his Emacs hang.
9549
9550 It seems that some version of XmbLookupString has
9551 a bug of not returning XBufferOverflow in
9552 status_return even if the input is too long to
9553 fit in 81 bytes. So, we must prepare sufficient
9554 bytes for copy_buffer. 513 bytes (256 chars for
9555 two-byte character set) seems to be a faily good
9556 approximation. -- 2000.8.10 handa@etl.go.jp */
9557 unsigned char copy_buffer[513];
9558 unsigned char *copy_bufptr = copy_buffer;
9559 int copy_bufsiz = sizeof (copy_buffer);
9560 int modifiers;
9561
9562 event.xkey.state
9563 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9564 extra_keyboard_modifiers);
9565 modifiers = event.xkey.state;
9566
9567 /* This will have to go some day... */
9568
9569 /* make_lispy_event turns chars into control chars.
9570 Don't do it here because XLookupString is too eager. */
9571 event.xkey.state &= ~ControlMask;
9572 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9573 | dpyinfo->super_mod_mask
9574 | dpyinfo->hyper_mod_mask
9575 | dpyinfo->alt_mod_mask);
9576
9577 /* In case Meta is ComposeCharacter,
9578 clear its status. According to Markus Ehrnsperger
9579 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9580 this enables ComposeCharacter to work whether or
9581 not it is combined with Meta. */
9582 if (modifiers & dpyinfo->meta_mod_mask)
9583 bzero (&compose_status, sizeof (compose_status));
9584
9585 #ifdef HAVE_X_I18N
9586 if (FRAME_XIC (f))
9587 {
9588 Status status_return;
9589
9590 nbytes = XmbLookupString (FRAME_XIC (f),
9591 &event.xkey, copy_bufptr,
9592 copy_bufsiz, &keysym,
9593 &status_return);
9594 if (status_return == XBufferOverflow)
9595 {
9596 copy_bufsiz = nbytes + 1;
9597 copy_bufptr = (char *) alloca (copy_bufsiz);
9598 nbytes = XmbLookupString (FRAME_XIC (f),
9599 &event.xkey, copy_bufptr,
9600 copy_bufsiz, &keysym,
9601 &status_return);
9602 }
9603
9604 if (status_return == XLookupNone)
9605 break;
9606 else if (status_return == XLookupChars)
9607 {
9608 keysym = NoSymbol;
9609 modifiers = 0;
9610 }
9611 else if (status_return != XLookupKeySym
9612 && status_return != XLookupBoth)
9613 abort ();
9614 }
9615 else
9616 nbytes = XLookupString (&event.xkey, copy_bufptr,
9617 copy_bufsiz, &keysym,
9618 &compose_status);
9619 #else
9620 nbytes = XLookupString (&event.xkey, copy_bufptr,
9621 copy_bufsiz, &keysym,
9622 &compose_status);
9623 #endif
9624
9625 orig_keysym = keysym;
9626
9627 if (numchars > 1)
9628 {
9629 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9630 || keysym == XK_Delete
9631 #ifdef XK_ISO_Left_Tab
9632 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9633 #endif
9634 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9635 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9636 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9637 #ifdef HPUX
9638 /* This recognizes the "extended function keys".
9639 It seems there's no cleaner way.
9640 Test IsModifierKey to avoid handling mode_switch
9641 incorrectly. */
9642 || ((unsigned) (keysym) >= XK_Select
9643 && (unsigned)(keysym) < XK_KP_Space)
9644 #endif
9645 #ifdef XK_dead_circumflex
9646 || orig_keysym == XK_dead_circumflex
9647 #endif
9648 #ifdef XK_dead_grave
9649 || orig_keysym == XK_dead_grave
9650 #endif
9651 #ifdef XK_dead_tilde
9652 || orig_keysym == XK_dead_tilde
9653 #endif
9654 #ifdef XK_dead_diaeresis
9655 || orig_keysym == XK_dead_diaeresis
9656 #endif
9657 #ifdef XK_dead_macron
9658 || orig_keysym == XK_dead_macron
9659 #endif
9660 #ifdef XK_dead_degree
9661 || orig_keysym == XK_dead_degree
9662 #endif
9663 #ifdef XK_dead_acute
9664 || orig_keysym == XK_dead_acute
9665 #endif
9666 #ifdef XK_dead_cedilla
9667 || orig_keysym == XK_dead_cedilla
9668 #endif
9669 #ifdef XK_dead_breve
9670 || orig_keysym == XK_dead_breve
9671 #endif
9672 #ifdef XK_dead_ogonek
9673 || orig_keysym == XK_dead_ogonek
9674 #endif
9675 #ifdef XK_dead_caron
9676 || orig_keysym == XK_dead_caron
9677 #endif
9678 #ifdef XK_dead_doubleacute
9679 || orig_keysym == XK_dead_doubleacute
9680 #endif
9681 #ifdef XK_dead_abovedot
9682 || orig_keysym == XK_dead_abovedot
9683 #endif
9684 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9685 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9686 /* Any "vendor-specific" key is ok. */
9687 || (orig_keysym & (1 << 28)))
9688 && ! (IsModifierKey (orig_keysym)
9689 #ifndef HAVE_X11R5
9690 #ifdef XK_Mode_switch
9691 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9692 #endif
9693 #ifdef XK_Num_Lock
9694 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9695 #endif
9696 #endif /* not HAVE_X11R5 */
9697 ))
9698 {
9699 if (temp_index == sizeof temp_buffer / sizeof (short))
9700 temp_index = 0;
9701 temp_buffer[temp_index++] = keysym;
9702 bufp->kind = non_ascii_keystroke;
9703 bufp->code = keysym;
9704 XSETFRAME (bufp->frame_or_window, f);
9705 bufp->arg = Qnil;
9706 bufp->modifiers
9707 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9708 modifiers);
9709 bufp->timestamp = event.xkey.time;
9710 bufp++;
9711 count++;
9712 numchars--;
9713 }
9714 else if (numchars > nbytes)
9715 {
9716 register int i;
9717 register int c;
9718 unsigned char *p, *pend;
9719 int nchars, len;
9720
9721 for (i = 0; i < nbytes; i++)
9722 {
9723 if (temp_index == (sizeof temp_buffer
9724 / sizeof (short)))
9725 temp_index = 0;
9726 temp_buffer[temp_index++] = copy_bufptr[i];
9727 }
9728
9729 if (/* If the event is not from XIM, */
9730 event.xkey.keycode != 0
9731 /* or the current locale doesn't request
9732 decoding of the intup data, ... */
9733 || coding.type == coding_type_raw_text
9734 || coding.type == coding_type_no_conversion)
9735 {
9736 /* ... we can use the input data as is. */
9737 nchars = nbytes;
9738 }
9739 else
9740 {
9741 /* We have to decode the input data. */
9742 int require;
9743 unsigned char *p;
9744
9745 require = decoding_buffer_size (&coding, nbytes);
9746 p = (unsigned char *) alloca (require);
9747 coding.mode |= CODING_MODE_LAST_BLOCK;
9748 decode_coding (&coding, copy_bufptr, p,
9749 nbytes, require);
9750 nbytes = coding.produced;
9751 nchars = coding.produced_char;
9752 copy_bufptr = p;
9753 }
9754
9755 /* Convert the input data to a sequence of
9756 character events. */
9757 for (i = 0; i < nbytes; i += len)
9758 {
9759 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9760 nbytes - i, len);
9761 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9762 ? ascii_keystroke
9763 : multibyte_char_keystroke);
9764 bufp->code = c;
9765 XSETFRAME (bufp->frame_or_window, f);
9766 bufp->arg = Qnil;
9767 bufp->modifiers
9768 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9769 modifiers);
9770 bufp->timestamp = event.xkey.time;
9771 bufp++;
9772 }
9773
9774 count += nchars;
9775 numchars -= nchars;
9776
9777 if (keysym == NoSymbol)
9778 break;
9779 }
9780 else
9781 abort ();
9782 }
9783 else
9784 abort ();
9785 }
9786 #ifdef HAVE_X_I18N
9787 /* Don't dispatch this event since XtDispatchEvent calls
9788 XFilterEvent, and two calls in a row may freeze the
9789 client. */
9790 break;
9791 #else
9792 goto OTHER;
9793 #endif
9794
9795 case KeyRelease:
9796 #ifdef HAVE_X_I18N
9797 /* Don't dispatch this event since XtDispatchEvent calls
9798 XFilterEvent, and two calls in a row may freeze the
9799 client. */
9800 break;
9801 #else
9802 goto OTHER;
9803 #endif
9804
9805 /* Here's a possible interpretation of the whole
9806 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9807 you get a FocusIn event, you have to get a FocusOut
9808 event before you relinquish the focus. If you
9809 haven't received a FocusIn event, then a mere
9810 LeaveNotify is enough to free you. */
9811
9812 case EnterNotify:
9813 {
9814 int from_menu_bar_p = 0;
9815
9816 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9817
9818 #ifdef LESSTIF_VERSION
9819 /* When clicking outside of a menu bar popup to close
9820 it, we get a FocusIn/ EnterNotify sequence of
9821 events. The flag event.xcrossing.focus is not set
9822 in the EnterNotify event of that sequence because
9823 the focus is in the menu bar,
9824 event.xcrossing.window is the frame's X window.
9825 Unconditionally setting the focus frame to null in
9826 this case is not the right thing, because no event
9827 follows that could set the focus frame to the right
9828 value.
9829
9830 This could be a LessTif bug, but I wasn't able to
9831 reproduce the behavior in a simple test program.
9832
9833 (gerd, LessTif 0.88.1). */
9834
9835 if (!event.xcrossing.focus
9836 && f
9837 && f->output_data.x->menubar_widget)
9838 {
9839 Window focus;
9840 int revert;
9841
9842 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9843 if (focus == XtWindow (f->output_data.x->menubar_widget))
9844 from_menu_bar_p = 1;
9845 }
9846 #endif /* LESSTIF_VERSION */
9847
9848 if (event.xcrossing.focus || from_menu_bar_p)
9849 {
9850 /* Avoid nasty pop/raise loops. */
9851 if (f && (!(f->auto_raise)
9852 || !(f->auto_lower)
9853 || (event.xcrossing.time - enter_timestamp) > 500))
9854 {
9855 x_new_focus_frame (dpyinfo, f);
9856 enter_timestamp = event.xcrossing.time;
9857 }
9858 }
9859 else if (f == dpyinfo->x_focus_frame)
9860 x_new_focus_frame (dpyinfo, 0);
9861
9862 /* EnterNotify counts as mouse movement,
9863 so update things that depend on mouse position. */
9864 if (f && !f->output_data.x->busy_p)
9865 note_mouse_movement (f, &event.xmotion);
9866 goto OTHER;
9867 }
9868
9869 case FocusIn:
9870 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9871 if (event.xfocus.detail != NotifyPointer)
9872 dpyinfo->x_focus_event_frame = f;
9873 if (f)
9874 {
9875 x_new_focus_frame (dpyinfo, f);
9876
9877 /* Don't stop displaying the initial startup message
9878 for a switch-frame event we don't need. */
9879 if (GC_NILP (Vterminal_frame)
9880 && GC_CONSP (Vframe_list)
9881 && !GC_NILP (XCDR (Vframe_list)))
9882 {
9883 bufp->kind = FOCUS_IN_EVENT;
9884 XSETFRAME (bufp->frame_or_window, f);
9885 bufp->arg = Qnil;
9886 ++bufp, ++count, --numchars;
9887 }
9888 }
9889
9890 #ifdef HAVE_X_I18N
9891 if (f && FRAME_XIC (f))
9892 XSetICFocus (FRAME_XIC (f));
9893 #endif
9894
9895 goto OTHER;
9896
9897 case LeaveNotify:
9898 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
9899 if (f)
9900 {
9901 Lisp_Object frame;
9902 int from_menu_bar_p = 0;
9903
9904 if (f == dpyinfo->mouse_face_mouse_frame)
9905 {
9906 /* If we move outside the frame, then we're
9907 certainly no longer on any text in the frame. */
9908 clear_mouse_face (dpyinfo);
9909 dpyinfo->mouse_face_mouse_frame = 0;
9910 }
9911
9912 /* Generate a nil HELP_EVENT to cancel a help-echo.
9913 Do it only if there's something to cancel.
9914 Otherwise, the startup message is cleared when
9915 the mouse leaves the frame. */
9916 if (any_help_event_p)
9917 {
9918 Lisp_Object frame;
9919 int n;
9920
9921 XSETFRAME (frame, f);
9922 n = gen_help_event (bufp, numchars,
9923 Qnil, frame, Qnil, Qnil, 0);
9924 bufp += n, count += n, numchars -= n;
9925 }
9926
9927 #ifdef LESSTIF_VERSION
9928 /* Please see the comment at the start of the
9929 EnterNotify case. */
9930 if (!event.xcrossing.focus
9931 && f->output_data.x->menubar_widget)
9932 {
9933 Window focus;
9934 int revert;
9935 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9936 if (focus == XtWindow (f->output_data.x->menubar_widget))
9937 from_menu_bar_p = 1;
9938 }
9939 #endif /* LESSTIF_VERSION */
9940
9941 if (event.xcrossing.focus || from_menu_bar_p)
9942 x_mouse_leave (dpyinfo);
9943 else
9944 {
9945 if (f == dpyinfo->x_focus_event_frame)
9946 dpyinfo->x_focus_event_frame = 0;
9947 if (f == dpyinfo->x_focus_frame)
9948 x_new_focus_frame (dpyinfo, 0);
9949 }
9950 }
9951 goto OTHER;
9952
9953 case FocusOut:
9954 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9955 if (event.xfocus.detail != NotifyPointer
9956 && f == dpyinfo->x_focus_event_frame)
9957 dpyinfo->x_focus_event_frame = 0;
9958 if (f && f == dpyinfo->x_focus_frame)
9959 x_new_focus_frame (dpyinfo, 0);
9960
9961 #ifdef HAVE_X_I18N
9962 if (f && FRAME_XIC (f))
9963 XUnsetICFocus (FRAME_XIC (f));
9964 #endif
9965
9966 goto OTHER;
9967
9968 case MotionNotify:
9969 {
9970 previous_help_echo = help_echo;
9971 help_echo = help_echo_object = help_echo_window = Qnil;
9972 help_echo_pos = -1;
9973
9974 if (dpyinfo->grabbed && last_mouse_frame
9975 && FRAME_LIVE_P (last_mouse_frame))
9976 f = last_mouse_frame;
9977 else
9978 f = x_window_to_frame (dpyinfo, event.xmotion.window);
9979
9980 if (f)
9981 note_mouse_movement (f, &event.xmotion);
9982 else
9983 {
9984 #ifndef USE_TOOLKIT_SCROLL_BARS
9985 struct scroll_bar *bar
9986 = x_window_to_scroll_bar (event.xmotion.window);
9987
9988 if (bar)
9989 x_scroll_bar_note_movement (bar, &event);
9990 #endif /* USE_TOOLKIT_SCROLL_BARS */
9991
9992 /* If we move outside the frame, then we're
9993 certainly no longer on any text in the frame. */
9994 clear_mouse_face (dpyinfo);
9995 }
9996
9997 /* If the contents of the global variable help_echo
9998 has changed, generate a HELP_EVENT. */
9999 if (!NILP (help_echo)
10000 || !NILP (previous_help_echo))
10001 {
10002 Lisp_Object frame;
10003 int n;
10004
10005 if (f)
10006 XSETFRAME (frame, f);
10007 else
10008 frame = Qnil;
10009
10010 any_help_event_p = 1;
10011 n = gen_help_event (bufp, numchars, help_echo, frame,
10012 help_echo_window, help_echo_object,
10013 help_echo_pos);
10014 bufp += n, count += n, numchars -= n;
10015 }
10016
10017 goto OTHER;
10018 }
10019
10020 case ConfigureNotify:
10021 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10022 if (f)
10023 {
10024 #ifndef USE_X_TOOLKIT
10025 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10026 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10027
10028 /* In the toolkit version, change_frame_size
10029 is called by the code that handles resizing
10030 of the EmacsFrame widget. */
10031
10032 /* Even if the number of character rows and columns has
10033 not changed, the font size may have changed, so we need
10034 to check the pixel dimensions as well. */
10035 if (columns != f->width
10036 || rows != f->height
10037 || event.xconfigure.width != f->output_data.x->pixel_width
10038 || event.xconfigure.height != f->output_data.x->pixel_height)
10039 {
10040 change_frame_size (f, rows, columns, 0, 1, 0);
10041 SET_FRAME_GARBAGED (f);
10042 cancel_mouse_face (f);
10043 }
10044 #endif
10045
10046 f->output_data.x->pixel_width = event.xconfigure.width;
10047 f->output_data.x->pixel_height = event.xconfigure.height;
10048
10049 /* What we have now is the position of Emacs's own window.
10050 Convert that to the position of the window manager window. */
10051 x_real_positions (f, &f->output_data.x->left_pos,
10052 &f->output_data.x->top_pos);
10053
10054 #ifdef HAVE_X_I18N
10055 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10056 xic_set_statusarea (f);
10057 #endif
10058
10059 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10060 {
10061 /* Since the WM decorations come below top_pos now,
10062 we must put them below top_pos in the future. */
10063 f->output_data.x->win_gravity = NorthWestGravity;
10064 x_wm_set_size_hint (f, (long) 0, 0);
10065 }
10066 #ifdef USE_MOTIF
10067 /* Some window managers pass (0,0) as the location of
10068 the window, and the Motif event handler stores it
10069 in the emacs widget, which messes up Motif menus. */
10070 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10071 {
10072 event.xconfigure.x = f->output_data.x->widget->core.x;
10073 event.xconfigure.y = f->output_data.x->widget->core.y;
10074 }
10075 #endif /* USE_MOTIF */
10076 }
10077 goto OTHER;
10078
10079 case ButtonPress:
10080 case ButtonRelease:
10081 {
10082 /* If we decide we want to generate an event to be seen
10083 by the rest of Emacs, we put it here. */
10084 struct input_event emacs_event;
10085 int tool_bar_p = 0;
10086
10087 emacs_event.kind = no_event;
10088 bzero (&compose_status, sizeof (compose_status));
10089
10090 if (dpyinfo->grabbed
10091 && last_mouse_frame
10092 && FRAME_LIVE_P (last_mouse_frame))
10093 f = last_mouse_frame;
10094 else
10095 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10096
10097 if (f)
10098 {
10099 /* Is this in the tool-bar? */
10100 if (WINDOWP (f->tool_bar_window)
10101 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10102 {
10103 Lisp_Object window;
10104 int p, x, y;
10105
10106 x = event.xbutton.x;
10107 y = event.xbutton.y;
10108
10109 /* Set x and y. */
10110 window = window_from_coordinates (f, x, y, &p, 1);
10111 if (EQ (window, f->tool_bar_window))
10112 {
10113 x_handle_tool_bar_click (f, &event.xbutton);
10114 tool_bar_p = 1;
10115 }
10116 }
10117
10118 if (!tool_bar_p)
10119 if (!dpyinfo->x_focus_frame
10120 || f == dpyinfo->x_focus_frame)
10121 construct_mouse_click (&emacs_event, &event, f);
10122 }
10123 else
10124 {
10125 #ifndef USE_TOOLKIT_SCROLL_BARS
10126 struct scroll_bar *bar
10127 = x_window_to_scroll_bar (event.xbutton.window);
10128
10129 if (bar)
10130 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10131 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10132 }
10133
10134 if (event.type == ButtonPress)
10135 {
10136 dpyinfo->grabbed |= (1 << event.xbutton.button);
10137 last_mouse_frame = f;
10138 /* Ignore any mouse motion that happened
10139 before this event; any subsequent mouse-movement
10140 Emacs events should reflect only motion after
10141 the ButtonPress. */
10142 if (f != 0)
10143 f->mouse_moved = 0;
10144
10145 if (!tool_bar_p)
10146 last_tool_bar_item = -1;
10147 }
10148 else
10149 {
10150 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10151 }
10152
10153 if (numchars >= 1 && emacs_event.kind != no_event)
10154 {
10155 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10156 bufp++;
10157 count++;
10158 numchars--;
10159 }
10160
10161 #ifdef USE_X_TOOLKIT
10162 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10163 /* For a down-event in the menu bar,
10164 don't pass it to Xt right now.
10165 Instead, save it away
10166 and we will pass it to Xt from kbd_buffer_get_event.
10167 That way, we can run some Lisp code first. */
10168 if (f && event.type == ButtonPress
10169 /* Verify the event is really within the menu bar
10170 and not just sent to it due to grabbing. */
10171 && event.xbutton.x >= 0
10172 && event.xbutton.x < f->output_data.x->pixel_width
10173 && event.xbutton.y >= 0
10174 && event.xbutton.y < f->output_data.x->menubar_height
10175 && event.xbutton.same_screen)
10176 {
10177 SET_SAVED_BUTTON_EVENT;
10178 XSETFRAME (last_mouse_press_frame, f);
10179 }
10180 else if (event.type == ButtonPress)
10181 {
10182 last_mouse_press_frame = Qnil;
10183 goto OTHER;
10184 }
10185
10186 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10187 but I am trying to be cautious. */
10188 else if (event.type == ButtonRelease)
10189 {
10190 if (!NILP (last_mouse_press_frame))
10191 {
10192 f = XFRAME (last_mouse_press_frame);
10193 if (f->output_data.x)
10194 SET_SAVED_BUTTON_EVENT;
10195 }
10196 else
10197 goto OTHER;
10198 }
10199 #endif /* USE_MOTIF */
10200 else
10201 goto OTHER;
10202 #endif /* USE_X_TOOLKIT */
10203 }
10204 break;
10205
10206 case CirculateNotify:
10207 goto OTHER;
10208
10209 case CirculateRequest:
10210 goto OTHER;
10211
10212 case VisibilityNotify:
10213 goto OTHER;
10214
10215 case MappingNotify:
10216 /* Someone has changed the keyboard mapping - update the
10217 local cache. */
10218 switch (event.xmapping.request)
10219 {
10220 case MappingModifier:
10221 x_find_modifier_meanings (dpyinfo);
10222 /* This is meant to fall through. */
10223 case MappingKeyboard:
10224 XRefreshKeyboardMapping (&event.xmapping);
10225 }
10226 goto OTHER;
10227
10228 default:
10229 OTHER:
10230 #ifdef USE_X_TOOLKIT
10231 BLOCK_INPUT;
10232 XtDispatchEvent (&event);
10233 UNBLOCK_INPUT;
10234 #endif /* USE_X_TOOLKIT */
10235 break;
10236 }
10237 }
10238 }
10239
10240 out:;
10241
10242 /* On some systems, an X bug causes Emacs to get no more events
10243 when the window is destroyed. Detect that. (1994.) */
10244 if (! event_found)
10245 {
10246 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10247 One XNOOP in 100 loops will make Emacs terminate.
10248 B. Bretthauer, 1994 */
10249 x_noop_count++;
10250 if (x_noop_count >= 100)
10251 {
10252 x_noop_count=0;
10253
10254 if (next_noop_dpyinfo == 0)
10255 next_noop_dpyinfo = x_display_list;
10256
10257 XNoOp (next_noop_dpyinfo->display);
10258
10259 /* Each time we get here, cycle through the displays now open. */
10260 next_noop_dpyinfo = next_noop_dpyinfo->next;
10261 }
10262 }
10263
10264 /* If the focus was just given to an auto-raising frame,
10265 raise it now. */
10266 /* ??? This ought to be able to handle more than one such frame. */
10267 if (pending_autoraise_frame)
10268 {
10269 x_raise_frame (pending_autoraise_frame);
10270 pending_autoraise_frame = 0;
10271 }
10272
10273 UNBLOCK_INPUT;
10274 --handling_signal;
10275 return count;
10276 }
10277
10278
10279
10280 \f
10281 /***********************************************************************
10282 Text Cursor
10283 ***********************************************************************/
10284
10285 /* Note if the text cursor of window W has been overwritten by a
10286 drawing operation that outputs N glyphs starting at HPOS in the
10287 line given by output_cursor.vpos. N < 0 means all the rest of the
10288 line after HPOS has been written. */
10289
10290 static void
10291 note_overwritten_text_cursor (w, hpos, n)
10292 struct window *w;
10293 int hpos, n;
10294 {
10295 if (updated_area == TEXT_AREA
10296 && output_cursor.vpos == w->phys_cursor.vpos
10297 && hpos <= w->phys_cursor.hpos
10298 && (n < 0
10299 || hpos + n > w->phys_cursor.hpos))
10300 w->phys_cursor_on_p = 0;
10301 }
10302
10303
10304 /* Set clipping for output in glyph row ROW. W is the window in which
10305 we operate. GC is the graphics context to set clipping in.
10306 WHOLE_LINE_P non-zero means include the areas used for truncation
10307 mark display and alike in the clipping rectangle.
10308
10309 ROW may be a text row or, e.g., a mode line. Text rows must be
10310 clipped to the interior of the window dedicated to text display,
10311 mode lines must be clipped to the whole window. */
10312
10313 static void
10314 x_clip_to_row (w, row, gc, whole_line_p)
10315 struct window *w;
10316 struct glyph_row *row;
10317 GC gc;
10318 int whole_line_p;
10319 {
10320 struct frame *f = XFRAME (WINDOW_FRAME (w));
10321 XRectangle clip_rect;
10322 int window_x, window_y, window_width, window_height;
10323
10324 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10325
10326 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10327 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10328 clip_rect.y = max (clip_rect.y, window_y);
10329 clip_rect.width = window_width;
10330 clip_rect.height = row->visible_height;
10331
10332 /* If clipping to the whole line, including trunc marks, extend
10333 the rectangle to the left and increase its width. */
10334 if (whole_line_p)
10335 {
10336 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10337 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10338 }
10339
10340 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10341 }
10342
10343
10344 /* Draw a hollow box cursor on window W in glyph row ROW. */
10345
10346 static void
10347 x_draw_hollow_cursor (w, row)
10348 struct window *w;
10349 struct glyph_row *row;
10350 {
10351 struct frame *f = XFRAME (WINDOW_FRAME (w));
10352 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10353 Display *dpy = FRAME_X_DISPLAY (f);
10354 int x, y, wd, h;
10355 XGCValues xgcv;
10356 struct glyph *cursor_glyph;
10357 GC gc;
10358
10359 /* Compute frame-relative coordinates from window-relative
10360 coordinates. */
10361 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10362 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10363 + row->ascent - w->phys_cursor_ascent);
10364 h = row->height - 1;
10365
10366 /* Get the glyph the cursor is on. If we can't tell because
10367 the current matrix is invalid or such, give up. */
10368 cursor_glyph = get_phys_cursor_glyph (w);
10369 if (cursor_glyph == NULL)
10370 return;
10371
10372 /* Compute the width of the rectangle to draw. If on a stretch
10373 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10374 rectangle as wide as the glyph, but use a canonical character
10375 width instead. */
10376 wd = cursor_glyph->pixel_width - 1;
10377 if (cursor_glyph->type == STRETCH_GLYPH
10378 && !x_stretch_cursor_p)
10379 wd = min (CANON_X_UNIT (f), wd);
10380
10381 /* The foreground of cursor_gc is typically the same as the normal
10382 background color, which can cause the cursor box to be invisible. */
10383 xgcv.foreground = f->output_data.x->cursor_pixel;
10384 if (dpyinfo->scratch_cursor_gc)
10385 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10386 else
10387 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10388 GCForeground, &xgcv);
10389 gc = dpyinfo->scratch_cursor_gc;
10390
10391 /* Set clipping, draw the rectangle, and reset clipping again. */
10392 x_clip_to_row (w, row, gc, 0);
10393 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10394 XSetClipMask (dpy, gc, None);
10395 }
10396
10397
10398 /* Draw a bar cursor on window W in glyph row ROW.
10399
10400 Implementation note: One would like to draw a bar cursor with an
10401 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10402 Unfortunately, I didn't find a font yet that has this property set.
10403 --gerd. */
10404
10405 static void
10406 x_draw_bar_cursor (w, row, width)
10407 struct window *w;
10408 struct glyph_row *row;
10409 int width;
10410 {
10411 struct frame *f = XFRAME (w->frame);
10412 struct glyph *cursor_glyph;
10413 GC gc;
10414 int x;
10415 unsigned long mask;
10416 XGCValues xgcv;
10417 Display *dpy;
10418 Window window;
10419
10420 /* If cursor is out of bounds, don't draw garbage. This can happen
10421 in mini-buffer windows when switching between echo area glyphs
10422 and mini-buffer. */
10423 cursor_glyph = get_phys_cursor_glyph (w);
10424 if (cursor_glyph == NULL)
10425 return;
10426
10427 /* If on an image, draw like a normal cursor. That's usually better
10428 visible than drawing a bar, esp. if the image is large so that
10429 the bar might not be in the window. */
10430 if (cursor_glyph->type == IMAGE_GLYPH)
10431 {
10432 struct glyph_row *row;
10433 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10434 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10435 }
10436 else
10437 {
10438 xgcv.background = f->output_data.x->cursor_pixel;
10439 xgcv.foreground = f->output_data.x->cursor_pixel;
10440 xgcv.graphics_exposures = 0;
10441 mask = GCForeground | GCBackground | GCGraphicsExposures;
10442 dpy = FRAME_X_DISPLAY (f);
10443 window = FRAME_X_WINDOW (f);
10444 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10445
10446 if (gc)
10447 XChangeGC (dpy, gc, mask, &xgcv);
10448 else
10449 {
10450 gc = XCreateGC (dpy, window, mask, &xgcv);
10451 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10452 }
10453
10454 if (width < 0)
10455 width = f->output_data.x->cursor_width;
10456
10457 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10458 x_clip_to_row (w, row, gc, 0);
10459 XFillRectangle (dpy, window, gc,
10460 x,
10461 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10462 min (cursor_glyph->pixel_width, width),
10463 row->height);
10464 XSetClipMask (dpy, gc, None);
10465 }
10466 }
10467
10468
10469 /* Clear the cursor of window W to background color, and mark the
10470 cursor as not shown. This is used when the text where the cursor
10471 is is about to be rewritten. */
10472
10473 static void
10474 x_clear_cursor (w)
10475 struct window *w;
10476 {
10477 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10478 x_update_window_cursor (w, 0);
10479 }
10480
10481
10482 /* Draw the cursor glyph of window W in glyph row ROW. See the
10483 comment of x_draw_glyphs for the meaning of HL. */
10484
10485 static void
10486 x_draw_phys_cursor_glyph (w, row, hl)
10487 struct window *w;
10488 struct glyph_row *row;
10489 enum draw_glyphs_face hl;
10490 {
10491 /* If cursor hpos is out of bounds, don't draw garbage. This can
10492 happen in mini-buffer windows when switching between echo area
10493 glyphs and mini-buffer. */
10494 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10495 {
10496 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10497 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10498 hl, 0, 0, 0);
10499
10500 /* When we erase the cursor, and ROW is overlapped by other
10501 rows, make sure that these overlapping parts of other rows
10502 are redrawn. */
10503 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10504 {
10505 if (row > w->current_matrix->rows
10506 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10507 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10508
10509 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10510 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10511 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10512 }
10513 }
10514 }
10515
10516
10517 /* Erase the image of a cursor of window W from the screen. */
10518
10519 static void
10520 x_erase_phys_cursor (w)
10521 struct window *w;
10522 {
10523 struct frame *f = XFRAME (w->frame);
10524 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10525 int hpos = w->phys_cursor.hpos;
10526 int vpos = w->phys_cursor.vpos;
10527 int mouse_face_here_p = 0;
10528 struct glyph_matrix *active_glyphs = w->current_matrix;
10529 struct glyph_row *cursor_row;
10530 struct glyph *cursor_glyph;
10531 enum draw_glyphs_face hl;
10532
10533 /* No cursor displayed or row invalidated => nothing to do on the
10534 screen. */
10535 if (w->phys_cursor_type == NO_CURSOR)
10536 goto mark_cursor_off;
10537
10538 /* VPOS >= active_glyphs->nrows means that window has been resized.
10539 Don't bother to erase the cursor. */
10540 if (vpos >= active_glyphs->nrows)
10541 goto mark_cursor_off;
10542
10543 /* If row containing cursor is marked invalid, there is nothing we
10544 can do. */
10545 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10546 if (!cursor_row->enabled_p)
10547 goto mark_cursor_off;
10548
10549 /* This can happen when the new row is shorter than the old one.
10550 In this case, either x_draw_glyphs or clear_end_of_line
10551 should have cleared the cursor. Note that we wouldn't be
10552 able to erase the cursor in this case because we don't have a
10553 cursor glyph at hand. */
10554 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10555 goto mark_cursor_off;
10556
10557 /* If the cursor is in the mouse face area, redisplay that when
10558 we clear the cursor. */
10559 if (! NILP (dpyinfo->mouse_face_window)
10560 && w == XWINDOW (dpyinfo->mouse_face_window)
10561 && (vpos > dpyinfo->mouse_face_beg_row
10562 || (vpos == dpyinfo->mouse_face_beg_row
10563 && hpos >= dpyinfo->mouse_face_beg_col))
10564 && (vpos < dpyinfo->mouse_face_end_row
10565 || (vpos == dpyinfo->mouse_face_end_row
10566 && hpos < dpyinfo->mouse_face_end_col))
10567 /* Don't redraw the cursor's spot in mouse face if it is at the
10568 end of a line (on a newline). The cursor appears there, but
10569 mouse highlighting does not. */
10570 && cursor_row->used[TEXT_AREA] > hpos)
10571 mouse_face_here_p = 1;
10572
10573 /* Maybe clear the display under the cursor. */
10574 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10575 {
10576 int x;
10577 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10578
10579 cursor_glyph = get_phys_cursor_glyph (w);
10580 if (cursor_glyph == NULL)
10581 goto mark_cursor_off;
10582
10583 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10584
10585 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10586 x,
10587 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10588 cursor_row->y)),
10589 cursor_glyph->pixel_width,
10590 cursor_row->visible_height,
10591 False);
10592 }
10593
10594 /* Erase the cursor by redrawing the character underneath it. */
10595 if (mouse_face_here_p)
10596 hl = DRAW_MOUSE_FACE;
10597 else if (cursor_row->inverse_p)
10598 hl = DRAW_INVERSE_VIDEO;
10599 else
10600 hl = DRAW_NORMAL_TEXT;
10601 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10602
10603 mark_cursor_off:
10604 w->phys_cursor_on_p = 0;
10605 w->phys_cursor_type = NO_CURSOR;
10606 }
10607
10608
10609 /* Display or clear cursor of window W. If ON is zero, clear the
10610 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10611 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10612
10613 void
10614 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10615 struct window *w;
10616 int on, hpos, vpos, x, y;
10617 {
10618 struct frame *f = XFRAME (w->frame);
10619 int new_cursor_type;
10620 int new_cursor_width;
10621 struct glyph_matrix *current_glyphs;
10622 struct glyph_row *glyph_row;
10623 struct glyph *glyph;
10624
10625 /* This is pointless on invisible frames, and dangerous on garbaged
10626 windows and frames; in the latter case, the frame or window may
10627 be in the midst of changing its size, and x and y may be off the
10628 window. */
10629 if (! FRAME_VISIBLE_P (f)
10630 || FRAME_GARBAGED_P (f)
10631 || vpos >= w->current_matrix->nrows
10632 || hpos >= w->current_matrix->matrix_w)
10633 return;
10634
10635 /* If cursor is off and we want it off, return quickly. */
10636 if (!on && !w->phys_cursor_on_p)
10637 return;
10638
10639 current_glyphs = w->current_matrix;
10640 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10641 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10642
10643 /* If cursor row is not enabled, we don't really know where to
10644 display the cursor. */
10645 if (!glyph_row->enabled_p)
10646 {
10647 w->phys_cursor_on_p = 0;
10648 return;
10649 }
10650
10651 xassert (interrupt_input_blocked);
10652
10653 /* Set new_cursor_type to the cursor we want to be displayed. In a
10654 mini-buffer window, we want the cursor only to appear if we are
10655 reading input from this window. For the selected window, we want
10656 the cursor type given by the frame parameter. If explicitly
10657 marked off, draw no cursor. In all other cases, we want a hollow
10658 box cursor. */
10659 new_cursor_width = -1;
10660 if (cursor_in_echo_area
10661 && FRAME_HAS_MINIBUF_P (f)
10662 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10663 {
10664 if (w == XWINDOW (echo_area_window))
10665 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10666 else
10667 new_cursor_type = HOLLOW_BOX_CURSOR;
10668 }
10669 else
10670 {
10671 if (w != XWINDOW (selected_window)
10672 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10673 {
10674 extern int cursor_in_non_selected_windows;
10675
10676 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
10677 new_cursor_type = NO_CURSOR;
10678 else
10679 new_cursor_type = HOLLOW_BOX_CURSOR;
10680 }
10681 else if (w->cursor_off_p)
10682 new_cursor_type = NO_CURSOR;
10683 else
10684 {
10685 struct buffer *b = XBUFFER (w->buffer);
10686
10687 if (EQ (b->cursor_type, Qt))
10688 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10689 else
10690 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10691 &new_cursor_width);
10692 }
10693 }
10694
10695 /* If cursor is currently being shown and we don't want it to be or
10696 it is in the wrong place, or the cursor type is not what we want,
10697 erase it. */
10698 if (w->phys_cursor_on_p
10699 && (!on
10700 || w->phys_cursor.x != x
10701 || w->phys_cursor.y != y
10702 || new_cursor_type != w->phys_cursor_type))
10703 x_erase_phys_cursor (w);
10704
10705 /* If the cursor is now invisible and we want it to be visible,
10706 display it. */
10707 if (on && !w->phys_cursor_on_p)
10708 {
10709 w->phys_cursor_ascent = glyph_row->ascent;
10710 w->phys_cursor_height = glyph_row->height;
10711
10712 /* Set phys_cursor_.* before x_draw_.* is called because some
10713 of them may need the information. */
10714 w->phys_cursor.x = x;
10715 w->phys_cursor.y = glyph_row->y;
10716 w->phys_cursor.hpos = hpos;
10717 w->phys_cursor.vpos = vpos;
10718 w->phys_cursor_type = new_cursor_type;
10719 w->phys_cursor_on_p = 1;
10720
10721 switch (new_cursor_type)
10722 {
10723 case HOLLOW_BOX_CURSOR:
10724 x_draw_hollow_cursor (w, glyph_row);
10725 break;
10726
10727 case FILLED_BOX_CURSOR:
10728 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10729 break;
10730
10731 case BAR_CURSOR:
10732 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
10733 break;
10734
10735 case NO_CURSOR:
10736 break;
10737
10738 default:
10739 abort ();
10740 }
10741
10742 #ifdef HAVE_X_I18N
10743 if (w == XWINDOW (f->selected_window))
10744 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10745 xic_set_preeditarea (w, x, y);
10746 #endif
10747 }
10748
10749 #ifndef XFlush
10750 if (updating_frame != f)
10751 XFlush (FRAME_X_DISPLAY (f));
10752 #endif
10753 }
10754
10755
10756 /* Display the cursor on window W, or clear it. X and Y are window
10757 relative pixel coordinates. HPOS and VPOS are glyph matrix
10758 positions. If W is not the selected window, display a hollow
10759 cursor. ON non-zero means display the cursor at X, Y which
10760 correspond to HPOS, VPOS, otherwise it is cleared. */
10761
10762 void
10763 x_display_cursor (w, on, hpos, vpos, x, y)
10764 struct window *w;
10765 int on, hpos, vpos, x, y;
10766 {
10767 BLOCK_INPUT;
10768 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10769 UNBLOCK_INPUT;
10770 }
10771
10772
10773 /* Display the cursor on window W, or clear it, according to ON_P.
10774 Don't change the cursor's position. */
10775
10776 void
10777 x_update_cursor (f, on_p)
10778 struct frame *f;
10779 {
10780 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10781 }
10782
10783
10784 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10785 in the window tree rooted at W. */
10786
10787 static void
10788 x_update_cursor_in_window_tree (w, on_p)
10789 struct window *w;
10790 int on_p;
10791 {
10792 while (w)
10793 {
10794 if (!NILP (w->hchild))
10795 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10796 else if (!NILP (w->vchild))
10797 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10798 else
10799 x_update_window_cursor (w, on_p);
10800
10801 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10802 }
10803 }
10804
10805
10806 /* Switch the display of W's cursor on or off, according to the value
10807 of ON. */
10808
10809 static void
10810 x_update_window_cursor (w, on)
10811 struct window *w;
10812 int on;
10813 {
10814 /* Don't update cursor in windows whose frame is in the process
10815 of being deleted. */
10816 if (w->current_matrix)
10817 {
10818 BLOCK_INPUT;
10819 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10820 w->phys_cursor.x, w->phys_cursor.y);
10821 UNBLOCK_INPUT;
10822 }
10823 }
10824
10825
10826
10827 \f
10828 /* Icons. */
10829
10830 /* Refresh bitmap kitchen sink icon for frame F
10831 when we get an expose event for it. */
10832
10833 void
10834 refreshicon (f)
10835 struct frame *f;
10836 {
10837 /* Normally, the window manager handles this function. */
10838 }
10839
10840 /* Make the x-window of frame F use the gnu icon bitmap. */
10841
10842 int
10843 x_bitmap_icon (f, file)
10844 struct frame *f;
10845 Lisp_Object file;
10846 {
10847 int bitmap_id;
10848
10849 if (FRAME_X_WINDOW (f) == 0)
10850 return 1;
10851
10852 /* Free up our existing icon bitmap if any. */
10853 if (f->output_data.x->icon_bitmap > 0)
10854 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10855 f->output_data.x->icon_bitmap = 0;
10856
10857 if (STRINGP (file))
10858 bitmap_id = x_create_bitmap_from_file (f, file);
10859 else
10860 {
10861 /* Create the GNU bitmap if necessary. */
10862 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10863 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10864 = x_create_bitmap_from_data (f, gnu_bits,
10865 gnu_width, gnu_height);
10866
10867 /* The first time we create the GNU bitmap,
10868 this increments the ref-count one extra time.
10869 As a result, the GNU bitmap is never freed.
10870 That way, we don't have to worry about allocating it again. */
10871 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10872
10873 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10874 }
10875
10876 x_wm_set_icon_pixmap (f, bitmap_id);
10877 f->output_data.x->icon_bitmap = bitmap_id;
10878
10879 return 0;
10880 }
10881
10882
10883 /* Make the x-window of frame F use a rectangle with text.
10884 Use ICON_NAME as the text. */
10885
10886 int
10887 x_text_icon (f, icon_name)
10888 struct frame *f;
10889 char *icon_name;
10890 {
10891 if (FRAME_X_WINDOW (f) == 0)
10892 return 1;
10893
10894 #ifdef HAVE_X11R4
10895 {
10896 XTextProperty text;
10897 text.value = (unsigned char *) icon_name;
10898 text.encoding = XA_STRING;
10899 text.format = 8;
10900 text.nitems = strlen (icon_name);
10901 #ifdef USE_X_TOOLKIT
10902 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10903 &text);
10904 #else /* not USE_X_TOOLKIT */
10905 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10906 #endif /* not USE_X_TOOLKIT */
10907 }
10908 #else /* not HAVE_X11R4 */
10909 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10910 #endif /* not HAVE_X11R4 */
10911
10912 if (f->output_data.x->icon_bitmap > 0)
10913 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10914 f->output_data.x->icon_bitmap = 0;
10915 x_wm_set_icon_pixmap (f, 0);
10916
10917 return 0;
10918 }
10919 \f
10920 #define X_ERROR_MESSAGE_SIZE 200
10921
10922 /* If non-nil, this should be a string.
10923 It means catch X errors and store the error message in this string. */
10924
10925 static Lisp_Object x_error_message_string;
10926
10927 /* An X error handler which stores the error message in
10928 x_error_message_string. This is called from x_error_handler if
10929 x_catch_errors is in effect. */
10930
10931 static void
10932 x_error_catcher (display, error)
10933 Display *display;
10934 XErrorEvent *error;
10935 {
10936 XGetErrorText (display, error->error_code,
10937 XSTRING (x_error_message_string)->data,
10938 X_ERROR_MESSAGE_SIZE);
10939 }
10940
10941 /* Begin trapping X errors for display DPY. Actually we trap X errors
10942 for all displays, but DPY should be the display you are actually
10943 operating on.
10944
10945 After calling this function, X protocol errors no longer cause
10946 Emacs to exit; instead, they are recorded in the string
10947 stored in x_error_message_string.
10948
10949 Calling x_check_errors signals an Emacs error if an X error has
10950 occurred since the last call to x_catch_errors or x_check_errors.
10951
10952 Calling x_uncatch_errors resumes the normal error handling. */
10953
10954 void x_check_errors ();
10955 static Lisp_Object x_catch_errors_unwind ();
10956
10957 int
10958 x_catch_errors (dpy)
10959 Display *dpy;
10960 {
10961 int count = specpdl_ptr - specpdl;
10962
10963 /* Make sure any errors from previous requests have been dealt with. */
10964 XSync (dpy, False);
10965
10966 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10967
10968 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10969 XSTRING (x_error_message_string)->data[0] = 0;
10970
10971 return count;
10972 }
10973
10974 /* Unbind the binding that we made to check for X errors. */
10975
10976 static Lisp_Object
10977 x_catch_errors_unwind (old_val)
10978 Lisp_Object old_val;
10979 {
10980 x_error_message_string = old_val;
10981 return Qnil;
10982 }
10983
10984 /* If any X protocol errors have arrived since the last call to
10985 x_catch_errors or x_check_errors, signal an Emacs error using
10986 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10987
10988 void
10989 x_check_errors (dpy, format)
10990 Display *dpy;
10991 char *format;
10992 {
10993 /* Make sure to catch any errors incurred so far. */
10994 XSync (dpy, False);
10995
10996 if (XSTRING (x_error_message_string)->data[0])
10997 error (format, XSTRING (x_error_message_string)->data);
10998 }
10999
11000 /* Nonzero if we had any X protocol errors
11001 since we did x_catch_errors on DPY. */
11002
11003 int
11004 x_had_errors_p (dpy)
11005 Display *dpy;
11006 {
11007 /* Make sure to catch any errors incurred so far. */
11008 XSync (dpy, False);
11009
11010 return XSTRING (x_error_message_string)->data[0] != 0;
11011 }
11012
11013 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11014
11015 void
11016 x_clear_errors (dpy)
11017 Display *dpy;
11018 {
11019 XSTRING (x_error_message_string)->data[0] = 0;
11020 }
11021
11022 /* Stop catching X protocol errors and let them make Emacs die.
11023 DPY should be the display that was passed to x_catch_errors.
11024 COUNT should be the value that was returned by
11025 the corresponding call to x_catch_errors. */
11026
11027 void
11028 x_uncatch_errors (dpy, count)
11029 Display *dpy;
11030 int count;
11031 {
11032 unbind_to (count, Qnil);
11033 }
11034
11035 #if 0
11036 static unsigned int x_wire_count;
11037 x_trace_wire ()
11038 {
11039 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11040 }
11041 #endif /* ! 0 */
11042
11043 \f
11044 /* Handle SIGPIPE, which can happen when the connection to a server
11045 simply goes away. SIGPIPE is handled by x_connection_signal.
11046 Don't need to do anything, because the write which caused the
11047 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11048 which will do the appropriate cleanup for us. */
11049
11050 static SIGTYPE
11051 x_connection_signal (signalnum) /* If we don't have an argument, */
11052 int signalnum; /* some compilers complain in signal calls. */
11053 {
11054 #ifdef USG
11055 /* USG systems forget handlers when they are used;
11056 must reestablish each time */
11057 signal (signalnum, x_connection_signal);
11058 #endif /* USG */
11059 }
11060 \f
11061 /* Handling X errors. */
11062
11063 /* Handle the loss of connection to display DISPLAY. */
11064
11065 static SIGTYPE
11066 x_connection_closed (display, error_message)
11067 Display *display;
11068 char *error_message;
11069 {
11070 struct x_display_info *dpyinfo = x_display_info_for_display (display);
11071 Lisp_Object frame, tail;
11072
11073 /* Indicate that this display is dead. */
11074
11075 #if 0 /* Closing the display caused a bus error on OpenWindows. */
11076 #ifdef USE_X_TOOLKIT
11077 XtCloseDisplay (display);
11078 #endif
11079 #endif
11080
11081 if (dpyinfo)
11082 dpyinfo->display = 0;
11083
11084 /* First delete frames whose mini-buffers are on frames
11085 that are on the dead display. */
11086 FOR_EACH_FRAME (tail, frame)
11087 {
11088 Lisp_Object minibuf_frame;
11089 minibuf_frame
11090 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11091 if (FRAME_X_P (XFRAME (frame))
11092 && FRAME_X_P (XFRAME (minibuf_frame))
11093 && ! EQ (frame, minibuf_frame)
11094 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11095 Fdelete_frame (frame, Qt);
11096 }
11097
11098 /* Now delete all remaining frames on the dead display.
11099 We are now sure none of these is used as the mini-buffer
11100 for another frame that we need to delete. */
11101 FOR_EACH_FRAME (tail, frame)
11102 if (FRAME_X_P (XFRAME (frame))
11103 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11104 {
11105 /* Set this to t so that Fdelete_frame won't get confused
11106 trying to find a replacement. */
11107 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11108 Fdelete_frame (frame, Qt);
11109 }
11110
11111 if (dpyinfo)
11112 x_delete_display (dpyinfo);
11113
11114 if (x_display_list == 0)
11115 {
11116 fprintf (stderr, "%s\n", error_message);
11117 shut_down_emacs (0, 0, Qnil);
11118 exit (70);
11119 }
11120
11121 /* Ordinary stack unwind doesn't deal with these. */
11122 #ifdef SIGIO
11123 sigunblock (sigmask (SIGIO));
11124 #endif
11125 sigunblock (sigmask (SIGALRM));
11126 TOTALLY_UNBLOCK_INPUT;
11127
11128 clear_waiting_for_input ();
11129 error ("%s", error_message);
11130 }
11131
11132 /* This is the usual handler for X protocol errors.
11133 It kills all frames on the display that we got the error for.
11134 If that was the only one, it prints an error message and kills Emacs. */
11135
11136 static void
11137 x_error_quitter (display, error)
11138 Display *display;
11139 XErrorEvent *error;
11140 {
11141 char buf[256], buf1[356];
11142
11143 /* Note that there is no real way portable across R3/R4 to get the
11144 original error handler. */
11145
11146 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11147 sprintf (buf1, "X protocol error: %s on protocol request %d",
11148 buf, error->request_code);
11149 x_connection_closed (display, buf1);
11150 }
11151
11152 /* This is the first-level handler for X protocol errors.
11153 It calls x_error_quitter or x_error_catcher. */
11154
11155 static int
11156 x_error_handler (display, error)
11157 Display *display;
11158 XErrorEvent *error;
11159 {
11160 if (! NILP (x_error_message_string))
11161 x_error_catcher (display, error);
11162 else
11163 x_error_quitter (display, error);
11164 return 0;
11165 }
11166
11167 /* This is the handler for X IO errors, always.
11168 It kills all frames on the display that we lost touch with.
11169 If that was the only one, it prints an error message and kills Emacs. */
11170
11171 static int
11172 x_io_error_quitter (display)
11173 Display *display;
11174 {
11175 char buf[256];
11176
11177 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11178 x_connection_closed (display, buf);
11179 return 0;
11180 }
11181 \f
11182 /* Changing the font of the frame. */
11183
11184 /* Give frame F the font named FONTNAME as its default font, and
11185 return the full name of that font. FONTNAME may be a wildcard
11186 pattern; in that case, we choose some font that fits the pattern.
11187 The return value shows which font we chose. */
11188
11189 Lisp_Object
11190 x_new_font (f, fontname)
11191 struct frame *f;
11192 register char *fontname;
11193 {
11194 struct font_info *fontp
11195 = FS_LOAD_FONT (f, 0, fontname, -1);
11196
11197 if (!fontp)
11198 return Qnil;
11199
11200 f->output_data.x->font = (XFontStruct *) (fontp->font);
11201 f->output_data.x->baseline_offset = fontp->baseline_offset;
11202 f->output_data.x->fontset = -1;
11203
11204 /* Compute the scroll bar width in character columns. */
11205 if (f->scroll_bar_pixel_width > 0)
11206 {
11207 int wid = FONT_WIDTH (f->output_data.x->font);
11208 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11209 }
11210 else
11211 {
11212 int wid = FONT_WIDTH (f->output_data.x->font);
11213 f->scroll_bar_cols = (14 + wid - 1) / wid;
11214 }
11215
11216 /* Now make the frame display the given font. */
11217 if (FRAME_X_WINDOW (f) != 0)
11218 {
11219 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11220 f->output_data.x->font->fid);
11221 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11222 f->output_data.x->font->fid);
11223 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11224 f->output_data.x->font->fid);
11225
11226 frame_update_line_height (f);
11227 x_set_window_size (f, 0, f->width, f->height);
11228 }
11229 else
11230 /* If we are setting a new frame's font for the first time,
11231 there are no faces yet, so this font's height is the line height. */
11232 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11233
11234 return build_string (fontp->full_name);
11235 }
11236
11237 /* Give frame F the fontset named FONTSETNAME as its default font, and
11238 return the full name of that fontset. FONTSETNAME may be a wildcard
11239 pattern; in that case, we choose some fontset that fits the pattern.
11240 The return value shows which fontset we chose. */
11241
11242 Lisp_Object
11243 x_new_fontset (f, fontsetname)
11244 struct frame *f;
11245 char *fontsetname;
11246 {
11247 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11248 Lisp_Object result;
11249
11250 if (fontset < 0)
11251 return Qnil;
11252
11253 if (f->output_data.x->fontset == fontset)
11254 /* This fontset is already set in frame F. There's nothing more
11255 to do. */
11256 return fontset_name (fontset);
11257
11258 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11259
11260 if (!STRINGP (result))
11261 /* Can't load ASCII font. */
11262 return Qnil;
11263
11264 /* Since x_new_font doesn't update any fontset information, do it now. */
11265 f->output_data.x->fontset = fontset;
11266
11267 #ifdef HAVE_X_I18N
11268 if (FRAME_XIC (f)
11269 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11270 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11271 #endif
11272
11273 return build_string (fontsetname);
11274 }
11275
11276 \f
11277 /***********************************************************************
11278 X Input Methods
11279 ***********************************************************************/
11280
11281 #ifdef HAVE_X_I18N
11282
11283 #ifdef HAVE_X11R6
11284
11285 /* XIM destroy callback function, which is called whenever the
11286 connection to input method XIM dies. CLIENT_DATA contains a
11287 pointer to the x_display_info structure corresponding to XIM. */
11288
11289 static void
11290 xim_destroy_callback (xim, client_data, call_data)
11291 XIM xim;
11292 XPointer client_data;
11293 XPointer call_data;
11294 {
11295 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11296 Lisp_Object frame, tail;
11297
11298 BLOCK_INPUT;
11299
11300 /* No need to call XDestroyIC.. */
11301 FOR_EACH_FRAME (tail, frame)
11302 {
11303 struct frame *f = XFRAME (frame);
11304 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11305 {
11306 FRAME_XIC (f) = NULL;
11307 if (FRAME_XIC_FONTSET (f))
11308 {
11309 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11310 FRAME_XIC_FONTSET (f) = NULL;
11311 }
11312 }
11313 }
11314
11315 /* No need to call XCloseIM. */
11316 dpyinfo->xim = NULL;
11317 XFree (dpyinfo->xim_styles);
11318 UNBLOCK_INPUT;
11319 }
11320
11321 #endif /* HAVE_X11R6 */
11322
11323 /* Open the connection to the XIM server on display DPYINFO.
11324 RESOURCE_NAME is the resource name Emacs uses. */
11325
11326 static void
11327 xim_open_dpy (dpyinfo, resource_name)
11328 struct x_display_info *dpyinfo;
11329 char *resource_name;
11330 {
11331 #ifdef USE_XIM
11332 XIM xim;
11333
11334 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11335 dpyinfo->xim = xim;
11336
11337 if (xim)
11338 {
11339 #ifdef HAVE_X11R6
11340 XIMCallback destroy;
11341 #endif
11342
11343 /* Get supported styles and XIM values. */
11344 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11345
11346 #ifdef HAVE_X11R6
11347 destroy.callback = xim_destroy_callback;
11348 destroy.client_data = (XPointer)dpyinfo;
11349 /* This isn't prptotyped in OSF 5.0. */
11350 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11351 #endif
11352 }
11353
11354 #else /* not USE_XIM */
11355 dpyinfo->xim = NULL;
11356 #endif /* not USE_XIM */
11357 }
11358
11359
11360 #ifdef HAVE_X11R6_XIM
11361
11362 struct xim_inst_t
11363 {
11364 struct x_display_info *dpyinfo;
11365 char *resource_name;
11366 };
11367
11368 /* XIM instantiate callback function, which is called whenever an XIM
11369 server is available. DISPLAY is teh display of the XIM.
11370 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11371 when the callback was registered. */
11372
11373 static void
11374 xim_instantiate_callback (display, client_data, call_data)
11375 Display *display;
11376 XPointer client_data;
11377 XPointer call_data;
11378 {
11379 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11380 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11381
11382 /* We don't support multiple XIM connections. */
11383 if (dpyinfo->xim)
11384 return;
11385
11386 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11387
11388 /* Create XIC for the existing frames on the same display, as long
11389 as they have no XIC. */
11390 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11391 {
11392 Lisp_Object tail, frame;
11393
11394 BLOCK_INPUT;
11395 FOR_EACH_FRAME (tail, frame)
11396 {
11397 struct frame *f = XFRAME (frame);
11398
11399 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11400 if (FRAME_XIC (f) == NULL)
11401 {
11402 create_frame_xic (f);
11403 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11404 xic_set_statusarea (f);
11405 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11406 {
11407 struct window *w = XWINDOW (f->selected_window);
11408 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11409 }
11410 }
11411 }
11412
11413 UNBLOCK_INPUT;
11414 }
11415 }
11416
11417 #endif /* HAVE_X11R6_XIM */
11418
11419
11420 /* Open a connection to the XIM server on display DPYINFO.
11421 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11422 connection only at the first time. On X11R6, open the connection
11423 in the XIM instantiate callback function. */
11424
11425 static void
11426 xim_initialize (dpyinfo, resource_name)
11427 struct x_display_info *dpyinfo;
11428 char *resource_name;
11429 {
11430 #ifdef USE_XIM
11431 #ifdef HAVE_X11R6_XIM
11432 struct xim_inst_t *xim_inst;
11433 int len;
11434
11435 dpyinfo->xim = NULL;
11436 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11437 xim_inst->dpyinfo = dpyinfo;
11438 len = strlen (resource_name);
11439 xim_inst->resource_name = (char *) xmalloc (len + 1);
11440 bcopy (resource_name, xim_inst->resource_name, len + 1);
11441 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11442 resource_name, EMACS_CLASS,
11443 xim_instantiate_callback,
11444 /* Fixme: This is XPointer in
11445 XFree86 but (XPointer *) on
11446 Tru64, at least. */
11447 (XPointer) xim_inst);
11448 #else /* not HAVE_X11R6_XIM */
11449 dpyinfo->xim = NULL;
11450 xim_open_dpy (dpyinfo, resource_name);
11451 #endif /* not HAVE_X11R6_XIM */
11452
11453 #else /* not USE_XIM */
11454 dpyinfo->xim = NULL;
11455 #endif /* not USE_XIM */
11456 }
11457
11458
11459 /* Close the connection to the XIM server on display DPYINFO. */
11460
11461 static void
11462 xim_close_dpy (dpyinfo)
11463 struct x_display_info *dpyinfo;
11464 {
11465 #ifdef USE_XIM
11466 #ifdef HAVE_X11R6_XIM
11467 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11468 NULL, EMACS_CLASS,
11469 xim_instantiate_callback, NULL);
11470 #endif /* not HAVE_X11R6_XIM */
11471 XCloseIM (dpyinfo->xim);
11472 dpyinfo->xim = NULL;
11473 XFree (dpyinfo->xim_styles);
11474 #endif /* USE_XIM */
11475 }
11476
11477 #endif /* not HAVE_X11R6_XIM */
11478
11479
11480 \f
11481 /* Calculate the absolute position in frame F
11482 from its current recorded position values and gravity. */
11483
11484 void
11485 x_calc_absolute_position (f)
11486 struct frame *f;
11487 {
11488 Window child;
11489 int win_x = 0, win_y = 0;
11490 int flags = f->output_data.x->size_hint_flags;
11491 int this_window;
11492
11493 /* We have nothing to do if the current position
11494 is already for the top-left corner. */
11495 if (! ((flags & XNegative) || (flags & YNegative)))
11496 return;
11497
11498 #ifdef USE_X_TOOLKIT
11499 this_window = XtWindow (f->output_data.x->widget);
11500 #else
11501 this_window = FRAME_X_WINDOW (f);
11502 #endif
11503
11504 /* Find the position of the outside upper-left corner of
11505 the inner window, with respect to the outer window.
11506 But do this only if we will need the results. */
11507 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11508 {
11509 int count;
11510
11511 BLOCK_INPUT;
11512 count = x_catch_errors (FRAME_X_DISPLAY (f));
11513 while (1)
11514 {
11515 x_clear_errors (FRAME_X_DISPLAY (f));
11516 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11517
11518 /* From-window, to-window. */
11519 this_window,
11520 f->output_data.x->parent_desc,
11521
11522 /* From-position, to-position. */
11523 0, 0, &win_x, &win_y,
11524
11525 /* Child of win. */
11526 &child);
11527 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11528 {
11529 Window newroot, newparent = 0xdeadbeef;
11530 Window *newchildren;
11531 unsigned int nchildren;
11532
11533 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11534 &newparent, &newchildren, &nchildren))
11535 break;
11536
11537 XFree ((char *) newchildren);
11538
11539 f->output_data.x->parent_desc = newparent;
11540 }
11541 else
11542 break;
11543 }
11544
11545 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11546 UNBLOCK_INPUT;
11547 }
11548
11549 /* Treat negative positions as relative to the leftmost bottommost
11550 position that fits on the screen. */
11551 if (flags & XNegative)
11552 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11553 - 2 * f->output_data.x->border_width - win_x
11554 - PIXEL_WIDTH (f)
11555 + f->output_data.x->left_pos);
11556
11557 if (flags & YNegative)
11558 {
11559 int menubar_height = 0;
11560
11561 #ifdef USE_X_TOOLKIT
11562 if (f->output_data.x->menubar_widget)
11563 menubar_height
11564 = (f->output_data.x->menubar_widget->core.height
11565 + f->output_data.x->menubar_widget->core.border_width);
11566 #endif
11567
11568 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11569 - 2 * f->output_data.x->border_width
11570 - win_y
11571 - PIXEL_HEIGHT (f)
11572 - menubar_height
11573 + f->output_data.x->top_pos);
11574 }
11575
11576 /* The left_pos and top_pos
11577 are now relative to the top and left screen edges,
11578 so the flags should correspond. */
11579 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11580 }
11581
11582 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11583 to really change the position, and 0 when calling from
11584 x_make_frame_visible (in that case, XOFF and YOFF are the current
11585 position values). It is -1 when calling from x_set_frame_parameters,
11586 which means, do adjust for borders but don't change the gravity. */
11587
11588 void
11589 x_set_offset (f, xoff, yoff, change_gravity)
11590 struct frame *f;
11591 register int xoff, yoff;
11592 int change_gravity;
11593 {
11594 int modified_top, modified_left;
11595
11596 if (change_gravity > 0)
11597 {
11598 f->output_data.x->top_pos = yoff;
11599 f->output_data.x->left_pos = xoff;
11600 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11601 if (xoff < 0)
11602 f->output_data.x->size_hint_flags |= XNegative;
11603 if (yoff < 0)
11604 f->output_data.x->size_hint_flags |= YNegative;
11605 f->output_data.x->win_gravity = NorthWestGravity;
11606 }
11607 x_calc_absolute_position (f);
11608
11609 BLOCK_INPUT;
11610 x_wm_set_size_hint (f, (long) 0, 0);
11611
11612 modified_left = f->output_data.x->left_pos;
11613 modified_top = f->output_data.x->top_pos;
11614 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11615 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11616 /* It is a mystery why we need to add the border_width here
11617 when the frame is already visible, but experiment says we do. */
11618 if (change_gravity != 0)
11619 {
11620 modified_left += f->output_data.x->border_width;
11621 modified_top += f->output_data.x->border_width;
11622 }
11623 #endif
11624
11625 #ifdef USE_X_TOOLKIT
11626 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11627 modified_left, modified_top);
11628 #else /* not USE_X_TOOLKIT */
11629 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11630 modified_left, modified_top);
11631 #endif /* not USE_X_TOOLKIT */
11632 UNBLOCK_INPUT;
11633 }
11634
11635 /* Call this to change the size of frame F's x-window.
11636 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11637 for this size change and subsequent size changes.
11638 Otherwise we leave the window gravity unchanged. */
11639
11640 void
11641 x_set_window_size (f, change_gravity, cols, rows)
11642 struct frame *f;
11643 int change_gravity;
11644 int cols, rows;
11645 {
11646 #ifndef USE_X_TOOLKIT
11647 int pixelwidth, pixelheight;
11648 #endif
11649
11650 BLOCK_INPUT;
11651
11652 #ifdef USE_X_TOOLKIT
11653 {
11654 /* The x and y position of the widget is clobbered by the
11655 call to XtSetValues within EmacsFrameSetCharSize.
11656 This is a real kludge, but I don't understand Xt so I can't
11657 figure out a correct fix. Can anyone else tell me? -- rms. */
11658 int xpos = f->output_data.x->widget->core.x;
11659 int ypos = f->output_data.x->widget->core.y;
11660 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11661 f->output_data.x->widget->core.x = xpos;
11662 f->output_data.x->widget->core.y = ypos;
11663 }
11664
11665 #else /* not USE_X_TOOLKIT */
11666
11667 check_frame_size (f, &rows, &cols);
11668 f->output_data.x->vertical_scroll_bar_extra
11669 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11670 ? 0
11671 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11672 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11673 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11674 f->output_data.x->flags_areas_extra
11675 = FRAME_FLAGS_AREA_WIDTH (f);
11676 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11677 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11678
11679 f->output_data.x->win_gravity = NorthWestGravity;
11680 x_wm_set_size_hint (f, (long) 0, 0);
11681
11682 XSync (FRAME_X_DISPLAY (f), False);
11683 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11684 pixelwidth, pixelheight);
11685
11686 /* Now, strictly speaking, we can't be sure that this is accurate,
11687 but the window manager will get around to dealing with the size
11688 change request eventually, and we'll hear how it went when the
11689 ConfigureNotify event gets here.
11690
11691 We could just not bother storing any of this information here,
11692 and let the ConfigureNotify event set everything up, but that
11693 might be kind of confusing to the Lisp code, since size changes
11694 wouldn't be reported in the frame parameters until some random
11695 point in the future when the ConfigureNotify event arrives.
11696
11697 We pass 1 for DELAY since we can't run Lisp code inside of
11698 a BLOCK_INPUT. */
11699 change_frame_size (f, rows, cols, 0, 1, 0);
11700 PIXEL_WIDTH (f) = pixelwidth;
11701 PIXEL_HEIGHT (f) = pixelheight;
11702
11703 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11704 receive in the ConfigureNotify event; if we get what we asked
11705 for, then the event won't cause the screen to become garbaged, so
11706 we have to make sure to do it here. */
11707 SET_FRAME_GARBAGED (f);
11708
11709 XFlush (FRAME_X_DISPLAY (f));
11710
11711 #endif /* not USE_X_TOOLKIT */
11712
11713 /* If cursor was outside the new size, mark it as off. */
11714 mark_window_cursors_off (XWINDOW (f->root_window));
11715
11716 /* Clear out any recollection of where the mouse highlighting was,
11717 since it might be in a place that's outside the new frame size.
11718 Actually checking whether it is outside is a pain in the neck,
11719 so don't try--just let the highlighting be done afresh with new size. */
11720 cancel_mouse_face (f);
11721
11722 UNBLOCK_INPUT;
11723 }
11724 \f
11725 /* Mouse warping. */
11726
11727 void
11728 x_set_mouse_position (f, x, y)
11729 struct frame *f;
11730 int x, y;
11731 {
11732 int pix_x, pix_y;
11733
11734 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11735 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11736
11737 if (pix_x < 0) pix_x = 0;
11738 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11739
11740 if (pix_y < 0) pix_y = 0;
11741 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11742
11743 BLOCK_INPUT;
11744
11745 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11746 0, 0, 0, 0, pix_x, pix_y);
11747 UNBLOCK_INPUT;
11748 }
11749
11750 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11751
11752 void
11753 x_set_mouse_pixel_position (f, pix_x, pix_y)
11754 struct frame *f;
11755 int pix_x, pix_y;
11756 {
11757 BLOCK_INPUT;
11758
11759 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11760 0, 0, 0, 0, pix_x, pix_y);
11761 UNBLOCK_INPUT;
11762 }
11763 \f
11764 /* focus shifting, raising and lowering. */
11765
11766 void
11767 x_focus_on_frame (f)
11768 struct frame *f;
11769 {
11770 #if 0 /* This proves to be unpleasant. */
11771 x_raise_frame (f);
11772 #endif
11773 #if 0
11774 /* I don't think that the ICCCM allows programs to do things like this
11775 without the interaction of the window manager. Whatever you end up
11776 doing with this code, do it to x_unfocus_frame too. */
11777 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11778 RevertToPointerRoot, CurrentTime);
11779 #endif /* ! 0 */
11780 }
11781
11782 void
11783 x_unfocus_frame (f)
11784 struct frame *f;
11785 {
11786 #if 0
11787 /* Look at the remarks in x_focus_on_frame. */
11788 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11789 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11790 RevertToPointerRoot, CurrentTime);
11791 #endif /* ! 0 */
11792 }
11793
11794 /* Raise frame F. */
11795
11796 void
11797 x_raise_frame (f)
11798 struct frame *f;
11799 {
11800 if (f->async_visible)
11801 {
11802 BLOCK_INPUT;
11803 #ifdef USE_X_TOOLKIT
11804 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11805 #else /* not USE_X_TOOLKIT */
11806 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11807 #endif /* not USE_X_TOOLKIT */
11808 XFlush (FRAME_X_DISPLAY (f));
11809 UNBLOCK_INPUT;
11810 }
11811 }
11812
11813 /* Lower frame F. */
11814
11815 void
11816 x_lower_frame (f)
11817 struct frame *f;
11818 {
11819 if (f->async_visible)
11820 {
11821 BLOCK_INPUT;
11822 #ifdef USE_X_TOOLKIT
11823 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11824 #else /* not USE_X_TOOLKIT */
11825 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11826 #endif /* not USE_X_TOOLKIT */
11827 XFlush (FRAME_X_DISPLAY (f));
11828 UNBLOCK_INPUT;
11829 }
11830 }
11831
11832 static void
11833 XTframe_raise_lower (f, raise_flag)
11834 FRAME_PTR f;
11835 int raise_flag;
11836 {
11837 if (raise_flag)
11838 x_raise_frame (f);
11839 else
11840 x_lower_frame (f);
11841 }
11842 \f
11843 /* Change of visibility. */
11844
11845 /* This tries to wait until the frame is really visible.
11846 However, if the window manager asks the user where to position
11847 the frame, this will return before the user finishes doing that.
11848 The frame will not actually be visible at that time,
11849 but it will become visible later when the window manager
11850 finishes with it. */
11851
11852 void
11853 x_make_frame_visible (f)
11854 struct frame *f;
11855 {
11856 Lisp_Object type;
11857 int original_top, original_left;
11858
11859 BLOCK_INPUT;
11860
11861 type = x_icon_type (f);
11862 if (!NILP (type))
11863 x_bitmap_icon (f, type);
11864
11865 if (! FRAME_VISIBLE_P (f))
11866 {
11867 /* We test FRAME_GARBAGED_P here to make sure we don't
11868 call x_set_offset a second time
11869 if we get to x_make_frame_visible a second time
11870 before the window gets really visible. */
11871 if (! FRAME_ICONIFIED_P (f)
11872 && ! f->output_data.x->asked_for_visible)
11873 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11874
11875 f->output_data.x->asked_for_visible = 1;
11876
11877 if (! EQ (Vx_no_window_manager, Qt))
11878 x_wm_set_window_state (f, NormalState);
11879 #ifdef USE_X_TOOLKIT
11880 /* This was XtPopup, but that did nothing for an iconified frame. */
11881 XtMapWidget (f->output_data.x->widget);
11882 #else /* not USE_X_TOOLKIT */
11883 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11884 #endif /* not USE_X_TOOLKIT */
11885 #if 0 /* This seems to bring back scroll bars in the wrong places
11886 if the window configuration has changed. They seem
11887 to come back ok without this. */
11888 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
11889 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11890 #endif
11891 }
11892
11893 XFlush (FRAME_X_DISPLAY (f));
11894
11895 /* Synchronize to ensure Emacs knows the frame is visible
11896 before we do anything else. We do this loop with input not blocked
11897 so that incoming events are handled. */
11898 {
11899 Lisp_Object frame;
11900 int count;
11901 /* This must be before UNBLOCK_INPUT
11902 since events that arrive in response to the actions above
11903 will set it when they are handled. */
11904 int previously_visible = f->output_data.x->has_been_visible;
11905
11906 original_left = f->output_data.x->left_pos;
11907 original_top = f->output_data.x->top_pos;
11908
11909 /* This must come after we set COUNT. */
11910 UNBLOCK_INPUT;
11911
11912 /* We unblock here so that arriving X events are processed. */
11913
11914 /* Now move the window back to where it was "supposed to be".
11915 But don't do it if the gravity is negative.
11916 When the gravity is negative, this uses a position
11917 that is 3 pixels too low. Perhaps that's really the border width.
11918
11919 Don't do this if the window has never been visible before,
11920 because the window manager may choose the position
11921 and we don't want to override it. */
11922
11923 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
11924 && f->output_data.x->win_gravity == NorthWestGravity
11925 && previously_visible)
11926 {
11927 Drawable rootw;
11928 int x, y;
11929 unsigned int width, height, border, depth;
11930
11931 BLOCK_INPUT;
11932
11933 /* On some window managers (such as FVWM) moving an existing
11934 window, even to the same place, causes the window manager
11935 to introduce an offset. This can cause the window to move
11936 to an unexpected location. Check the geometry (a little
11937 slow here) and then verify that the window is in the right
11938 place. If the window is not in the right place, move it
11939 there, and take the potential window manager hit. */
11940 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11941 &rootw, &x, &y, &width, &height, &border, &depth);
11942
11943 if (original_left != x || original_top != y)
11944 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11945 original_left, original_top);
11946
11947 UNBLOCK_INPUT;
11948 }
11949
11950 XSETFRAME (frame, f);
11951
11952 /* Wait until the frame is visible. Process X events until a
11953 MapNotify event has been seen, or until we think we won't get a
11954 MapNotify at all.. */
11955 for (count = input_signal_count + 10;
11956 input_signal_count < count && !FRAME_VISIBLE_P (f);)
11957 {
11958 /* Force processing of queued events. */
11959 x_sync (f);
11960
11961 /* Machines that do polling rather than SIGIO have been
11962 observed to go into a busy-wait here. So we'll fake an
11963 alarm signal to let the handler know that there's something
11964 to be read. We used to raise a real alarm, but it seems
11965 that the handler isn't always enabled here. This is
11966 probably a bug. */
11967 if (input_polling_used ())
11968 {
11969 /* It could be confusing if a real alarm arrives while
11970 processing the fake one. Turn it off and let the
11971 handler reset it. */
11972 extern void poll_for_input_1 P_ ((void));
11973 int old_poll_suppress_count = poll_suppress_count;
11974 poll_suppress_count = 1;
11975 poll_for_input_1 ();
11976 poll_suppress_count = old_poll_suppress_count;
11977 }
11978
11979 /* See if a MapNotify event has been processed. */
11980 FRAME_SAMPLE_VISIBILITY (f);
11981 }
11982 }
11983 }
11984
11985 /* Change from mapped state to withdrawn state. */
11986
11987 /* Make the frame visible (mapped and not iconified). */
11988
11989 void
11990 x_make_frame_invisible (f)
11991 struct frame *f;
11992 {
11993 Window window;
11994
11995 #ifdef USE_X_TOOLKIT
11996 /* Use the frame's outermost window, not the one we normally draw on. */
11997 window = XtWindow (f->output_data.x->widget);
11998 #else /* not USE_X_TOOLKIT */
11999 window = FRAME_X_WINDOW (f);
12000 #endif /* not USE_X_TOOLKIT */
12001
12002 /* Don't keep the highlight on an invisible frame. */
12003 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12004 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12005
12006 #if 0/* This might add unreliability; I don't trust it -- rms. */
12007 if (! f->async_visible && ! f->async_iconified)
12008 return;
12009 #endif
12010
12011 BLOCK_INPUT;
12012
12013 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12014 that the current position of the window is user-specified, rather than
12015 program-specified, so that when the window is mapped again, it will be
12016 placed at the same location, without forcing the user to position it
12017 by hand again (they have already done that once for this window.) */
12018 x_wm_set_size_hint (f, (long) 0, 1);
12019
12020 #ifdef HAVE_X11R4
12021
12022 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12023 DefaultScreen (FRAME_X_DISPLAY (f))))
12024 {
12025 UNBLOCK_INPUT_RESIGNAL;
12026 error ("Can't notify window manager of window withdrawal");
12027 }
12028 #else /* ! defined (HAVE_X11R4) */
12029
12030 /* Tell the window manager what we're going to do. */
12031 if (! EQ (Vx_no_window_manager, Qt))
12032 {
12033 XEvent unmap;
12034
12035 unmap.xunmap.type = UnmapNotify;
12036 unmap.xunmap.window = window;
12037 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12038 unmap.xunmap.from_configure = False;
12039 if (! XSendEvent (FRAME_X_DISPLAY (f),
12040 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12041 False,
12042 SubstructureRedirectMaskSubstructureNotifyMask,
12043 &unmap))
12044 {
12045 UNBLOCK_INPUT_RESIGNAL;
12046 error ("Can't notify window manager of withdrawal");
12047 }
12048 }
12049
12050 /* Unmap the window ourselves. Cheeky! */
12051 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12052 #endif /* ! defined (HAVE_X11R4) */
12053
12054 /* We can't distinguish this from iconification
12055 just by the event that we get from the server.
12056 So we can't win using the usual strategy of letting
12057 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12058 and synchronize with the server to make sure we agree. */
12059 f->visible = 0;
12060 FRAME_ICONIFIED_P (f) = 0;
12061 f->async_visible = 0;
12062 f->async_iconified = 0;
12063
12064 x_sync (f);
12065
12066 UNBLOCK_INPUT;
12067 }
12068
12069 /* Change window state from mapped to iconified. */
12070
12071 void
12072 x_iconify_frame (f)
12073 struct frame *f;
12074 {
12075 int result;
12076 Lisp_Object type;
12077
12078 /* Don't keep the highlight on an invisible frame. */
12079 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12080 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12081
12082 if (f->async_iconified)
12083 return;
12084
12085 BLOCK_INPUT;
12086
12087 FRAME_SAMPLE_VISIBILITY (f);
12088
12089 type = x_icon_type (f);
12090 if (!NILP (type))
12091 x_bitmap_icon (f, type);
12092
12093 #ifdef USE_X_TOOLKIT
12094
12095 if (! FRAME_VISIBLE_P (f))
12096 {
12097 if (! EQ (Vx_no_window_manager, Qt))
12098 x_wm_set_window_state (f, IconicState);
12099 /* This was XtPopup, but that did nothing for an iconified frame. */
12100 XtMapWidget (f->output_data.x->widget);
12101 /* The server won't give us any event to indicate
12102 that an invisible frame was changed to an icon,
12103 so we have to record it here. */
12104 f->iconified = 1;
12105 f->visible = 1;
12106 f->async_iconified = 1;
12107 f->async_visible = 0;
12108 UNBLOCK_INPUT;
12109 return;
12110 }
12111
12112 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12113 XtWindow (f->output_data.x->widget),
12114 DefaultScreen (FRAME_X_DISPLAY (f)));
12115 UNBLOCK_INPUT;
12116
12117 if (!result)
12118 error ("Can't notify window manager of iconification");
12119
12120 f->async_iconified = 1;
12121 f->async_visible = 0;
12122
12123
12124 BLOCK_INPUT;
12125 XFlush (FRAME_X_DISPLAY (f));
12126 UNBLOCK_INPUT;
12127 #else /* not USE_X_TOOLKIT */
12128
12129 /* Make sure the X server knows where the window should be positioned,
12130 in case the user deiconifies with the window manager. */
12131 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12132 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12133
12134 /* Since we don't know which revision of X we're running, we'll use both
12135 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12136
12137 /* X11R4: send a ClientMessage to the window manager using the
12138 WM_CHANGE_STATE type. */
12139 {
12140 XEvent message;
12141
12142 message.xclient.window = FRAME_X_WINDOW (f);
12143 message.xclient.type = ClientMessage;
12144 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12145 message.xclient.format = 32;
12146 message.xclient.data.l[0] = IconicState;
12147
12148 if (! XSendEvent (FRAME_X_DISPLAY (f),
12149 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12150 False,
12151 SubstructureRedirectMask | SubstructureNotifyMask,
12152 &message))
12153 {
12154 UNBLOCK_INPUT_RESIGNAL;
12155 error ("Can't notify window manager of iconification");
12156 }
12157 }
12158
12159 /* X11R3: set the initial_state field of the window manager hints to
12160 IconicState. */
12161 x_wm_set_window_state (f, IconicState);
12162
12163 if (!FRAME_VISIBLE_P (f))
12164 {
12165 /* If the frame was withdrawn, before, we must map it. */
12166 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12167 }
12168
12169 f->async_iconified = 1;
12170 f->async_visible = 0;
12171
12172 XFlush (FRAME_X_DISPLAY (f));
12173 UNBLOCK_INPUT;
12174 #endif /* not USE_X_TOOLKIT */
12175 }
12176 \f
12177 /* Destroy the X window of frame F. */
12178
12179 void
12180 x_destroy_window (f)
12181 struct frame *f;
12182 {
12183 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12184
12185 BLOCK_INPUT;
12186
12187 /* If a display connection is dead, don't try sending more
12188 commands to the X server. */
12189 if (dpyinfo->display != 0)
12190 {
12191 if (f->output_data.x->icon_desc != 0)
12192 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12193 #ifdef HAVE_X_I18N
12194 if (FRAME_XIC (f))
12195 free_frame_xic (f);
12196 #endif
12197 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
12198 #ifdef USE_X_TOOLKIT
12199 if (f->output_data.x->widget)
12200 XtDestroyWidget (f->output_data.x->widget);
12201 free_frame_menubar (f);
12202 #endif /* USE_X_TOOLKIT */
12203
12204 unload_color (f, f->output_data.x->foreground_pixel);
12205 unload_color (f, f->output_data.x->background_pixel);
12206 unload_color (f, f->output_data.x->cursor_pixel);
12207 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12208 unload_color (f, f->output_data.x->border_pixel);
12209 unload_color (f, f->output_data.x->mouse_pixel);
12210 if (f->output_data.x->scroll_bar_background_pixel != -1)
12211 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12212 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12213 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12214 if (f->output_data.x->white_relief.allocated_p)
12215 unload_color (f, f->output_data.x->white_relief.pixel);
12216 if (f->output_data.x->black_relief.allocated_p)
12217 unload_color (f, f->output_data.x->black_relief.pixel);
12218
12219 free_frame_faces (f);
12220 XFlush (FRAME_X_DISPLAY (f));
12221 }
12222
12223 if (f->output_data.x->saved_menu_event)
12224 xfree (f->output_data.x->saved_menu_event);
12225
12226 xfree (f->output_data.x);
12227 f->output_data.x = 0;
12228 if (f == dpyinfo->x_focus_frame)
12229 dpyinfo->x_focus_frame = 0;
12230 if (f == dpyinfo->x_focus_event_frame)
12231 dpyinfo->x_focus_event_frame = 0;
12232 if (f == dpyinfo->x_highlight_frame)
12233 dpyinfo->x_highlight_frame = 0;
12234
12235 dpyinfo->reference_count--;
12236
12237 if (f == dpyinfo->mouse_face_mouse_frame)
12238 {
12239 dpyinfo->mouse_face_beg_row
12240 = dpyinfo->mouse_face_beg_col = -1;
12241 dpyinfo->mouse_face_end_row
12242 = dpyinfo->mouse_face_end_col = -1;
12243 dpyinfo->mouse_face_window = Qnil;
12244 dpyinfo->mouse_face_deferred_gc = 0;
12245 dpyinfo->mouse_face_mouse_frame = 0;
12246 }
12247
12248 UNBLOCK_INPUT;
12249 }
12250 \f
12251 /* Setting window manager hints. */
12252
12253 /* Set the normal size hints for the window manager, for frame F.
12254 FLAGS is the flags word to use--or 0 meaning preserve the flags
12255 that the window now has.
12256 If USER_POSITION is nonzero, we set the USPosition
12257 flag (this is useful when FLAGS is 0). */
12258
12259 void
12260 x_wm_set_size_hint (f, flags, user_position)
12261 struct frame *f;
12262 long flags;
12263 int user_position;
12264 {
12265 XSizeHints size_hints;
12266
12267 #ifdef USE_X_TOOLKIT
12268 Arg al[2];
12269 int ac = 0;
12270 Dimension widget_width, widget_height;
12271 Window window = XtWindow (f->output_data.x->widget);
12272 #else /* not USE_X_TOOLKIT */
12273 Window window = FRAME_X_WINDOW (f);
12274 #endif /* not USE_X_TOOLKIT */
12275
12276 /* Setting PMaxSize caused various problems. */
12277 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12278
12279 size_hints.x = f->output_data.x->left_pos;
12280 size_hints.y = f->output_data.x->top_pos;
12281
12282 #ifdef USE_X_TOOLKIT
12283 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12284 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12285 XtGetValues (f->output_data.x->widget, al, ac);
12286 size_hints.height = widget_height;
12287 size_hints.width = widget_width;
12288 #else /* not USE_X_TOOLKIT */
12289 size_hints.height = PIXEL_HEIGHT (f);
12290 size_hints.width = PIXEL_WIDTH (f);
12291 #endif /* not USE_X_TOOLKIT */
12292
12293 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12294 size_hints.height_inc = f->output_data.x->line_height;
12295 size_hints.max_width
12296 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12297 size_hints.max_height
12298 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12299
12300 /* Calculate the base and minimum sizes.
12301
12302 (When we use the X toolkit, we don't do it here.
12303 Instead we copy the values that the widgets are using, below.) */
12304 #ifndef USE_X_TOOLKIT
12305 {
12306 int base_width, base_height;
12307 int min_rows = 0, min_cols = 0;
12308
12309 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12310 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12311
12312 check_frame_size (f, &min_rows, &min_cols);
12313
12314 /* The window manager uses the base width hints to calculate the
12315 current number of rows and columns in the frame while
12316 resizing; min_width and min_height aren't useful for this
12317 purpose, since they might not give the dimensions for a
12318 zero-row, zero-column frame.
12319
12320 We use the base_width and base_height members if we have
12321 them; otherwise, we set the min_width and min_height members
12322 to the size for a zero x zero frame. */
12323
12324 #ifdef HAVE_X11R4
12325 size_hints.flags |= PBaseSize;
12326 size_hints.base_width = base_width;
12327 size_hints.base_height = base_height;
12328 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12329 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12330 #else
12331 size_hints.min_width = base_width;
12332 size_hints.min_height = base_height;
12333 #endif
12334 }
12335
12336 /* If we don't need the old flags, we don't need the old hint at all. */
12337 if (flags)
12338 {
12339 size_hints.flags |= flags;
12340 goto no_read;
12341 }
12342 #endif /* not USE_X_TOOLKIT */
12343
12344 {
12345 XSizeHints hints; /* Sometimes I hate X Windows... */
12346 long supplied_return;
12347 int value;
12348
12349 #ifdef HAVE_X11R4
12350 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12351 &supplied_return);
12352 #else
12353 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12354 #endif
12355
12356 #ifdef USE_X_TOOLKIT
12357 size_hints.base_height = hints.base_height;
12358 size_hints.base_width = hints.base_width;
12359 size_hints.min_height = hints.min_height;
12360 size_hints.min_width = hints.min_width;
12361 #endif
12362
12363 if (flags)
12364 size_hints.flags |= flags;
12365 else
12366 {
12367 if (value == 0)
12368 hints.flags = 0;
12369 if (hints.flags & PSize)
12370 size_hints.flags |= PSize;
12371 if (hints.flags & PPosition)
12372 size_hints.flags |= PPosition;
12373 if (hints.flags & USPosition)
12374 size_hints.flags |= USPosition;
12375 if (hints.flags & USSize)
12376 size_hints.flags |= USSize;
12377 }
12378 }
12379
12380 #ifndef USE_X_TOOLKIT
12381 no_read:
12382 #endif
12383
12384 #ifdef PWinGravity
12385 size_hints.win_gravity = f->output_data.x->win_gravity;
12386 size_hints.flags |= PWinGravity;
12387
12388 if (user_position)
12389 {
12390 size_hints.flags &= ~ PPosition;
12391 size_hints.flags |= USPosition;
12392 }
12393 #endif /* PWinGravity */
12394
12395 #ifdef HAVE_X11R4
12396 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12397 #else
12398 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12399 #endif
12400 }
12401
12402 /* Used for IconicState or NormalState */
12403
12404 void
12405 x_wm_set_window_state (f, state)
12406 struct frame *f;
12407 int state;
12408 {
12409 #ifdef USE_X_TOOLKIT
12410 Arg al[1];
12411
12412 XtSetArg (al[0], XtNinitialState, state);
12413 XtSetValues (f->output_data.x->widget, al, 1);
12414 #else /* not USE_X_TOOLKIT */
12415 Window window = FRAME_X_WINDOW (f);
12416
12417 f->output_data.x->wm_hints.flags |= StateHint;
12418 f->output_data.x->wm_hints.initial_state = state;
12419
12420 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12421 #endif /* not USE_X_TOOLKIT */
12422 }
12423
12424 void
12425 x_wm_set_icon_pixmap (f, pixmap_id)
12426 struct frame *f;
12427 int pixmap_id;
12428 {
12429 Pixmap icon_pixmap;
12430
12431 #ifndef USE_X_TOOLKIT
12432 Window window = FRAME_X_WINDOW (f);
12433 #endif
12434
12435 if (pixmap_id > 0)
12436 {
12437 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12438 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12439 }
12440 else
12441 {
12442 /* It seems there is no way to turn off use of an icon pixmap.
12443 The following line does it, only if no icon has yet been created,
12444 for some window managers. But with mwm it crashes.
12445 Some people say it should clear the IconPixmapHint bit in this case,
12446 but that doesn't work, and the X consortium said it isn't the
12447 right thing at all. Since there is no way to win,
12448 best to explicitly give up. */
12449 #if 0
12450 f->output_data.x->wm_hints.icon_pixmap = None;
12451 #else
12452 return;
12453 #endif
12454 }
12455
12456 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12457
12458 {
12459 Arg al[1];
12460 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12461 XtSetValues (f->output_data.x->widget, al, 1);
12462 }
12463
12464 #else /* not USE_X_TOOLKIT */
12465
12466 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12467 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12468
12469 #endif /* not USE_X_TOOLKIT */
12470 }
12471
12472 void
12473 x_wm_set_icon_position (f, icon_x, icon_y)
12474 struct frame *f;
12475 int icon_x, icon_y;
12476 {
12477 #ifdef USE_X_TOOLKIT
12478 Window window = XtWindow (f->output_data.x->widget);
12479 #else
12480 Window window = FRAME_X_WINDOW (f);
12481 #endif
12482
12483 f->output_data.x->wm_hints.flags |= IconPositionHint;
12484 f->output_data.x->wm_hints.icon_x = icon_x;
12485 f->output_data.x->wm_hints.icon_y = icon_y;
12486
12487 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12488 }
12489
12490 \f
12491 /***********************************************************************
12492 Fonts
12493 ***********************************************************************/
12494
12495 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12496
12497 struct font_info *
12498 x_get_font_info (f, font_idx)
12499 FRAME_PTR f;
12500 int font_idx;
12501 {
12502 return (FRAME_X_FONT_TABLE (f) + font_idx);
12503 }
12504
12505
12506 /* Return a list of names of available fonts matching PATTERN on frame
12507 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12508 to be listed. Frame F NULL means we have not yet created any
12509 frame on X, and consult the first display in x_display_list.
12510 MAXNAMES sets a limit on how many fonts to match. */
12511
12512 Lisp_Object
12513 x_list_fonts (f, pattern, size, maxnames)
12514 FRAME_PTR f;
12515 Lisp_Object pattern;
12516 int size;
12517 int maxnames;
12518 {
12519 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12520 Lisp_Object tem, second_best;
12521 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12522 int try_XLoadQueryFont = 0;
12523 int count;
12524
12525 patterns = Fassoc (pattern, Valternate_fontname_alist);
12526 if (NILP (patterns))
12527 patterns = Fcons (pattern, Qnil);
12528
12529 if (maxnames == 1 && !size)
12530 /* We can return any single font matching PATTERN. */
12531 try_XLoadQueryFont = 1;
12532
12533 for (; CONSP (patterns); patterns = XCDR (patterns))
12534 {
12535 int num_fonts;
12536 char **names = NULL;
12537
12538 pattern = XCAR (patterns);
12539 /* See if we cached the result for this particular query.
12540 The cache is an alist of the form:
12541 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12542 */
12543 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12544 key = Fcons (pattern, make_number (maxnames)),
12545 !NILP (list = Fassoc (key, tem))))
12546 {
12547 list = Fcdr_safe (list);
12548 /* We have a cashed list. Don't have to get the list again. */
12549 goto label_cached;
12550 }
12551
12552 /* At first, put PATTERN in the cache. */
12553
12554 BLOCK_INPUT;
12555 count = x_catch_errors (dpy);
12556
12557 if (try_XLoadQueryFont)
12558 {
12559 XFontStruct *font;
12560 unsigned long value;
12561
12562 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12563 if (x_had_errors_p (dpy))
12564 {
12565 /* This error is perhaps due to insufficient memory on X
12566 server. Let's just ignore it. */
12567 font = NULL;
12568 x_clear_errors (dpy);
12569 }
12570
12571 if (font
12572 && XGetFontProperty (font, XA_FONT, &value))
12573 {
12574 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12575 int len = strlen (name);
12576 char *tmp;
12577
12578 /* If DXPC (a Differential X Protocol Compressor)
12579 Ver.3.7 is running, XGetAtomName will return null
12580 string. We must avoid such a name. */
12581 if (len == 0)
12582 try_XLoadQueryFont = 0;
12583 else
12584 {
12585 num_fonts = 1;
12586 names = (char **) alloca (sizeof (char *));
12587 /* Some systems only allow alloca assigned to a
12588 simple var. */
12589 tmp = (char *) alloca (len + 1); names[0] = tmp;
12590 bcopy (name, names[0], len + 1);
12591 XFree (name);
12592 }
12593 }
12594 else
12595 try_XLoadQueryFont = 0;
12596
12597 if (font)
12598 XFreeFont (dpy, font);
12599 }
12600
12601 if (!try_XLoadQueryFont)
12602 {
12603 /* We try at least 10 fonts because XListFonts will return
12604 auto-scaled fonts at the head. */
12605 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12606 &num_fonts);
12607 if (x_had_errors_p (dpy))
12608 {
12609 /* This error is perhaps due to insufficient memory on X
12610 server. Let's just ignore it. */
12611 names = NULL;
12612 x_clear_errors (dpy);
12613 }
12614 }
12615
12616 x_uncatch_errors (dpy, count);
12617 UNBLOCK_INPUT;
12618
12619 if (names)
12620 {
12621 int i;
12622
12623 /* Make a list of all the fonts we got back.
12624 Store that in the font cache for the display. */
12625 for (i = 0; i < num_fonts; i++)
12626 {
12627 int width = 0;
12628 char *p = names[i];
12629 int average_width = -1, dashes = 0;
12630
12631 /* Count the number of dashes in NAMES[I]. If there are
12632 14 dashes, and the field value following 12th dash
12633 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12634 is usually too ugly to be used for editing. Let's
12635 ignore it. */
12636 while (*p)
12637 if (*p++ == '-')
12638 {
12639 dashes++;
12640 if (dashes == 7) /* PIXEL_SIZE field */
12641 width = atoi (p);
12642 else if (dashes == 12) /* AVERAGE_WIDTH field */
12643 average_width = atoi (p);
12644 }
12645 if (dashes < 14 || average_width != 0)
12646 {
12647 tem = build_string (names[i]);
12648 if (NILP (Fassoc (tem, list)))
12649 {
12650 if (STRINGP (Vx_pixel_size_width_font_regexp)
12651 && ((fast_c_string_match_ignore_case
12652 (Vx_pixel_size_width_font_regexp, names[i]))
12653 >= 0))
12654 /* We can set the value of PIXEL_SIZE to the
12655 width of this font. */
12656 list = Fcons (Fcons (tem, make_number (width)), list);
12657 else
12658 /* For the moment, width is not known. */
12659 list = Fcons (Fcons (tem, Qnil), list);
12660 }
12661 }
12662 }
12663 if (!try_XLoadQueryFont)
12664 XFreeFontNames (names);
12665 }
12666
12667 /* Now store the result in the cache. */
12668 if (f != NULL)
12669 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12670 = Fcons (Fcons (key, list),
12671 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12672
12673 label_cached:
12674 if (NILP (list)) continue; /* Try the remaining alternatives. */
12675
12676 newlist = second_best = Qnil;
12677 /* Make a list of the fonts that have the right width. */
12678 for (; CONSP (list); list = XCDR (list))
12679 {
12680 int found_size;
12681
12682 tem = XCAR (list);
12683
12684 if (!CONSP (tem) || NILP (XCAR (tem)))
12685 continue;
12686 if (!size)
12687 {
12688 newlist = Fcons (XCAR (tem), newlist);
12689 continue;
12690 }
12691
12692 if (!INTEGERP (XCDR (tem)))
12693 {
12694 /* Since we have not yet known the size of this font, we
12695 must try slow function call XLoadQueryFont. */
12696 XFontStruct *thisinfo;
12697
12698 BLOCK_INPUT;
12699 count = x_catch_errors (dpy);
12700 thisinfo = XLoadQueryFont (dpy,
12701 XSTRING (XCAR (tem))->data);
12702 if (x_had_errors_p (dpy))
12703 {
12704 /* This error is perhaps due to insufficient memory on X
12705 server. Let's just ignore it. */
12706 thisinfo = NULL;
12707 x_clear_errors (dpy);
12708 }
12709 x_uncatch_errors (dpy, count);
12710 UNBLOCK_INPUT;
12711
12712 if (thisinfo)
12713 {
12714 XCDR (tem)
12715 = (thisinfo->min_bounds.width == 0
12716 ? make_number (0)
12717 : make_number (thisinfo->max_bounds.width));
12718 XFreeFont (dpy, thisinfo);
12719 }
12720 else
12721 /* For unknown reason, the previous call of XListFont had
12722 returned a font which can't be opened. Record the size
12723 as 0 not to try to open it again. */
12724 XCDR (tem) = make_number (0);
12725 }
12726
12727 found_size = XINT (XCDR (tem));
12728 if (found_size == size)
12729 newlist = Fcons (XCAR (tem), newlist);
12730 else if (found_size > 0)
12731 {
12732 if (NILP (second_best))
12733 second_best = tem;
12734 else if (found_size < size)
12735 {
12736 if (XINT (XCDR (second_best)) > size
12737 || XINT (XCDR (second_best)) < found_size)
12738 second_best = tem;
12739 }
12740 else
12741 {
12742 if (XINT (XCDR (second_best)) > size
12743 && XINT (XCDR (second_best)) > found_size)
12744 second_best = tem;
12745 }
12746 }
12747 }
12748 if (!NILP (newlist))
12749 break;
12750 else if (!NILP (second_best))
12751 {
12752 newlist = Fcons (XCAR (second_best), Qnil);
12753 break;
12754 }
12755 }
12756
12757 return newlist;
12758 }
12759
12760
12761 #if GLYPH_DEBUG
12762
12763 /* Check that FONT is valid on frame F. It is if it can be found in F's
12764 font table. */
12765
12766 static void
12767 x_check_font (f, font)
12768 struct frame *f;
12769 XFontStruct *font;
12770 {
12771 int i;
12772 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12773
12774 xassert (font != NULL);
12775
12776 for (i = 0; i < dpyinfo->n_fonts; i++)
12777 if (dpyinfo->font_table[i].name
12778 && font == dpyinfo->font_table[i].font)
12779 break;
12780
12781 xassert (i < dpyinfo->n_fonts);
12782 }
12783
12784 #endif /* GLYPH_DEBUG != 0 */
12785
12786 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12787 Note: There are (broken) X fonts out there with invalid XFontStruct
12788 min_bounds contents. For example, handa@etl.go.jp reports that
12789 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12790 have font->min_bounds.width == 0. */
12791
12792 static INLINE void
12793 x_font_min_bounds (font, w, h)
12794 XFontStruct *font;
12795 int *w, *h;
12796 {
12797 *h = FONT_HEIGHT (font);
12798 *w = font->min_bounds.width;
12799
12800 /* Try to handle the case where FONT->min_bounds has invalid
12801 contents. Since the only font known to have invalid min_bounds
12802 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12803 if (*w <= 0)
12804 *w = font->max_bounds.width;
12805 }
12806
12807
12808 /* Compute the smallest character width and smallest font height over
12809 all fonts available on frame F. Set the members smallest_char_width
12810 and smallest_font_height in F's x_display_info structure to
12811 the values computed. Value is non-zero if smallest_font_height or
12812 smallest_char_width become smaller than they were before. */
12813
12814 static int
12815 x_compute_min_glyph_bounds (f)
12816 struct frame *f;
12817 {
12818 int i;
12819 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12820 XFontStruct *font;
12821 int old_width = dpyinfo->smallest_char_width;
12822 int old_height = dpyinfo->smallest_font_height;
12823
12824 dpyinfo->smallest_font_height = 100000;
12825 dpyinfo->smallest_char_width = 100000;
12826
12827 for (i = 0; i < dpyinfo->n_fonts; ++i)
12828 if (dpyinfo->font_table[i].name)
12829 {
12830 struct font_info *fontp = dpyinfo->font_table + i;
12831 int w, h;
12832
12833 font = (XFontStruct *) fontp->font;
12834 xassert (font != (XFontStruct *) ~0);
12835 x_font_min_bounds (font, &w, &h);
12836
12837 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12838 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12839 }
12840
12841 xassert (dpyinfo->smallest_char_width > 0
12842 && dpyinfo->smallest_font_height > 0);
12843
12844 return (dpyinfo->n_fonts == 1
12845 || dpyinfo->smallest_char_width < old_width
12846 || dpyinfo->smallest_font_height < old_height);
12847 }
12848
12849
12850 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12851 pointer to the structure font_info while allocating it dynamically.
12852 If SIZE is 0, load any size of font.
12853 If loading is failed, return NULL. */
12854
12855 struct font_info *
12856 x_load_font (f, fontname, size)
12857 struct frame *f;
12858 register char *fontname;
12859 int size;
12860 {
12861 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12862 Lisp_Object font_names;
12863 int count;
12864
12865 /* Get a list of all the fonts that match this name. Once we
12866 have a list of matching fonts, we compare them against the fonts
12867 we already have by comparing names. */
12868 font_names = x_list_fonts (f, build_string (fontname), size, 1);
12869
12870 if (!NILP (font_names))
12871 {
12872 Lisp_Object tail;
12873 int i;
12874
12875 for (i = 0; i < dpyinfo->n_fonts; i++)
12876 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
12877 if (dpyinfo->font_table[i].name
12878 && (!strcmp (dpyinfo->font_table[i].name,
12879 XSTRING (XCAR (tail))->data)
12880 || !strcmp (dpyinfo->font_table[i].full_name,
12881 XSTRING (XCAR (tail))->data)))
12882 return (dpyinfo->font_table + i);
12883 }
12884
12885 /* Load the font and add it to the table. */
12886 {
12887 char *full_name;
12888 XFontStruct *font;
12889 struct font_info *fontp;
12890 unsigned long value;
12891 int i;
12892
12893 /* If we have found fonts by x_list_font, load one of them. If
12894 not, we still try to load a font by the name given as FONTNAME
12895 because XListFonts (called in x_list_font) of some X server has
12896 a bug of not finding a font even if the font surely exists and
12897 is loadable by XLoadQueryFont. */
12898 if (size > 0 && !NILP (font_names))
12899 fontname = (char *) XSTRING (XCAR (font_names))->data;
12900
12901 BLOCK_INPUT;
12902 count = x_catch_errors (FRAME_X_DISPLAY (f));
12903 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
12904 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12905 {
12906 /* This error is perhaps due to insufficient memory on X
12907 server. Let's just ignore it. */
12908 font = NULL;
12909 x_clear_errors (FRAME_X_DISPLAY (f));
12910 }
12911 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12912 UNBLOCK_INPUT;
12913 if (!font)
12914 return NULL;
12915
12916 /* Find a free slot in the font table. */
12917 for (i = 0; i < dpyinfo->n_fonts; ++i)
12918 if (dpyinfo->font_table[i].name == NULL)
12919 break;
12920
12921 /* If no free slot found, maybe enlarge the font table. */
12922 if (i == dpyinfo->n_fonts
12923 && dpyinfo->n_fonts == dpyinfo->font_table_size)
12924 {
12925 int sz;
12926 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12927 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
12928 dpyinfo->font_table
12929 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
12930 }
12931
12932 fontp = dpyinfo->font_table + i;
12933 if (i == dpyinfo->n_fonts)
12934 ++dpyinfo->n_fonts;
12935
12936 /* Now fill in the slots of *FONTP. */
12937 BLOCK_INPUT;
12938 fontp->font = font;
12939 fontp->font_idx = i;
12940 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12941 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12942
12943 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12944 full_name = 0;
12945 if (XGetFontProperty (font, XA_FONT, &value))
12946 {
12947 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12948 char *p = name;
12949 int dashes = 0;
12950
12951 /* Count the number of dashes in the "full name".
12952 If it is too few, this isn't really the font's full name,
12953 so don't use it.
12954 In X11R4, the fonts did not come with their canonical names
12955 stored in them. */
12956 while (*p)
12957 {
12958 if (*p == '-')
12959 dashes++;
12960 p++;
12961 }
12962
12963 if (dashes >= 13)
12964 {
12965 full_name = (char *) xmalloc (p - name + 1);
12966 bcopy (name, full_name, p - name + 1);
12967 }
12968
12969 XFree (name);
12970 }
12971
12972 if (full_name != 0)
12973 fontp->full_name = full_name;
12974 else
12975 fontp->full_name = fontp->name;
12976
12977 fontp->size = font->max_bounds.width;
12978 fontp->height = FONT_HEIGHT (font);
12979 {
12980 /* For some font, ascent and descent in max_bounds field is
12981 larger than the above value. */
12982 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12983 if (max_height > fontp->height)
12984 fontp->height = max_height;
12985 }
12986
12987 if (NILP (font_names))
12988 {
12989 /* We come here because of a bug of XListFonts mentioned at
12990 the head of this block. Let's store this information in
12991 the cache for x_list_fonts. */
12992 Lisp_Object lispy_name = build_string (fontname);
12993 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12994
12995 XCDR (dpyinfo->name_list_element)
12996 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12997 Fcons (Fcons (lispy_full_name,
12998 make_number (fontp->size)),
12999 Qnil)),
13000 XCDR (dpyinfo->name_list_element));
13001 if (full_name)
13002 XCDR (dpyinfo->name_list_element)
13003 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
13004 Fcons (Fcons (lispy_full_name,
13005 make_number (fontp->size)),
13006 Qnil)),
13007 XCDR (dpyinfo->name_list_element));
13008 }
13009
13010 /* The slot `encoding' specifies how to map a character
13011 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13012 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13013 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13014 2:0xA020..0xFF7F). For the moment, we don't know which charset
13015 uses this font. So, we set information in fontp->encoding[1]
13016 which is never used by any charset. If mapping can't be
13017 decided, set FONT_ENCODING_NOT_DECIDED. */
13018 fontp->encoding[1]
13019 = (font->max_byte1 == 0
13020 /* 1-byte font */
13021 ? (font->min_char_or_byte2 < 0x80
13022 ? (font->max_char_or_byte2 < 0x80
13023 ? 0 /* 0x20..0x7F */
13024 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13025 : 1) /* 0xA0..0xFF */
13026 /* 2-byte font */
13027 : (font->min_byte1 < 0x80
13028 ? (font->max_byte1 < 0x80
13029 ? (font->min_char_or_byte2 < 0x80
13030 ? (font->max_char_or_byte2 < 0x80
13031 ? 0 /* 0x2020..0x7F7F */
13032 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13033 : 3) /* 0x20A0..0x7FFF */
13034 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13035 : (font->min_char_or_byte2 < 0x80
13036 ? (font->max_char_or_byte2 < 0x80
13037 ? 2 /* 0xA020..0xFF7F */
13038 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13039 : 1))); /* 0xA0A0..0xFFFF */
13040
13041 fontp->baseline_offset
13042 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13043 ? (long) value : 0);
13044 fontp->relative_compose
13045 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13046 ? (long) value : 0);
13047 fontp->default_ascent
13048 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13049 ? (long) value : 0);
13050
13051 /* Set global flag fonts_changed_p to non-zero if the font loaded
13052 has a character with a smaller width than any other character
13053 before, or if the font loaded has a smalle>r height than any
13054 other font loaded before. If this happens, it will make a
13055 glyph matrix reallocation necessary. */
13056 fonts_changed_p = x_compute_min_glyph_bounds (f);
13057 UNBLOCK_INPUT;
13058 return fontp;
13059 }
13060 }
13061
13062
13063 /* Return a pointer to struct font_info of a font named FONTNAME for
13064 frame F. If no such font is loaded, return NULL. */
13065
13066 struct font_info *
13067 x_query_font (f, fontname)
13068 struct frame *f;
13069 register char *fontname;
13070 {
13071 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13072 int i;
13073
13074 for (i = 0; i < dpyinfo->n_fonts; i++)
13075 if (dpyinfo->font_table[i].name
13076 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13077 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13078 return (dpyinfo->font_table + i);
13079 return NULL;
13080 }
13081
13082
13083 /* Find a CCL program for a font specified by FONTP, and set the member
13084 `encoder' of the structure. */
13085
13086 void
13087 x_find_ccl_program (fontp)
13088 struct font_info *fontp;
13089 {
13090 Lisp_Object list, elt;
13091
13092 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13093 {
13094 elt = XCAR (list);
13095 if (CONSP (elt)
13096 && STRINGP (XCAR (elt))
13097 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13098 >= 0))
13099 break;
13100 }
13101 if (! NILP (list))
13102 {
13103 struct ccl_program *ccl
13104 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13105
13106 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13107 xfree (ccl);
13108 else
13109 fontp->font_encoder = ccl;
13110 }
13111 }
13112
13113
13114 \f
13115 /***********************************************************************
13116 Initialization
13117 ***********************************************************************/
13118
13119 #ifdef USE_X_TOOLKIT
13120 static XrmOptionDescRec emacs_options[] = {
13121 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13122 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13123
13124 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13125 XrmoptionSepArg, NULL},
13126 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13127
13128 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13129 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13130 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13131 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13132 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13133 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13134 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13135 };
13136 #endif /* USE_X_TOOLKIT */
13137
13138 static int x_initialized;
13139
13140 #ifdef MULTI_KBOARD
13141 /* Test whether two display-name strings agree up to the dot that separates
13142 the screen number from the server number. */
13143 static int
13144 same_x_server (name1, name2)
13145 char *name1, *name2;
13146 {
13147 int seen_colon = 0;
13148 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13149 int system_name_length = strlen (system_name);
13150 int length_until_period = 0;
13151
13152 while (system_name[length_until_period] != 0
13153 && system_name[length_until_period] != '.')
13154 length_until_period++;
13155
13156 /* Treat `unix' like an empty host name. */
13157 if (! strncmp (name1, "unix:", 5))
13158 name1 += 4;
13159 if (! strncmp (name2, "unix:", 5))
13160 name2 += 4;
13161 /* Treat this host's name like an empty host name. */
13162 if (! strncmp (name1, system_name, system_name_length)
13163 && name1[system_name_length] == ':')
13164 name1 += system_name_length;
13165 if (! strncmp (name2, system_name, system_name_length)
13166 && name2[system_name_length] == ':')
13167 name2 += system_name_length;
13168 /* Treat this host's domainless name like an empty host name. */
13169 if (! strncmp (name1, system_name, length_until_period)
13170 && name1[length_until_period] == ':')
13171 name1 += length_until_period;
13172 if (! strncmp (name2, system_name, length_until_period)
13173 && name2[length_until_period] == ':')
13174 name2 += length_until_period;
13175
13176 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13177 {
13178 if (*name1 == ':')
13179 seen_colon++;
13180 if (seen_colon && *name1 == '.')
13181 return 1;
13182 }
13183 return (seen_colon
13184 && (*name1 == '.' || *name1 == '\0')
13185 && (*name2 == '.' || *name2 == '\0'));
13186 }
13187 #endif
13188
13189 struct x_display_info *
13190 x_term_init (display_name, xrm_option, resource_name)
13191 Lisp_Object display_name;
13192 char *xrm_option;
13193 char *resource_name;
13194 {
13195 int connection;
13196 Display *dpy;
13197 struct x_display_info *dpyinfo;
13198 XrmDatabase xrdb;
13199
13200 BLOCK_INPUT;
13201
13202 if (!x_initialized)
13203 {
13204 x_initialize ();
13205 x_initialized = 1;
13206 }
13207
13208 #ifdef USE_X_TOOLKIT
13209 /* weiner@footloose.sps.mot.com reports that this causes
13210 errors with X11R5:
13211 X protocol error: BadAtom (invalid Atom parameter)
13212 on protocol request 18skiloaf.
13213 So let's not use it until R6. */
13214 #ifdef HAVE_X11XTR6
13215 XtSetLanguageProc (NULL, NULL, NULL);
13216 #endif
13217
13218 {
13219 int argc = 0;
13220 char *argv[3];
13221
13222 argv[0] = "";
13223 argc = 1;
13224 if (xrm_option)
13225 {
13226 argv[argc++] = "-xrm";
13227 argv[argc++] = xrm_option;
13228 }
13229 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13230 resource_name, EMACS_CLASS,
13231 emacs_options, XtNumber (emacs_options),
13232 &argc, argv);
13233
13234 #ifdef HAVE_X11XTR6
13235 /* I think this is to compensate for XtSetLanguageProc. */
13236 fixup_locale ();
13237 #endif
13238 }
13239
13240 #else /* not USE_X_TOOLKIT */
13241 #ifdef HAVE_X11R5
13242 XSetLocaleModifiers ("");
13243 #endif
13244 dpy = XOpenDisplay (XSTRING (display_name)->data);
13245 #endif /* not USE_X_TOOLKIT */
13246
13247 /* Detect failure. */
13248 if (dpy == 0)
13249 {
13250 UNBLOCK_INPUT;
13251 return 0;
13252 }
13253
13254 /* We have definitely succeeded. Record the new connection. */
13255
13256 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13257
13258 #ifdef MULTI_KBOARD
13259 {
13260 struct x_display_info *share;
13261 Lisp_Object tail;
13262
13263 for (share = x_display_list, tail = x_display_name_list; share;
13264 share = share->next, tail = XCDR (tail))
13265 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13266 XSTRING (display_name)->data))
13267 break;
13268 if (share)
13269 dpyinfo->kboard = share->kboard;
13270 else
13271 {
13272 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13273 init_kboard (dpyinfo->kboard);
13274 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13275 {
13276 char *vendor = ServerVendor (dpy);
13277 UNBLOCK_INPUT;
13278 dpyinfo->kboard->Vsystem_key_alist
13279 = call1 (Qvendor_specific_keysyms,
13280 build_string (vendor ? vendor : ""));
13281 BLOCK_INPUT;
13282 }
13283
13284 dpyinfo->kboard->next_kboard = all_kboards;
13285 all_kboards = dpyinfo->kboard;
13286 /* Don't let the initial kboard remain current longer than necessary.
13287 That would cause problems if a file loaded on startup tries to
13288 prompt in the mini-buffer. */
13289 if (current_kboard == initial_kboard)
13290 current_kboard = dpyinfo->kboard;
13291 }
13292 dpyinfo->kboard->reference_count++;
13293 }
13294 #endif
13295
13296 /* Put this display on the chain. */
13297 dpyinfo->next = x_display_list;
13298 x_display_list = dpyinfo;
13299
13300 /* Put it on x_display_name_list as well, to keep them parallel. */
13301 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13302 x_display_name_list);
13303 dpyinfo->name_list_element = XCAR (x_display_name_list);
13304
13305 dpyinfo->display = dpy;
13306
13307 #if 0
13308 XSetAfterFunction (x_current_display, x_trace_wire);
13309 #endif /* ! 0 */
13310
13311 dpyinfo->x_id_name
13312 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13313 + STRING_BYTES (XSTRING (Vsystem_name))
13314 + 2);
13315 sprintf (dpyinfo->x_id_name, "%s@%s",
13316 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13317
13318 /* Figure out which modifier bits mean what. */
13319 x_find_modifier_meanings (dpyinfo);
13320
13321 /* Get the scroll bar cursor. */
13322 dpyinfo->vertical_scroll_bar_cursor
13323 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13324
13325 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13326 resource_name, EMACS_CLASS);
13327 #ifdef HAVE_XRMSETDATABASE
13328 XrmSetDatabase (dpyinfo->display, xrdb);
13329 #else
13330 dpyinfo->display->db = xrdb;
13331 #endif
13332 /* Put the rdb where we can find it in a way that works on
13333 all versions. */
13334 dpyinfo->xrdb = xrdb;
13335
13336 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13337 DefaultScreen (dpyinfo->display));
13338 select_visual (dpyinfo);
13339 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13340 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13341 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13342 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13343 dpyinfo->grabbed = 0;
13344 dpyinfo->reference_count = 0;
13345 dpyinfo->icon_bitmap_id = -1;
13346 dpyinfo->font_table = NULL;
13347 dpyinfo->n_fonts = 0;
13348 dpyinfo->font_table_size = 0;
13349 dpyinfo->bitmaps = 0;
13350 dpyinfo->bitmaps_size = 0;
13351 dpyinfo->bitmaps_last = 0;
13352 dpyinfo->scratch_cursor_gc = 0;
13353 dpyinfo->mouse_face_mouse_frame = 0;
13354 dpyinfo->mouse_face_deferred_gc = 0;
13355 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13356 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13357 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13358 dpyinfo->mouse_face_window = Qnil;
13359 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13360 dpyinfo->mouse_face_defer = 0;
13361 dpyinfo->x_focus_frame = 0;
13362 dpyinfo->x_focus_event_frame = 0;
13363 dpyinfo->x_highlight_frame = 0;
13364 dpyinfo->image_cache = make_image_cache ();
13365
13366 /* See if a private colormap is requested. */
13367 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13368 {
13369 if (dpyinfo->visual->class == PseudoColor)
13370 {
13371 Lisp_Object value;
13372 value = display_x_get_resource (dpyinfo,
13373 build_string ("privateColormap"),
13374 build_string ("PrivateColormap"),
13375 Qnil, Qnil);
13376 if (STRINGP (value)
13377 && (!strcmp (XSTRING (value)->data, "true")
13378 || !strcmp (XSTRING (value)->data, "on")))
13379 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13380 }
13381 }
13382 else
13383 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13384 dpyinfo->visual, AllocNone);
13385
13386 {
13387 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13388 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13389 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13390 dpyinfo->resy = pixels * 25.4 / mm;
13391 pixels = DisplayWidth (dpyinfo->display, screen_number);
13392 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13393 dpyinfo->resx = pixels * 25.4 / mm;
13394 }
13395
13396 dpyinfo->Xatom_wm_protocols
13397 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13398 dpyinfo->Xatom_wm_take_focus
13399 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13400 dpyinfo->Xatom_wm_save_yourself
13401 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13402 dpyinfo->Xatom_wm_delete_window
13403 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13404 dpyinfo->Xatom_wm_change_state
13405 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13406 dpyinfo->Xatom_wm_configure_denied
13407 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13408 dpyinfo->Xatom_wm_window_moved
13409 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13410 dpyinfo->Xatom_editres
13411 = XInternAtom (dpyinfo->display, "Editres", False);
13412 dpyinfo->Xatom_CLIPBOARD
13413 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13414 dpyinfo->Xatom_TIMESTAMP
13415 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13416 dpyinfo->Xatom_TEXT
13417 = XInternAtom (dpyinfo->display, "TEXT", False);
13418 dpyinfo->Xatom_COMPOUND_TEXT
13419 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13420 dpyinfo->Xatom_DELETE
13421 = XInternAtom (dpyinfo->display, "DELETE", False);
13422 dpyinfo->Xatom_MULTIPLE
13423 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13424 dpyinfo->Xatom_INCR
13425 = XInternAtom (dpyinfo->display, "INCR", False);
13426 dpyinfo->Xatom_EMACS_TMP
13427 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13428 dpyinfo->Xatom_TARGETS
13429 = XInternAtom (dpyinfo->display, "TARGETS", False);
13430 dpyinfo->Xatom_NULL
13431 = XInternAtom (dpyinfo->display, "NULL", False);
13432 dpyinfo->Xatom_ATOM_PAIR
13433 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13434 /* For properties of font. */
13435 dpyinfo->Xatom_PIXEL_SIZE
13436 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13437 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13438 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13439 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13440 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13441 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13442 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13443
13444 /* Ghostscript support. */
13445 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13446 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13447
13448 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13449 False);
13450
13451 dpyinfo->cut_buffers_initialized = 0;
13452
13453 connection = ConnectionNumber (dpyinfo->display);
13454 dpyinfo->connection = connection;
13455
13456 {
13457 char null_bits[1];
13458
13459 null_bits[0] = 0x00;
13460
13461 dpyinfo->null_pixel
13462 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13463 null_bits, 1, 1, (long) 0, (long) 0,
13464 1);
13465 }
13466
13467 {
13468 extern int gray_bitmap_width, gray_bitmap_height;
13469 extern unsigned char *gray_bitmap_bits;
13470 dpyinfo->gray
13471 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13472 gray_bitmap_bits,
13473 gray_bitmap_width, gray_bitmap_height,
13474 (unsigned long) 1, (unsigned long) 0, 1);
13475 }
13476
13477 #ifdef HAVE_X_I18N
13478 xim_initialize (dpyinfo, resource_name);
13479 #endif
13480
13481 #ifdef subprocesses
13482 /* This is only needed for distinguishing keyboard and process input. */
13483 if (connection != 0)
13484 add_keyboard_wait_descriptor (connection);
13485 #endif
13486
13487 #ifndef F_SETOWN_BUG
13488 #ifdef F_SETOWN
13489 #ifdef F_SETOWN_SOCK_NEG
13490 /* stdin is a socket here */
13491 fcntl (connection, F_SETOWN, -getpid ());
13492 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13493 fcntl (connection, F_SETOWN, getpid ());
13494 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13495 #endif /* ! defined (F_SETOWN) */
13496 #endif /* F_SETOWN_BUG */
13497
13498 #ifdef SIGIO
13499 if (interrupt_input)
13500 init_sigio (connection);
13501 #endif /* ! defined (SIGIO) */
13502
13503 #ifdef USE_LUCID
13504 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13505 /* Make sure that we have a valid font for dialog boxes
13506 so that Xt does not crash. */
13507 {
13508 Display *dpy = dpyinfo->display;
13509 XrmValue d, fr, to;
13510 Font font;
13511 int count;
13512
13513 d.addr = (XPointer)&dpy;
13514 d.size = sizeof (Display *);
13515 fr.addr = XtDefaultFont;
13516 fr.size = sizeof (XtDefaultFont);
13517 to.size = sizeof (Font *);
13518 to.addr = (XPointer)&font;
13519 count = x_catch_errors (dpy);
13520 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13521 abort ();
13522 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13523 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13524 x_uncatch_errors (dpy, count);
13525 }
13526 #endif
13527 #endif
13528
13529 /* See if we should run in synchronous mode. This is useful
13530 for debugging X code. */
13531 {
13532 Lisp_Object value;
13533 value = display_x_get_resource (dpyinfo,
13534 build_string ("synchronous"),
13535 build_string ("Synchronous"),
13536 Qnil, Qnil);
13537 if (STRINGP (value)
13538 && (!strcmp (XSTRING (value)->data, "true")
13539 || !strcmp (XSTRING (value)->data, "on")))
13540 XSynchronize (dpyinfo->display, True);
13541 }
13542
13543 UNBLOCK_INPUT;
13544
13545 return dpyinfo;
13546 }
13547 \f
13548 /* Get rid of display DPYINFO, assuming all frames are already gone,
13549 and without sending any more commands to the X server. */
13550
13551 void
13552 x_delete_display (dpyinfo)
13553 struct x_display_info *dpyinfo;
13554 {
13555 delete_keyboard_wait_descriptor (dpyinfo->connection);
13556
13557 /* Discard this display from x_display_name_list and x_display_list.
13558 We can't use Fdelq because that can quit. */
13559 if (! NILP (x_display_name_list)
13560 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13561 x_display_name_list = XCDR (x_display_name_list);
13562 else
13563 {
13564 Lisp_Object tail;
13565
13566 tail = x_display_name_list;
13567 while (CONSP (tail) && CONSP (XCDR (tail)))
13568 {
13569 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13570 {
13571 XCDR (tail) = XCDR (XCDR (tail));
13572 break;
13573 }
13574 tail = XCDR (tail);
13575 }
13576 }
13577
13578 if (next_noop_dpyinfo == dpyinfo)
13579 next_noop_dpyinfo = dpyinfo->next;
13580
13581 if (x_display_list == dpyinfo)
13582 x_display_list = dpyinfo->next;
13583 else
13584 {
13585 struct x_display_info *tail;
13586
13587 for (tail = x_display_list; tail; tail = tail->next)
13588 if (tail->next == dpyinfo)
13589 tail->next = tail->next->next;
13590 }
13591
13592 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13593 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13594 XrmDestroyDatabase (dpyinfo->xrdb);
13595 #endif
13596 #endif
13597 #ifdef MULTI_KBOARD
13598 if (--dpyinfo->kboard->reference_count == 0)
13599 delete_kboard (dpyinfo->kboard);
13600 #endif
13601 #ifdef HAVE_X_I18N
13602 if (dpyinfo->xim)
13603 xim_close_dpy (dpyinfo);
13604 #endif
13605
13606 xfree (dpyinfo->font_table);
13607 xfree (dpyinfo->x_id_name);
13608 xfree (dpyinfo);
13609 }
13610 \f
13611 /* Set up use of X before we make the first connection. */
13612
13613 static struct redisplay_interface x_redisplay_interface =
13614 {
13615 x_produce_glyphs,
13616 x_write_glyphs,
13617 x_insert_glyphs,
13618 x_clear_end_of_line,
13619 x_scroll_run,
13620 x_after_update_window_line,
13621 x_update_window_begin,
13622 x_update_window_end,
13623 XTcursor_to,
13624 x_flush,
13625 x_clear_mouse_face,
13626 x_get_glyph_overhangs,
13627 x_fix_overlapping_area
13628 };
13629
13630 void
13631 x_initialize ()
13632 {
13633 rif = &x_redisplay_interface;
13634
13635 clear_frame_hook = x_clear_frame;
13636 ins_del_lines_hook = x_ins_del_lines;
13637 change_line_highlight_hook = x_change_line_highlight;
13638 delete_glyphs_hook = x_delete_glyphs;
13639 ring_bell_hook = XTring_bell;
13640 reset_terminal_modes_hook = XTreset_terminal_modes;
13641 set_terminal_modes_hook = XTset_terminal_modes;
13642 update_begin_hook = x_update_begin;
13643 update_end_hook = x_update_end;
13644 set_terminal_window_hook = XTset_terminal_window;
13645 read_socket_hook = XTread_socket;
13646 frame_up_to_date_hook = XTframe_up_to_date;
13647 reassert_line_highlight_hook = XTreassert_line_highlight;
13648 mouse_position_hook = XTmouse_position;
13649 frame_rehighlight_hook = XTframe_rehighlight;
13650 frame_raise_lower_hook = XTframe_raise_lower;
13651 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13652 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13653 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13654 judge_scroll_bars_hook = XTjudge_scroll_bars;
13655 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13656
13657 scroll_region_ok = 1; /* we'll scroll partial frames */
13658 char_ins_del_ok = 0; /* just as fast to write the line */
13659 line_ins_del_ok = 1; /* we'll just blt 'em */
13660 fast_clear_end_of_line = 1; /* X does this well */
13661 memory_below_frame = 0; /* we don't remember what scrolls
13662 off the bottom */
13663 baud_rate = 19200;
13664
13665 x_noop_count = 0;
13666 last_tool_bar_item = -1;
13667 any_help_event_p = 0;
13668
13669 /* Try to use interrupt input; if we can't, then start polling. */
13670 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13671
13672 #ifdef USE_X_TOOLKIT
13673 XtToolkitInitialize ();
13674 Xt_app_con = XtCreateApplicationContext ();
13675 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13676
13677 /* Install an asynchronous timer that processes Xt timeout events
13678 every 0.1s. This is necessary because some widget sets use
13679 timeouts internally, for example the LessTif menu bar, or the
13680 Xaw3d scroll bar. When Xt timouts aren't processed, these
13681 widgets don't behave normally. */
13682 {
13683 EMACS_TIME interval;
13684 EMACS_SET_SECS_USECS (interval, 0, 100000);
13685 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13686 }
13687 #endif
13688
13689 #if USE_TOOLKIT_SCROLL_BARS
13690 xaw3d_arrow_scroll = False;
13691 xaw3d_pick_top = True;
13692 #endif
13693
13694 /* Note that there is no real way portable across R3/R4 to get the
13695 original error handler. */
13696 XSetErrorHandler (x_error_handler);
13697 XSetIOErrorHandler (x_io_error_quitter);
13698
13699 /* Disable Window Change signals; they are handled by X events. */
13700 #ifdef SIGWINCH
13701 signal (SIGWINCH, SIG_DFL);
13702 #endif /* ! defined (SIGWINCH) */
13703
13704 signal (SIGPIPE, x_connection_signal);
13705 }
13706
13707
13708 void
13709 syms_of_xterm ()
13710 {
13711 staticpro (&x_error_message_string);
13712 x_error_message_string = Qnil;
13713
13714 staticpro (&x_display_name_list);
13715 x_display_name_list = Qnil;
13716
13717 staticpro (&last_mouse_scroll_bar);
13718 last_mouse_scroll_bar = Qnil;
13719
13720 staticpro (&Qvendor_specific_keysyms);
13721 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13722
13723 staticpro (&last_mouse_press_frame);
13724 last_mouse_press_frame = Qnil;
13725
13726 help_echo = Qnil;
13727 staticpro (&help_echo);
13728 help_echo_object = Qnil;
13729 staticpro (&help_echo_object);
13730 help_echo_window = Qnil;
13731 staticpro (&help_echo_window);
13732 previous_help_echo = Qnil;
13733 staticpro (&previous_help_echo);
13734 help_echo_pos = -1;
13735
13736 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13737 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13738 For example, if a block cursor is over a tab, it will be drawn as\n\
13739 wide as that tab on the display.");
13740 x_stretch_cursor_p = 0;
13741
13742 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13743 "If not nil, Emacs uses toolkit scroll bars.");
13744 #if USE_TOOLKIT_SCROLL_BARS
13745 x_toolkit_scroll_bars_p = 1;
13746 #else
13747 x_toolkit_scroll_bars_p = 0;
13748 #endif
13749
13750 staticpro (&last_mouse_motion_frame);
13751 last_mouse_motion_frame = Qnil;
13752 }
13753
13754 #endif /* not HAVE_X_WINDOWS */
13755