]> code.delx.au - gnu-emacs/blob - src/xterm.c
(command-line-processed): Doc fix.
[gnu-emacs] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
24
25 #include <config.h>
26
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
29 #include <signal.h>
30
31 #include <stdio.h>
32
33 #ifdef HAVE_X_WINDOWS
34
35 #include "lisp.h"
36 #include "blockinput.h"
37
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
41
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
46
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
56
57 #include "systty.h"
58 #include "systime.h"
59
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
69
70 #include "charset.h"
71 #include "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #include "gnu.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85 #include "process.h"
86 #include "atimer.h"
87 #include "keymap.h"
88
89 #ifdef USE_X_TOOLKIT
90 #include <X11/Shell.h>
91 #endif
92
93 #ifdef HAVE_SYS_TIME_H
94 #include <sys/time.h>
95 #endif
96 #ifdef HAVE_UNISTD_H
97 #include <unistd.h>
98 #endif
99
100 #ifdef USE_LUCID
101 extern int xlwmenu_window_p (Widget w, Window window);
102 extern void xlwmenu_redisplay P_ ((Widget));
103 #endif
104
105 #ifdef USE_X_TOOLKIT
106
107 extern void free_frame_menubar P_ ((struct frame *));
108 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
109 int));
110
111 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112 #define HACK_EDITRES
113 extern void _XEditResCheckMessages ();
114 #endif /* not NO_EDITRES */
115
116 /* Include toolkit specific headers for the scroll bar widget. */
117
118 #ifdef USE_TOOLKIT_SCROLL_BARS
119 #if defined USE_MOTIF
120 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
121 #include <Xm/ScrollBar.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
123
124 #ifdef HAVE_XAW3D
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
133 #ifndef XtNpickTop
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
138
139 #endif /* USE_X_TOOLKIT */
140
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
144 #endif
145
146 #ifdef USE_X_TOOLKIT
147 #include "widget.h"
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
150 #endif
151 #endif
152
153 #define abs(x) ((x) < 0 ? -(x) : (x))
154
155 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
156
157 \f
158 /* Fringe bitmaps. */
159
160 enum fringe_bitmap_type
161 {
162 NO_FRINGE_BITMAP,
163 LEFT_TRUNCATION_BITMAP,
164 RIGHT_TRUNCATION_BITMAP,
165 OVERLAY_ARROW_BITMAP,
166 CONTINUED_LINE_BITMAP,
167 CONTINUATION_LINE_BITMAP,
168 ZV_LINE_BITMAP
169 };
170
171 /* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
173
174 #define zv_width 8
175 #define zv_height 8
176 static unsigned char zv_bits[] = {
177 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
178
179 /* An arrow like this: `<-'. */
180
181 #define left_width 8
182 #define left_height 8
183 static unsigned char left_bits[] = {
184 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
185
186 /* Right truncation arrow bitmap `->'. */
187
188 #define right_width 8
189 #define right_height 8
190 static unsigned char right_bits[] = {
191 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
192
193 /* Marker for continued lines. */
194
195 #define continued_width 8
196 #define continued_height 8
197 static unsigned char continued_bits[] = {
198 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
199
200 /* Marker for continuation lines. */
201
202 #define continuation_width 8
203 #define continuation_height 8
204 static unsigned char continuation_bits[] = {
205 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
206
207 /* Overlay arrow bitmap. */
208
209 #if 0
210 /* A bomb. */
211 #define ov_width 8
212 #define ov_height 8
213 static unsigned char ov_bits[] = {
214 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
215 #else
216 /* A triangular arrow. */
217 #define ov_width 8
218 #define ov_height 8
219 static unsigned char ov_bits[] = {
220 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
221
222 #endif
223
224 extern Lisp_Object Qhelp_echo;
225
226 \f
227 /* Non-nil means Emacs uses toolkit scroll bars. */
228
229 Lisp_Object Vx_toolkit_scroll_bars;
230
231 /* If a string, XTread_socket generates an event to display that string.
232 (The display is done in read_char.) */
233
234 static Lisp_Object help_echo;
235 static Lisp_Object help_echo_window;
236 static Lisp_Object help_echo_object;
237 static int help_echo_pos;
238
239 /* Temporary variable for XTread_socket. */
240
241 static Lisp_Object previous_help_echo;
242
243 /* Non-zero means that a HELP_EVENT has been generated since Emacs
244 start. */
245
246 static int any_help_event_p;
247
248 /* Non-zero means draw block and hollow cursor as wide as the glyph
249 under it. For example, if a block cursor is over a tab, it will be
250 drawn as wide as that tab on the display. */
251
252 int x_stretch_cursor_p;
253
254 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
255
256 int x_use_underline_position_properties;
257
258 /* This is a chain of structures for all the X displays currently in
259 use. */
260
261 struct x_display_info *x_display_list;
262
263 /* This is a list of cons cells, each of the form (NAME
264 . FONT-LIST-CACHE), one for each element of x_display_list and in
265 the same order. NAME is the name of the frame. FONT-LIST-CACHE
266 records previous values returned by x-list-fonts. */
267
268 Lisp_Object x_display_name_list;
269
270 /* Frame being updated by update_frame. This is declared in term.c.
271 This is set by update_begin and looked at by all the XT functions.
272 It is zero while not inside an update. In that case, the XT
273 functions assume that `selected_frame' is the frame to apply to. */
274
275 extern struct frame *updating_frame;
276
277 extern int waiting_for_input;
278
279 /* This is a frame waiting to be auto-raised, within XTread_socket. */
280
281 struct frame *pending_autoraise_frame;
282
283 #ifdef USE_X_TOOLKIT
284 /* The application context for Xt use. */
285 XtAppContext Xt_app_con;
286 static String Xt_default_resources[] = {0};
287 #endif /* USE_X_TOOLKIT */
288
289 /* Nominal cursor position -- where to draw output.
290 HPOS and VPOS are window relative glyph matrix coordinates.
291 X and Y are window relative pixel coordinates. */
292
293 struct cursor_pos output_cursor;
294
295 /* Non-zero means user is interacting with a toolkit scroll bar. */
296
297 static int toolkit_scroll_bar_interaction;
298
299 /* Mouse movement.
300
301 Formerly, we used PointerMotionHintMask (in standard_event_mask)
302 so that we would have to call XQueryPointer after each MotionNotify
303 event to ask for another such event. However, this made mouse tracking
304 slow, and there was a bug that made it eventually stop.
305
306 Simply asking for MotionNotify all the time seems to work better.
307
308 In order to avoid asking for motion events and then throwing most
309 of them away or busy-polling the server for mouse positions, we ask
310 the server for pointer motion hints. This means that we get only
311 one event per group of mouse movements. "Groups" are delimited by
312 other kinds of events (focus changes and button clicks, for
313 example), or by XQueryPointer calls; when one of these happens, we
314 get another MotionNotify event the next time the mouse moves. This
315 is at least as efficient as getting motion events when mouse
316 tracking is on, and I suspect only negligibly worse when tracking
317 is off. */
318
319 /* Where the mouse was last time we reported a mouse event. */
320
321 FRAME_PTR last_mouse_frame;
322 static XRectangle last_mouse_glyph;
323 static Lisp_Object last_mouse_press_frame;
324
325 /* The scroll bar in which the last X motion event occurred.
326
327 If the last X motion event occurred in a scroll bar, we set this so
328 XTmouse_position can know whether to report a scroll bar motion or
329 an ordinary motion.
330
331 If the last X motion event didn't occur in a scroll bar, we set
332 this to Qnil, to tell XTmouse_position to return an ordinary motion
333 event. */
334
335 static Lisp_Object last_mouse_scroll_bar;
336
337 /* This is a hack. We would really prefer that XTmouse_position would
338 return the time associated with the position it returns, but there
339 doesn't seem to be any way to wrest the time-stamp from the server
340 along with the position query. So, we just keep track of the time
341 of the last movement we received, and return that in hopes that
342 it's somewhat accurate. */
343
344 static Time last_mouse_movement_time;
345
346 /* Incremented by XTread_socket whenever it really tries to read
347 events. */
348
349 #ifdef __STDC__
350 static int volatile input_signal_count;
351 #else
352 static int input_signal_count;
353 #endif
354
355 /* Used locally within XTread_socket. */
356
357 static int x_noop_count;
358
359 /* Initial values of argv and argc. */
360
361 extern char **initial_argv;
362 extern int initial_argc;
363
364 extern Lisp_Object Vcommand_line_args, Vsystem_name;
365
366 /* Tells if a window manager is present or not. */
367
368 extern Lisp_Object Vx_no_window_manager;
369
370 extern Lisp_Object Qface, Qmouse_face;
371
372 extern int errno;
373
374 /* A mask of extra modifier bits to put into every keyboard char. */
375
376 extern int extra_keyboard_modifiers;
377
378 static Lisp_Object Qvendor_specific_keysyms;
379
380 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
381 extern Lisp_Object x_icon_type P_ ((struct frame *));
382
383
384 /* Enumeration for overriding/changing the face to use for drawing
385 glyphs in x_draw_glyphs. */
386
387 enum draw_glyphs_face
388 {
389 DRAW_NORMAL_TEXT,
390 DRAW_INVERSE_VIDEO,
391 DRAW_CURSOR,
392 DRAW_MOUSE_FACE,
393 DRAW_IMAGE_RAISED,
394 DRAW_IMAGE_SUNKEN
395 };
396
397 static int cursor_in_mouse_face_p P_ ((struct window *));
398 static int clear_mouse_face P_ ((struct x_display_info *));
399 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
400 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
401 static const XColor *x_color_cells P_ ((Display *, int *));
402 static void x_update_window_end P_ ((struct window *, int, int));
403 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
404 void x_delete_display P_ ((struct x_display_info *));
405 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
406 unsigned));
407 static int fast_find_position P_ ((struct window *, int, int *, int *,
408 int *, int *, Lisp_Object));
409 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
410 int *, int *, int *, int *, int));
411 static void set_output_cursor P_ ((struct cursor_pos *));
412 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
413 int *, int *, int *, int));
414 static void note_mode_line_highlight P_ ((struct window *, int, int));
415 static void note_mouse_highlight P_ ((struct frame *, int, int));
416 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
417 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
418 static void show_mouse_face P_ ((struct x_display_info *,
419 enum draw_glyphs_face));
420 static int x_io_error_quitter P_ ((Display *));
421 int x_catch_errors P_ ((Display *));
422 void x_uncatch_errors P_ ((Display *, int));
423 void x_lower_frame P_ ((struct frame *));
424 void x_scroll_bar_clear P_ ((struct frame *));
425 int x_had_errors_p P_ ((Display *));
426 void x_wm_set_size_hint P_ ((struct frame *, long, int));
427 void x_raise_frame P_ ((struct frame *));
428 void x_set_window_size P_ ((struct frame *, int, int, int));
429 void x_wm_set_window_state P_ ((struct frame *, int));
430 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
431 void x_initialize P_ ((void));
432 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
433 static int x_compute_min_glyph_bounds P_ ((struct frame *));
434 static void x_draw_phys_cursor_glyph P_ ((struct window *,
435 struct glyph_row *,
436 enum draw_glyphs_face));
437 static void x_update_end P_ ((struct frame *));
438 static void XTframe_up_to_date P_ ((struct frame *));
439 static void XTset_terminal_modes P_ ((void));
440 static void XTreset_terminal_modes P_ ((void));
441 static void XTcursor_to P_ ((int, int, int, int));
442 static void x_write_glyphs P_ ((struct glyph *, int));
443 static void x_clear_end_of_line P_ ((int));
444 static void x_clear_frame P_ ((void));
445 static void x_clear_cursor P_ ((struct window *));
446 static void frame_highlight P_ ((struct frame *));
447 static void frame_unhighlight P_ ((struct frame *));
448 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
449 static void XTframe_rehighlight P_ ((struct frame *));
450 static void x_frame_rehighlight P_ ((struct x_display_info *));
451 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
452 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
453 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
454 XRectangle *));
455 static void expose_frame P_ ((struct frame *, int, int, int, int));
456 static int expose_window_tree P_ ((struct window *, XRectangle *));
457 static int expose_window P_ ((struct window *, XRectangle *));
458 static void expose_area P_ ((struct window *, struct glyph_row *,
459 XRectangle *, enum glyph_row_area));
460 static int expose_line P_ ((struct window *, struct glyph_row *,
461 XRectangle *));
462 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
463 static void x_update_window_cursor P_ ((struct window *, int));
464 static void x_erase_phys_cursor P_ ((struct window *));
465 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
466 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
467 enum fringe_bitmap_type));
468
469 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
470 GC, int));
471 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
472 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
473 static void notice_overwritten_cursor P_ ((struct window *, int, int));
474 static void x_flush P_ ((struct frame *f));
475 static void x_update_begin P_ ((struct frame *));
476 static void x_update_window_begin P_ ((struct window *));
477 static void x_draw_vertical_border P_ ((struct window *));
478 static void x_after_update_window_line P_ ((struct glyph_row *));
479 static INLINE void take_vertical_position_into_account P_ ((struct it *));
480 static void x_produce_stretch_glyph P_ ((struct it *));
481 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
482 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
483 enum scroll_bar_part *,
484 Lisp_Object *, Lisp_Object *,
485 unsigned long *));
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_FRINGE_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 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
690
691 if (!w->pseudo_window_p)
692 {
693 BLOCK_INPUT;
694
695 if (cursor_on_p)
696 x_display_and_set_cursor (w, 1, output_cursor.hpos,
697 output_cursor.vpos,
698 output_cursor.x, output_cursor.y);
699
700 x_draw_vertical_border (w);
701 UNBLOCK_INPUT;
702 }
703
704 /* If a row with mouse-face was overwritten, arrange for
705 XTframe_up_to_date to redisplay the mouse highlight. */
706 if (mouse_face_overwritten_p)
707 {
708 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
709 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
710 dpyinfo->mouse_face_window = Qnil;
711 }
712
713 updated_window = NULL;
714 }
715
716
717 /* End update of frame F. This function is installed as a hook in
718 update_end. */
719
720 static void
721 x_update_end (f)
722 struct frame *f;
723 {
724 /* Mouse highlight may be displayed again. */
725 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
726
727 BLOCK_INPUT;
728 XFlush (FRAME_X_DISPLAY (f));
729 UNBLOCK_INPUT;
730 }
731
732
733 /* This function is called from various places in xdisp.c whenever a
734 complete update has been performed. The global variable
735 updated_window is not available here. */
736
737 static void
738 XTframe_up_to_date (f)
739 struct frame *f;
740 {
741 if (FRAME_X_P (f))
742 {
743 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
744
745 if (dpyinfo->mouse_face_deferred_gc
746 || f == dpyinfo->mouse_face_mouse_frame)
747 {
748 BLOCK_INPUT;
749 if (dpyinfo->mouse_face_mouse_frame)
750 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
751 dpyinfo->mouse_face_mouse_x,
752 dpyinfo->mouse_face_mouse_y);
753 dpyinfo->mouse_face_deferred_gc = 0;
754 UNBLOCK_INPUT;
755 }
756 }
757 }
758
759
760 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
761 arrow bitmaps, or clear the fringes if no bitmaps are required
762 before DESIRED_ROW is made current. The window being updated is
763 found in updated_window. This function It is called from
764 update_window_line only if it is known that there are differences
765 between bitmaps to be drawn between current row and DESIRED_ROW. */
766
767 static void
768 x_after_update_window_line (desired_row)
769 struct glyph_row *desired_row;
770 {
771 struct window *w = updated_window;
772 struct frame *f;
773 int width, height;
774
775 xassert (w);
776
777 if (!desired_row->mode_line_p && !w->pseudo_window_p)
778 {
779 BLOCK_INPUT;
780 x_draw_row_fringe_bitmaps (w, desired_row);
781 UNBLOCK_INPUT;
782 }
783
784 /* When a window has disappeared, make sure that no rest of
785 full-width rows stays visible in the internal border. Could
786 check here if updated_window is the leftmost/rightmost window,
787 but I guess it's not worth doing since vertically split windows
788 are almost never used, internal border is rarely set, and the
789 overhead is very small. */
790 if (windows_or_buffers_changed
791 && desired_row->full_width_p
792 && (f = XFRAME (w->frame),
793 width = FRAME_INTERNAL_BORDER_WIDTH (f),
794 width != 0)
795 && (height = desired_row->visible_height,
796 height > 0))
797 {
798 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
799
800 /* Internal border is drawn below the tool bar. */
801 if (WINDOWP (f->tool_bar_window)
802 && w == XWINDOW (f->tool_bar_window))
803 y -= width;
804
805 BLOCK_INPUT;
806 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
807 0, y, width, height, False);
808 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
809 f->output_data.x->pixel_width - width,
810 y, width, height, False);
811 UNBLOCK_INPUT;
812 }
813 }
814
815
816 /* Draw the bitmap WHICH in one of the left or right fringes of
817 window W. ROW is the glyph row for which to display the bitmap; it
818 determines the vertical position at which the bitmap has to be
819 drawn. */
820
821 static void
822 x_draw_fringe_bitmap (w, row, which)
823 struct window *w;
824 struct glyph_row *row;
825 enum fringe_bitmap_type which;
826 {
827 struct frame *f = XFRAME (WINDOW_FRAME (w));
828 Display *display = FRAME_X_DISPLAY (f);
829 Window window = FRAME_X_WINDOW (f);
830 int x, y, wd, h, dy;
831 unsigned char *bits;
832 Pixmap pixmap;
833 GC gc = f->output_data.x->normal_gc;
834 struct face *face;
835 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
836
837 /* Must clip because of partially visible lines. */
838 x_clip_to_row (w, row, gc, 1);
839
840 switch (which)
841 {
842 case LEFT_TRUNCATION_BITMAP:
843 wd = left_width;
844 h = left_height;
845 bits = left_bits;
846 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
847 - wd
848 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
849 break;
850
851 case OVERLAY_ARROW_BITMAP:
852 wd = left_width;
853 h = left_height;
854 bits = ov_bits;
855 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
856 - wd
857 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
858 break;
859
860 case RIGHT_TRUNCATION_BITMAP:
861 wd = right_width;
862 h = right_height;
863 bits = right_bits;
864 x = window_box_right (w, -1);
865 x += (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2;
866 break;
867
868 case CONTINUED_LINE_BITMAP:
869 wd = right_width;
870 h = right_height;
871 bits = continued_bits;
872 x = window_box_right (w, -1);
873 x += (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2;
874 break;
875
876 case CONTINUATION_LINE_BITMAP:
877 wd = continuation_width;
878 h = continuation_height;
879 bits = continuation_bits;
880 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
881 - wd
882 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
883 break;
884
885 case ZV_LINE_BITMAP:
886 wd = zv_width;
887 h = zv_height;
888 bits = zv_bits;
889 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
890 - wd
891 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
892 break;
893
894 default:
895 abort ();
896 }
897
898 /* Convert to frame coordinates. Set dy to the offset in the row to
899 start drawing the bitmap. */
900 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
901 dy = (row->height - h) / 2;
902
903 /* Draw the bitmap. I believe these small pixmaps can be cached
904 by the server. */
905 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
906 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
907 face->foreground,
908 face->background, depth);
909 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
910 XFreePixmap (display, pixmap);
911 XSetClipMask (display, gc, None);
912 }
913
914
915 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
916 function with input blocked. */
917
918 static void
919 x_draw_row_fringe_bitmaps (w, row)
920 struct window *w;
921 struct glyph_row *row;
922 {
923 struct frame *f = XFRAME (w->frame);
924 enum fringe_bitmap_type bitmap;
925 struct face *face;
926 int header_line_height = -1;
927
928 xassert (interrupt_input_blocked);
929
930 /* If row is completely invisible, because of vscrolling, we
931 don't have to draw anything. */
932 if (row->visible_height <= 0)
933 return;
934
935 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
936 PREPARE_FACE_FOR_DISPLAY (f, face);
937
938 /* Decide which bitmap to draw in the left fringe. */
939 if (row->overlay_arrow_p)
940 bitmap = OVERLAY_ARROW_BITMAP;
941 else if (row->truncated_on_left_p)
942 bitmap = LEFT_TRUNCATION_BITMAP;
943 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
944 bitmap = CONTINUATION_LINE_BITMAP;
945 else if (row->indicate_empty_line_p)
946 bitmap = ZV_LINE_BITMAP;
947 else
948 bitmap = NO_FRINGE_BITMAP;
949
950 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
951 the fringe. */
952 if (bitmap == NO_FRINGE_BITMAP
953 || FRAME_FRINGE_BITMAP_WIDTH (f) < FRAME_X_LEFT_FRINGE_WIDTH (f)
954 || row->height > FRAME_FRINGE_BITMAP_HEIGHT (f))
955 {
956 /* If W has a vertical border to its left, don't draw over it. */
957 int border = ((XFASTINT (w->left) > 0
958 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
959 ? 1 : 0);
960 int left = window_box_left (w, -1);
961
962 if (header_line_height < 0)
963 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
964
965 /* In case the same realized face is used for fringes and
966 for something displayed in the text (e.g. face `region' on
967 mono-displays, the fill style may have been changed to
968 FillSolid in x_draw_glyph_string_background. */
969 if (face->stipple)
970 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
971 else
972 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
973
974 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
975 face->gc,
976 (left
977 - FRAME_X_LEFT_FRINGE_WIDTH (f)
978 + border),
979 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
980 row->y)),
981 FRAME_X_LEFT_FRINGE_WIDTH (f) - border,
982 row->visible_height);
983 if (!face->stipple)
984 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
985 }
986
987 /* Draw the left bitmap. */
988 if (bitmap != NO_FRINGE_BITMAP)
989 x_draw_fringe_bitmap (w, row, bitmap);
990
991 /* Decide which bitmap to draw in the right fringe. */
992 if (row->truncated_on_right_p)
993 bitmap = RIGHT_TRUNCATION_BITMAP;
994 else if (row->continued_p)
995 bitmap = CONTINUED_LINE_BITMAP;
996 else
997 bitmap = NO_FRINGE_BITMAP;
998
999 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
1000 the fringe. */
1001 if (bitmap == NO_FRINGE_BITMAP
1002 || FRAME_FRINGE_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FRINGE_WIDTH (f)
1003 || row->height > FRAME_FRINGE_BITMAP_HEIGHT (f))
1004 {
1005 int right = window_box_right (w, -1);
1006
1007 if (header_line_height < 0)
1008 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
1009
1010 /* In case the same realized face is used for fringes and
1011 for something displayed in the text (e.g. face `region' on
1012 mono-displays, the fill style may have been changed to
1013 FillSolid in x_draw_glyph_string_background. */
1014 if (face->stipple)
1015 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1016 else
1017 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1018 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1019 face->gc,
1020 right,
1021 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1022 row->y)),
1023 FRAME_X_RIGHT_FRINGE_WIDTH (f),
1024 row->visible_height);
1025 if (!face->stipple)
1026 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1027 }
1028
1029 /* Draw the right bitmap. */
1030 if (bitmap != NO_FRINGE_BITMAP)
1031 x_draw_fringe_bitmap (w, row, bitmap);
1032 }
1033
1034 \f
1035
1036 /* This is called when starting Emacs and when restarting after
1037 suspend. When starting Emacs, no X window is mapped. And nothing
1038 must be done to Emacs's own window if it is suspended (though that
1039 rarely happens). */
1040
1041 static void
1042 XTset_terminal_modes ()
1043 {
1044 }
1045
1046 /* This is called when exiting or suspending Emacs. Exiting will make
1047 the X-windows go away, and suspending requires no action. */
1048
1049 static void
1050 XTreset_terminal_modes ()
1051 {
1052 }
1053
1054
1055 \f
1056 /***********************************************************************
1057 Output Cursor
1058 ***********************************************************************/
1059
1060 /* Set the global variable output_cursor to CURSOR. All cursor
1061 positions are relative to updated_window. */
1062
1063 static void
1064 set_output_cursor (cursor)
1065 struct cursor_pos *cursor;
1066 {
1067 output_cursor.hpos = cursor->hpos;
1068 output_cursor.vpos = cursor->vpos;
1069 output_cursor.x = cursor->x;
1070 output_cursor.y = cursor->y;
1071 }
1072
1073
1074 /* Set a nominal cursor position.
1075
1076 HPOS and VPOS are column/row positions in a window glyph matrix. X
1077 and Y are window text area relative pixel positions.
1078
1079 If this is done during an update, updated_window will contain the
1080 window that is being updated and the position is the future output
1081 cursor position for that window. If updated_window is null, use
1082 selected_window and display the cursor at the given position. */
1083
1084 static void
1085 XTcursor_to (vpos, hpos, y, x)
1086 int vpos, hpos, y, x;
1087 {
1088 struct window *w;
1089
1090 /* If updated_window is not set, work on selected_window. */
1091 if (updated_window)
1092 w = updated_window;
1093 else
1094 w = XWINDOW (selected_window);
1095
1096 /* Set the output cursor. */
1097 output_cursor.hpos = hpos;
1098 output_cursor.vpos = vpos;
1099 output_cursor.x = x;
1100 output_cursor.y = y;
1101
1102 /* If not called as part of an update, really display the cursor.
1103 This will also set the cursor position of W. */
1104 if (updated_window == NULL)
1105 {
1106 BLOCK_INPUT;
1107 x_display_cursor (w, 1, hpos, vpos, x, y);
1108 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1109 UNBLOCK_INPUT;
1110 }
1111 }
1112
1113
1114 \f
1115 /***********************************************************************
1116 Display Iterator
1117 ***********************************************************************/
1118
1119 /* Function prototypes of this page. */
1120
1121 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1122 struct glyph *,
1123 XChar2b *,
1124 int *));
1125 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1126 int, XChar2b *, int));
1127 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1128 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1129 static void x_append_glyph P_ ((struct it *));
1130 static void x_append_composite_glyph P_ ((struct it *));
1131 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1132 int, int, double));
1133 static void x_produce_glyphs P_ ((struct it *));
1134 static void x_produce_image_glyph P_ ((struct it *it));
1135
1136
1137 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1138 is not contained in the font. */
1139
1140 static INLINE XCharStruct *
1141 x_per_char_metric (font, char2b)
1142 XFontStruct *font;
1143 XChar2b *char2b;
1144 {
1145 /* The result metric information. */
1146 XCharStruct *pcm = NULL;
1147
1148 xassert (font && char2b);
1149
1150 if (font->per_char != NULL)
1151 {
1152 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1153 {
1154 /* min_char_or_byte2 specifies the linear character index
1155 corresponding to the first element of the per_char array,
1156 max_char_or_byte2 is the index of the last character. A
1157 character with non-zero CHAR2B->byte1 is not in the font.
1158 A character with byte2 less than min_char_or_byte2 or
1159 greater max_char_or_byte2 is not in the font. */
1160 if (char2b->byte1 == 0
1161 && char2b->byte2 >= font->min_char_or_byte2
1162 && char2b->byte2 <= font->max_char_or_byte2)
1163 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1164 }
1165 else
1166 {
1167 /* If either min_byte1 or max_byte1 are nonzero, both
1168 min_char_or_byte2 and max_char_or_byte2 are less than
1169 256, and the 2-byte character index values corresponding
1170 to the per_char array element N (counting from 0) are:
1171
1172 byte1 = N/D + min_byte1
1173 byte2 = N\D + min_char_or_byte2
1174
1175 where:
1176
1177 D = max_char_or_byte2 - min_char_or_byte2 + 1
1178 / = integer division
1179 \ = integer modulus */
1180 if (char2b->byte1 >= font->min_byte1
1181 && char2b->byte1 <= font->max_byte1
1182 && char2b->byte2 >= font->min_char_or_byte2
1183 && char2b->byte2 <= font->max_char_or_byte2)
1184 {
1185 pcm = (font->per_char
1186 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1187 * (char2b->byte1 - font->min_byte1))
1188 + (char2b->byte2 - font->min_char_or_byte2));
1189 }
1190 }
1191 }
1192 else
1193 {
1194 /* If the per_char pointer is null, all glyphs between the first
1195 and last character indexes inclusive have the same
1196 information, as given by both min_bounds and max_bounds. */
1197 if (char2b->byte2 >= font->min_char_or_byte2
1198 && char2b->byte2 <= font->max_char_or_byte2)
1199 pcm = &font->max_bounds;
1200 }
1201
1202 return ((pcm == NULL
1203 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1204 ? NULL : pcm);
1205 }
1206
1207
1208 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1209 the two-byte form of C. Encoding is returned in *CHAR2B. */
1210
1211 static INLINE void
1212 x_encode_char (c, char2b, font_info)
1213 int c;
1214 XChar2b *char2b;
1215 struct font_info *font_info;
1216 {
1217 int charset = CHAR_CHARSET (c);
1218 XFontStruct *font = font_info->font;
1219
1220 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1221 This may be either a program in a special encoder language or a
1222 fixed encoding. */
1223 if (font_info->font_encoder)
1224 {
1225 /* It's a program. */
1226 struct ccl_program *ccl = font_info->font_encoder;
1227
1228 if (CHARSET_DIMENSION (charset) == 1)
1229 {
1230 ccl->reg[0] = charset;
1231 ccl->reg[1] = char2b->byte2;
1232 }
1233 else
1234 {
1235 ccl->reg[0] = charset;
1236 ccl->reg[1] = char2b->byte1;
1237 ccl->reg[2] = char2b->byte2;
1238 }
1239
1240 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1241
1242 /* We assume that MSBs are appropriately set/reset by CCL
1243 program. */
1244 if (font->max_byte1 == 0) /* 1-byte font */
1245 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1246 else
1247 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1248 }
1249 else if (font_info->encoding[charset])
1250 {
1251 /* Fixed encoding scheme. See fontset.h for the meaning of the
1252 encoding numbers. */
1253 int enc = font_info->encoding[charset];
1254
1255 if ((enc == 1 || enc == 2)
1256 && CHARSET_DIMENSION (charset) == 2)
1257 char2b->byte1 |= 0x80;
1258
1259 if (enc == 1 || enc == 3)
1260 char2b->byte2 |= 0x80;
1261 }
1262 }
1263
1264
1265 /* Get face and two-byte form of character C in face FACE_ID on frame
1266 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1267 means we want to display multibyte text. Value is a pointer to a
1268 realized face that is ready for display. */
1269
1270 static INLINE struct face *
1271 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1272 struct frame *f;
1273 int c, face_id;
1274 XChar2b *char2b;
1275 int multibyte_p;
1276 {
1277 struct face *face = FACE_FROM_ID (f, face_id);
1278
1279 if (!multibyte_p)
1280 {
1281 /* Unibyte case. We don't have to encode, but we have to make
1282 sure to use a face suitable for unibyte. */
1283 char2b->byte1 = 0;
1284 char2b->byte2 = c;
1285 face_id = FACE_FOR_CHAR (f, face, c);
1286 face = FACE_FROM_ID (f, face_id);
1287 }
1288 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1289 {
1290 /* Case of ASCII in a face known to fit ASCII. */
1291 char2b->byte1 = 0;
1292 char2b->byte2 = c;
1293 }
1294 else
1295 {
1296 int c1, c2, charset;
1297
1298 /* Split characters into bytes. If c2 is -1 afterwards, C is
1299 really a one-byte character so that byte1 is zero. */
1300 SPLIT_CHAR (c, charset, c1, c2);
1301 if (c2 > 0)
1302 char2b->byte1 = c1, char2b->byte2 = c2;
1303 else
1304 char2b->byte1 = 0, char2b->byte2 = c1;
1305
1306 /* Maybe encode the character in *CHAR2B. */
1307 if (face->font != NULL)
1308 {
1309 struct font_info *font_info
1310 = FONT_INFO_FROM_ID (f, face->font_info_id);
1311 if (font_info)
1312 x_encode_char (c, char2b, font_info);
1313 }
1314 }
1315
1316 /* Make sure X resources of the face are allocated. */
1317 xassert (face != NULL);
1318 PREPARE_FACE_FOR_DISPLAY (f, face);
1319
1320 return face;
1321 }
1322
1323
1324 /* Get face and two-byte form of character glyph GLYPH on frame F.
1325 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1326 a pointer to a realized face that is ready for display. */
1327
1328 static INLINE struct face *
1329 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1330 struct frame *f;
1331 struct glyph *glyph;
1332 XChar2b *char2b;
1333 int *two_byte_p;
1334 {
1335 struct face *face;
1336
1337 xassert (glyph->type == CHAR_GLYPH);
1338 face = FACE_FROM_ID (f, glyph->face_id);
1339
1340 if (two_byte_p)
1341 *two_byte_p = 0;
1342
1343 if (!glyph->multibyte_p)
1344 {
1345 /* Unibyte case. We don't have to encode, but we have to make
1346 sure to use a face suitable for unibyte. */
1347 char2b->byte1 = 0;
1348 char2b->byte2 = glyph->u.ch;
1349 }
1350 else if (glyph->u.ch < 128
1351 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1352 {
1353 /* Case of ASCII in a face known to fit ASCII. */
1354 char2b->byte1 = 0;
1355 char2b->byte2 = glyph->u.ch;
1356 }
1357 else
1358 {
1359 int c1, c2, charset;
1360
1361 /* Split characters into bytes. If c2 is -1 afterwards, C is
1362 really a one-byte character so that byte1 is zero. */
1363 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1364 if (c2 > 0)
1365 char2b->byte1 = c1, char2b->byte2 = c2;
1366 else
1367 char2b->byte1 = 0, char2b->byte2 = c1;
1368
1369 /* Maybe encode the character in *CHAR2B. */
1370 if (charset != CHARSET_ASCII)
1371 {
1372 struct font_info *font_info
1373 = FONT_INFO_FROM_ID (f, face->font_info_id);
1374 if (font_info)
1375 {
1376 x_encode_char (glyph->u.ch, char2b, font_info);
1377 if (two_byte_p)
1378 *two_byte_p
1379 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1380 }
1381 }
1382 }
1383
1384 /* Make sure X resources of the face are allocated. */
1385 xassert (face != NULL);
1386 PREPARE_FACE_FOR_DISPLAY (f, face);
1387 return face;
1388 }
1389
1390
1391 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1392 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1393
1394 static INLINE void
1395 x_append_glyph (it)
1396 struct it *it;
1397 {
1398 struct glyph *glyph;
1399 enum glyph_row_area area = it->area;
1400
1401 xassert (it->glyph_row);
1402 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1403
1404 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1405 if (glyph < it->glyph_row->glyphs[area + 1])
1406 {
1407 glyph->charpos = CHARPOS (it->position);
1408 glyph->object = it->object;
1409 glyph->pixel_width = it->pixel_width;
1410 glyph->voffset = it->voffset;
1411 glyph->type = CHAR_GLYPH;
1412 glyph->multibyte_p = it->multibyte_p;
1413 glyph->left_box_line_p = it->start_of_box_run_p;
1414 glyph->right_box_line_p = it->end_of_box_run_p;
1415 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1416 || it->phys_descent > it->descent);
1417 glyph->padding_p = 0;
1418 glyph->glyph_not_available_p = it->glyph_not_available_p;
1419 glyph->face_id = it->face_id;
1420 glyph->u.ch = it->char_to_display;
1421 ++it->glyph_row->used[area];
1422 }
1423 }
1424
1425 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1426 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1427
1428 static INLINE void
1429 x_append_composite_glyph (it)
1430 struct it *it;
1431 {
1432 struct glyph *glyph;
1433 enum glyph_row_area area = it->area;
1434
1435 xassert (it->glyph_row);
1436
1437 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1438 if (glyph < it->glyph_row->glyphs[area + 1])
1439 {
1440 glyph->charpos = CHARPOS (it->position);
1441 glyph->object = it->object;
1442 glyph->pixel_width = it->pixel_width;
1443 glyph->voffset = it->voffset;
1444 glyph->type = COMPOSITE_GLYPH;
1445 glyph->multibyte_p = it->multibyte_p;
1446 glyph->left_box_line_p = it->start_of_box_run_p;
1447 glyph->right_box_line_p = it->end_of_box_run_p;
1448 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1449 || it->phys_descent > it->descent);
1450 glyph->padding_p = 0;
1451 glyph->glyph_not_available_p = 0;
1452 glyph->face_id = it->face_id;
1453 glyph->u.cmp_id = it->cmp_id;
1454 ++it->glyph_row->used[area];
1455 }
1456 }
1457
1458
1459 /* Change IT->ascent and IT->height according to the setting of
1460 IT->voffset. */
1461
1462 static INLINE void
1463 take_vertical_position_into_account (it)
1464 struct it *it;
1465 {
1466 if (it->voffset)
1467 {
1468 if (it->voffset < 0)
1469 /* Increase the ascent so that we can display the text higher
1470 in the line. */
1471 it->ascent += abs (it->voffset);
1472 else
1473 /* Increase the descent so that we can display the text lower
1474 in the line. */
1475 it->descent += it->voffset;
1476 }
1477 }
1478
1479
1480 /* Produce glyphs/get display metrics for the image IT is loaded with.
1481 See the description of struct display_iterator in dispextern.h for
1482 an overview of struct display_iterator. */
1483
1484 static void
1485 x_produce_image_glyph (it)
1486 struct it *it;
1487 {
1488 struct image *img;
1489 struct face *face;
1490
1491 xassert (it->what == IT_IMAGE);
1492
1493 face = FACE_FROM_ID (it->f, it->face_id);
1494 img = IMAGE_FROM_ID (it->f, it->image_id);
1495 xassert (img);
1496
1497 /* Make sure X resources of the face and image are loaded. */
1498 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1499 prepare_image_for_display (it->f, img);
1500
1501 it->ascent = it->phys_ascent = image_ascent (img, face);
1502 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1503 it->pixel_width = img->width + 2 * img->hmargin;
1504
1505 it->nglyphs = 1;
1506
1507 if (face->box != FACE_NO_BOX)
1508 {
1509 if (face->box_line_width > 0)
1510 {
1511 it->ascent += face->box_line_width;
1512 it->descent += face->box_line_width;
1513 }
1514
1515 if (it->start_of_box_run_p)
1516 it->pixel_width += abs (face->box_line_width);
1517 if (it->end_of_box_run_p)
1518 it->pixel_width += abs (face->box_line_width);
1519 }
1520
1521 take_vertical_position_into_account (it);
1522
1523 if (it->glyph_row)
1524 {
1525 struct glyph *glyph;
1526 enum glyph_row_area area = it->area;
1527
1528 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1529 if (glyph < it->glyph_row->glyphs[area + 1])
1530 {
1531 glyph->charpos = CHARPOS (it->position);
1532 glyph->object = it->object;
1533 glyph->pixel_width = it->pixel_width;
1534 glyph->voffset = it->voffset;
1535 glyph->type = IMAGE_GLYPH;
1536 glyph->multibyte_p = it->multibyte_p;
1537 glyph->left_box_line_p = it->start_of_box_run_p;
1538 glyph->right_box_line_p = it->end_of_box_run_p;
1539 glyph->overlaps_vertically_p = 0;
1540 glyph->padding_p = 0;
1541 glyph->glyph_not_available_p = 0;
1542 glyph->face_id = it->face_id;
1543 glyph->u.img_id = img->id;
1544 ++it->glyph_row->used[area];
1545 }
1546 }
1547 }
1548
1549
1550 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1551 of the glyph, WIDTH and HEIGHT are the width and height of the
1552 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1553 ascent of the glyph (0 <= ASCENT <= 1). */
1554
1555 static void
1556 x_append_stretch_glyph (it, object, width, height, ascent)
1557 struct it *it;
1558 Lisp_Object object;
1559 int width, height;
1560 double ascent;
1561 {
1562 struct glyph *glyph;
1563 enum glyph_row_area area = it->area;
1564
1565 xassert (ascent >= 0 && ascent <= 1);
1566
1567 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1568 if (glyph < it->glyph_row->glyphs[area + 1])
1569 {
1570 glyph->charpos = CHARPOS (it->position);
1571 glyph->object = object;
1572 glyph->pixel_width = width;
1573 glyph->voffset = it->voffset;
1574 glyph->type = STRETCH_GLYPH;
1575 glyph->multibyte_p = it->multibyte_p;
1576 glyph->left_box_line_p = it->start_of_box_run_p;
1577 glyph->right_box_line_p = it->end_of_box_run_p;
1578 glyph->overlaps_vertically_p = 0;
1579 glyph->padding_p = 0;
1580 glyph->glyph_not_available_p = 0;
1581 glyph->face_id = it->face_id;
1582 glyph->u.stretch.ascent = height * ascent;
1583 glyph->u.stretch.height = height;
1584 ++it->glyph_row->used[area];
1585 }
1586 }
1587
1588
1589 /* Produce a stretch glyph for iterator IT. IT->object is the value
1590 of the glyph property displayed. The value must be a list
1591 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1592 being recognized:
1593
1594 1. `:width WIDTH' specifies that the space should be WIDTH *
1595 canonical char width wide. WIDTH may be an integer or floating
1596 point number.
1597
1598 2. `:relative-width FACTOR' specifies that the width of the stretch
1599 should be computed from the width of the first character having the
1600 `glyph' property, and should be FACTOR times that width.
1601
1602 3. `:align-to HPOS' specifies that the space should be wide enough
1603 to reach HPOS, a value in canonical character units.
1604
1605 Exactly one of the above pairs must be present.
1606
1607 4. `:height HEIGHT' specifies that the height of the stretch produced
1608 should be HEIGHT, measured in canonical character units.
1609
1610 5. `:relative-height FACTOR' specifies that the height of the the
1611 stretch should be FACTOR times the height of the characters having
1612 the glyph property.
1613
1614 Either none or exactly one of 4 or 5 must be present.
1615
1616 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1617 of the stretch should be used for the ascent of the stretch.
1618 ASCENT must be in the range 0 <= ASCENT <= 100. */
1619
1620 #define NUMVAL(X) \
1621 ((INTEGERP (X) || FLOATP (X)) \
1622 ? XFLOATINT (X) \
1623 : - 1)
1624
1625
1626 static void
1627 x_produce_stretch_glyph (it)
1628 struct it *it;
1629 {
1630 /* (space :width WIDTH :height HEIGHT. */
1631 #if GLYPH_DEBUG
1632 extern Lisp_Object Qspace;
1633 #endif
1634 extern Lisp_Object QCwidth, QCheight, QCascent;
1635 extern Lisp_Object QCrelative_width, QCrelative_height;
1636 extern Lisp_Object QCalign_to;
1637 Lisp_Object prop, plist;
1638 double width = 0, height = 0, ascent = 0;
1639 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1640 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1641
1642 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1643
1644 /* List should start with `space'. */
1645 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1646 plist = XCDR (it->object);
1647
1648 /* Compute the width of the stretch. */
1649 if (prop = Fplist_get (plist, QCwidth),
1650 NUMVAL (prop) > 0)
1651 /* Absolute width `:width WIDTH' specified and valid. */
1652 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1653 else if (prop = Fplist_get (plist, QCrelative_width),
1654 NUMVAL (prop) > 0)
1655 {
1656 /* Relative width `:relative-width FACTOR' specified and valid.
1657 Compute the width of the characters having the `glyph'
1658 property. */
1659 struct it it2;
1660 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1661
1662 it2 = *it;
1663 if (it->multibyte_p)
1664 {
1665 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1666 - IT_BYTEPOS (*it));
1667 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1668 }
1669 else
1670 it2.c = *p, it2.len = 1;
1671
1672 it2.glyph_row = NULL;
1673 it2.what = IT_CHARACTER;
1674 x_produce_glyphs (&it2);
1675 width = NUMVAL (prop) * it2.pixel_width;
1676 }
1677 else if (prop = Fplist_get (plist, QCalign_to),
1678 NUMVAL (prop) > 0)
1679 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1680 else
1681 /* Nothing specified -> width defaults to canonical char width. */
1682 width = CANON_X_UNIT (it->f);
1683
1684 /* Compute height. */
1685 if (prop = Fplist_get (plist, QCheight),
1686 NUMVAL (prop) > 0)
1687 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1688 else if (prop = Fplist_get (plist, QCrelative_height),
1689 NUMVAL (prop) > 0)
1690 height = FONT_HEIGHT (font) * NUMVAL (prop);
1691 else
1692 height = FONT_HEIGHT (font);
1693
1694 /* Compute percentage of height used for ascent. If
1695 `:ascent ASCENT' is present and valid, use that. Otherwise,
1696 derive the ascent from the font in use. */
1697 if (prop = Fplist_get (plist, QCascent),
1698 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1699 ascent = NUMVAL (prop) / 100.0;
1700 else
1701 ascent = (double) font->ascent / FONT_HEIGHT (font);
1702
1703 if (width <= 0)
1704 width = 1;
1705 if (height <= 0)
1706 height = 1;
1707
1708 if (it->glyph_row)
1709 {
1710 Lisp_Object object = it->stack[it->sp - 1].string;
1711 if (!STRINGP (object))
1712 object = it->w->buffer;
1713 x_append_stretch_glyph (it, object, width, height, ascent);
1714 }
1715
1716 it->pixel_width = width;
1717 it->ascent = it->phys_ascent = height * ascent;
1718 it->descent = it->phys_descent = height - it->ascent;
1719 it->nglyphs = 1;
1720
1721 if (face->box != FACE_NO_BOX)
1722 {
1723 if (face->box_line_width > 0)
1724 {
1725 it->ascent += face->box_line_width;
1726 it->descent += face->box_line_width;
1727 }
1728
1729 if (it->start_of_box_run_p)
1730 it->pixel_width += abs (face->box_line_width);
1731 if (it->end_of_box_run_p)
1732 it->pixel_width += abs (face->box_line_width);
1733 }
1734
1735 take_vertical_position_into_account (it);
1736 }
1737
1738 /* Return proper value to be used as baseline offset of font that has
1739 ASCENT and DESCENT to draw characters by the font at the vertical
1740 center of the line of frame F.
1741
1742 Here, out task is to find the value of BOFF in the following figure;
1743
1744 -------------------------+-----------+-
1745 -+-+---------+-+ | |
1746 | | | | | |
1747 | | | | F_ASCENT F_HEIGHT
1748 | | | ASCENT | |
1749 HEIGHT | | | | |
1750 | | |-|-+------+-----------|------- baseline
1751 | | | | BOFF | |
1752 | |---------|-+-+ | |
1753 | | | DESCENT | |
1754 -+-+---------+-+ F_DESCENT |
1755 -------------------------+-----------+-
1756
1757 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1758 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1759 DESCENT = FONT->descent
1760 HEIGHT = FONT_HEIGHT (FONT)
1761 F_DESCENT = (F->output_data.x->font->descent
1762 - F->output_data.x->baseline_offset)
1763 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1764 */
1765
1766 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1767 ((FONT)->descent \
1768 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1769 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1770 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1771
1772 /* Produce glyphs/get display metrics for the display element IT is
1773 loaded with. See the description of struct display_iterator in
1774 dispextern.h for an overview of struct display_iterator. */
1775
1776 static void
1777 x_produce_glyphs (it)
1778 struct it *it;
1779 {
1780 it->glyph_not_available_p = 0;
1781
1782 if (it->what == IT_CHARACTER)
1783 {
1784 XChar2b char2b;
1785 XFontStruct *font;
1786 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1787 XCharStruct *pcm;
1788 int font_not_found_p;
1789 struct font_info *font_info;
1790 int boff; /* baseline offset */
1791 /* We may change it->multibyte_p upon unibyte<->multibyte
1792 conversion. So, save the current value now and restore it
1793 later.
1794
1795 Note: It seems that we don't have to record multibyte_p in
1796 struct glyph because the character code itself tells if or
1797 not the character is multibyte. Thus, in the future, we must
1798 consider eliminating the field `multibyte_p' in the struct
1799 glyph. */
1800 int saved_multibyte_p = it->multibyte_p;
1801
1802 /* Maybe translate single-byte characters to multibyte, or the
1803 other way. */
1804 it->char_to_display = it->c;
1805 if (!ASCII_BYTE_P (it->c))
1806 {
1807 if (unibyte_display_via_language_environment
1808 && SINGLE_BYTE_CHAR_P (it->c)
1809 && (it->c >= 0240
1810 || !NILP (Vnonascii_translation_table)))
1811 {
1812 it->char_to_display = unibyte_char_to_multibyte (it->c);
1813 it->multibyte_p = 1;
1814 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1815 face = FACE_FROM_ID (it->f, it->face_id);
1816 }
1817 else if (!SINGLE_BYTE_CHAR_P (it->c)
1818 && !it->multibyte_p)
1819 {
1820 it->multibyte_p = 1;
1821 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1822 face = FACE_FROM_ID (it->f, it->face_id);
1823 }
1824 }
1825
1826 /* Get font to use. Encode IT->char_to_display. */
1827 x_get_char_face_and_encoding (it->f, it->char_to_display,
1828 it->face_id, &char2b,
1829 it->multibyte_p);
1830 font = face->font;
1831
1832 /* When no suitable font found, use the default font. */
1833 font_not_found_p = font == NULL;
1834 if (font_not_found_p)
1835 {
1836 font = FRAME_FONT (it->f);
1837 boff = it->f->output_data.x->baseline_offset;
1838 font_info = NULL;
1839 }
1840 else
1841 {
1842 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1843 boff = font_info->baseline_offset;
1844 if (font_info->vertical_centering)
1845 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1846 }
1847
1848 if (it->char_to_display >= ' '
1849 && (!it->multibyte_p || it->char_to_display < 128))
1850 {
1851 /* Either unibyte or ASCII. */
1852 int stretched_p;
1853
1854 it->nglyphs = 1;
1855
1856 pcm = x_per_char_metric (font, &char2b);
1857 it->ascent = font->ascent + boff;
1858 it->descent = font->descent - boff;
1859
1860 if (pcm)
1861 {
1862 it->phys_ascent = pcm->ascent + boff;
1863 it->phys_descent = pcm->descent - boff;
1864 it->pixel_width = pcm->width;
1865 }
1866 else
1867 {
1868 it->glyph_not_available_p = 1;
1869 it->phys_ascent = font->ascent + boff;
1870 it->phys_descent = font->descent - boff;
1871 it->pixel_width = FONT_WIDTH (font);
1872 }
1873
1874 /* If this is a space inside a region of text with
1875 `space-width' property, change its width. */
1876 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1877 if (stretched_p)
1878 it->pixel_width *= XFLOATINT (it->space_width);
1879
1880 /* If face has a box, add the box thickness to the character
1881 height. If character has a box line to the left and/or
1882 right, add the box line width to the character's width. */
1883 if (face->box != FACE_NO_BOX)
1884 {
1885 int thick = face->box_line_width;
1886
1887 if (thick > 0)
1888 {
1889 it->ascent += thick;
1890 it->descent += thick;
1891 }
1892 else
1893 thick = -thick;
1894
1895 if (it->start_of_box_run_p)
1896 it->pixel_width += thick;
1897 if (it->end_of_box_run_p)
1898 it->pixel_width += thick;
1899 }
1900
1901 /* If face has an overline, add the height of the overline
1902 (1 pixel) and a 1 pixel margin to the character height. */
1903 if (face->overline_p)
1904 it->ascent += 2;
1905
1906 take_vertical_position_into_account (it);
1907
1908 /* If we have to actually produce glyphs, do it. */
1909 if (it->glyph_row)
1910 {
1911 if (stretched_p)
1912 {
1913 /* Translate a space with a `space-width' property
1914 into a stretch glyph. */
1915 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1916 x_append_stretch_glyph (it, it->object, it->pixel_width,
1917 it->ascent + it->descent, ascent);
1918 }
1919 else
1920 x_append_glyph (it);
1921
1922 /* If characters with lbearing or rbearing are displayed
1923 in this line, record that fact in a flag of the
1924 glyph row. This is used to optimize X output code. */
1925 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1926 it->glyph_row->contains_overlapping_glyphs_p = 1;
1927 }
1928 }
1929 else if (it->char_to_display == '\n')
1930 {
1931 /* A newline has no width but we need the height of the line. */
1932 it->pixel_width = 0;
1933 it->nglyphs = 0;
1934 it->ascent = it->phys_ascent = font->ascent + boff;
1935 it->descent = it->phys_descent = font->descent - boff;
1936
1937 if (face->box != FACE_NO_BOX
1938 && face->box_line_width > 0)
1939 {
1940 it->ascent += face->box_line_width;
1941 it->descent += face->box_line_width;
1942 }
1943 }
1944 else if (it->char_to_display == '\t')
1945 {
1946 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1947 int x = it->current_x + it->continuation_lines_width;
1948 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1949
1950 /* If the distance from the current position to the next tab
1951 stop is less than a canonical character width, use the
1952 tab stop after that. */
1953 if (next_tab_x - x < CANON_X_UNIT (it->f))
1954 next_tab_x += tab_width;
1955
1956 it->pixel_width = next_tab_x - x;
1957 it->nglyphs = 1;
1958 it->ascent = it->phys_ascent = font->ascent + boff;
1959 it->descent = it->phys_descent = font->descent - boff;
1960
1961 if (it->glyph_row)
1962 {
1963 double ascent = (double) it->ascent / (it->ascent + it->descent);
1964 x_append_stretch_glyph (it, it->object, it->pixel_width,
1965 it->ascent + it->descent, ascent);
1966 }
1967 }
1968 else
1969 {
1970 /* A multi-byte character. Assume that the display width of the
1971 character is the width of the character multiplied by the
1972 width of the font. */
1973
1974 /* If we found a font, this font should give us the right
1975 metrics. If we didn't find a font, use the frame's
1976 default font and calculate the width of the character
1977 from the charset width; this is what old redisplay code
1978 did. */
1979 pcm = x_per_char_metric (font, &char2b);
1980 if (font_not_found_p || !pcm)
1981 {
1982 int charset = CHAR_CHARSET (it->char_to_display);
1983
1984 it->glyph_not_available_p = 1;
1985 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1986 * CHARSET_WIDTH (charset));
1987 it->phys_ascent = font->ascent + boff;
1988 it->phys_descent = font->descent - boff;
1989 }
1990 else
1991 {
1992 it->pixel_width = pcm->width;
1993 it->phys_ascent = pcm->ascent + boff;
1994 it->phys_descent = pcm->descent - boff;
1995 if (it->glyph_row
1996 && (pcm->lbearing < 0
1997 || pcm->rbearing > pcm->width))
1998 it->glyph_row->contains_overlapping_glyphs_p = 1;
1999 }
2000 it->nglyphs = 1;
2001 it->ascent = font->ascent + boff;
2002 it->descent = font->descent - boff;
2003 if (face->box != FACE_NO_BOX)
2004 {
2005 int thick = face->box_line_width;
2006
2007 if (thick > 0)
2008 {
2009 it->ascent += thick;
2010 it->descent += thick;
2011 }
2012 else
2013 thick = - thick;
2014
2015 if (it->start_of_box_run_p)
2016 it->pixel_width += thick;
2017 if (it->end_of_box_run_p)
2018 it->pixel_width += thick;
2019 }
2020
2021 /* If face has an overline, add the height of the overline
2022 (1 pixel) and a 1 pixel margin to the character height. */
2023 if (face->overline_p)
2024 it->ascent += 2;
2025
2026 take_vertical_position_into_account (it);
2027
2028 if (it->glyph_row)
2029 x_append_glyph (it);
2030 }
2031 it->multibyte_p = saved_multibyte_p;
2032 }
2033 else if (it->what == IT_COMPOSITION)
2034 {
2035 /* Note: A composition is represented as one glyph in the
2036 glyph matrix. There are no padding glyphs. */
2037 XChar2b char2b;
2038 XFontStruct *font;
2039 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2040 XCharStruct *pcm;
2041 int font_not_found_p;
2042 struct font_info *font_info;
2043 int boff; /* baseline offset */
2044 struct composition *cmp = composition_table[it->cmp_id];
2045
2046 /* Maybe translate single-byte characters to multibyte. */
2047 it->char_to_display = it->c;
2048 if (unibyte_display_via_language_environment
2049 && SINGLE_BYTE_CHAR_P (it->c)
2050 && (it->c >= 0240
2051 || (it->c >= 0200
2052 && !NILP (Vnonascii_translation_table))))
2053 {
2054 it->char_to_display = unibyte_char_to_multibyte (it->c);
2055 }
2056
2057 /* Get face and font to use. Encode IT->char_to_display. */
2058 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2059 face = FACE_FROM_ID (it->f, it->face_id);
2060 x_get_char_face_and_encoding (it->f, it->char_to_display,
2061 it->face_id, &char2b, it->multibyte_p);
2062 font = face->font;
2063
2064 /* When no suitable font found, use the default font. */
2065 font_not_found_p = font == NULL;
2066 if (font_not_found_p)
2067 {
2068 font = FRAME_FONT (it->f);
2069 boff = it->f->output_data.x->baseline_offset;
2070 font_info = NULL;
2071 }
2072 else
2073 {
2074 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2075 boff = font_info->baseline_offset;
2076 if (font_info->vertical_centering)
2077 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2078 }
2079
2080 /* There are no padding glyphs, so there is only one glyph to
2081 produce for the composition. Important is that pixel_width,
2082 ascent and descent are the values of what is drawn by
2083 draw_glyphs (i.e. the values of the overall glyphs composed). */
2084 it->nglyphs = 1;
2085
2086 /* If we have not yet calculated pixel size data of glyphs of
2087 the composition for the current face font, calculate them
2088 now. Theoretically, we have to check all fonts for the
2089 glyphs, but that requires much time and memory space. So,
2090 here we check only the font of the first glyph. This leads
2091 to incorrect display very rarely, and C-l (recenter) can
2092 correct the display anyway. */
2093 if (cmp->font != (void *) font)
2094 {
2095 /* Ascent and descent of the font of the first character of
2096 this composition (adjusted by baseline offset). Ascent
2097 and descent of overall glyphs should not be less than
2098 them respectively. */
2099 int font_ascent = font->ascent + boff;
2100 int font_descent = font->descent - boff;
2101 /* Bounding box of the overall glyphs. */
2102 int leftmost, rightmost, lowest, highest;
2103 int i, width, ascent, descent;
2104
2105 cmp->font = (void *) font;
2106
2107 /* Initialize the bounding box. */
2108 if (font_info
2109 && (pcm = x_per_char_metric (font, &char2b)))
2110 {
2111 width = pcm->width;
2112 ascent = pcm->ascent;
2113 descent = pcm->descent;
2114 }
2115 else
2116 {
2117 width = FONT_WIDTH (font);
2118 ascent = font->ascent;
2119 descent = font->descent;
2120 }
2121
2122 rightmost = width;
2123 lowest = - descent + boff;
2124 highest = ascent + boff;
2125 leftmost = 0;
2126
2127 if (font_info
2128 && font_info->default_ascent
2129 && CHAR_TABLE_P (Vuse_default_ascent)
2130 && !NILP (Faref (Vuse_default_ascent,
2131 make_number (it->char_to_display))))
2132 highest = font_info->default_ascent + boff;
2133
2134 /* Draw the first glyph at the normal position. It may be
2135 shifted to right later if some other glyphs are drawn at
2136 the left. */
2137 cmp->offsets[0] = 0;
2138 cmp->offsets[1] = boff;
2139
2140 /* Set cmp->offsets for the remaining glyphs. */
2141 for (i = 1; i < cmp->glyph_len; i++)
2142 {
2143 int left, right, btm, top;
2144 int ch = COMPOSITION_GLYPH (cmp, i);
2145 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2146
2147 face = FACE_FROM_ID (it->f, face_id);
2148 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2149 it->multibyte_p);
2150 font = face->font;
2151 if (font == NULL)
2152 {
2153 font = FRAME_FONT (it->f);
2154 boff = it->f->output_data.x->baseline_offset;
2155 font_info = NULL;
2156 }
2157 else
2158 {
2159 font_info
2160 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2161 boff = font_info->baseline_offset;
2162 if (font_info->vertical_centering)
2163 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2164 }
2165
2166 if (font_info
2167 && (pcm = x_per_char_metric (font, &char2b)))
2168 {
2169 width = pcm->width;
2170 ascent = pcm->ascent;
2171 descent = pcm->descent;
2172 }
2173 else
2174 {
2175 width = FONT_WIDTH (font);
2176 ascent = 1;
2177 descent = 0;
2178 }
2179
2180 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2181 {
2182 /* Relative composition with or without
2183 alternate chars. */
2184 left = (leftmost + rightmost - width) / 2;
2185 btm = - descent + boff;
2186 if (font_info && font_info->relative_compose
2187 && (! CHAR_TABLE_P (Vignore_relative_composition)
2188 || NILP (Faref (Vignore_relative_composition,
2189 make_number (ch)))))
2190 {
2191
2192 if (- descent >= font_info->relative_compose)
2193 /* One extra pixel between two glyphs. */
2194 btm = highest + 1;
2195 else if (ascent <= 0)
2196 /* One extra pixel between two glyphs. */
2197 btm = lowest - 1 - ascent - descent;
2198 }
2199 }
2200 else
2201 {
2202 /* A composition rule is specified by an integer
2203 value that encodes global and new reference
2204 points (GREF and NREF). GREF and NREF are
2205 specified by numbers as below:
2206
2207 0---1---2 -- ascent
2208 | |
2209 | |
2210 | |
2211 9--10--11 -- center
2212 | |
2213 ---3---4---5--- baseline
2214 | |
2215 6---7---8 -- descent
2216 */
2217 int rule = COMPOSITION_RULE (cmp, i);
2218 int gref, nref, grefx, grefy, nrefx, nrefy;
2219
2220 COMPOSITION_DECODE_RULE (rule, gref, nref);
2221 grefx = gref % 3, nrefx = nref % 3;
2222 grefy = gref / 3, nrefy = nref / 3;
2223
2224 left = (leftmost
2225 + grefx * (rightmost - leftmost) / 2
2226 - nrefx * width / 2);
2227 btm = ((grefy == 0 ? highest
2228 : grefy == 1 ? 0
2229 : grefy == 2 ? lowest
2230 : (highest + lowest) / 2)
2231 - (nrefy == 0 ? ascent + descent
2232 : nrefy == 1 ? descent - boff
2233 : nrefy == 2 ? 0
2234 : (ascent + descent) / 2));
2235 }
2236
2237 cmp->offsets[i * 2] = left;
2238 cmp->offsets[i * 2 + 1] = btm + descent;
2239
2240 /* Update the bounding box of the overall glyphs. */
2241 right = left + width;
2242 top = btm + descent + ascent;
2243 if (left < leftmost)
2244 leftmost = left;
2245 if (right > rightmost)
2246 rightmost = right;
2247 if (top > highest)
2248 highest = top;
2249 if (btm < lowest)
2250 lowest = btm;
2251 }
2252
2253 /* If there are glyphs whose x-offsets are negative,
2254 shift all glyphs to the right and make all x-offsets
2255 non-negative. */
2256 if (leftmost < 0)
2257 {
2258 for (i = 0; i < cmp->glyph_len; i++)
2259 cmp->offsets[i * 2] -= leftmost;
2260 rightmost -= leftmost;
2261 }
2262
2263 cmp->pixel_width = rightmost;
2264 cmp->ascent = highest;
2265 cmp->descent = - lowest;
2266 if (cmp->ascent < font_ascent)
2267 cmp->ascent = font_ascent;
2268 if (cmp->descent < font_descent)
2269 cmp->descent = font_descent;
2270 }
2271
2272 it->pixel_width = cmp->pixel_width;
2273 it->ascent = it->phys_ascent = cmp->ascent;
2274 it->descent = it->phys_descent = cmp->descent;
2275
2276 if (face->box != FACE_NO_BOX)
2277 {
2278 int thick = face->box_line_width;
2279
2280 if (thick > 0)
2281 {
2282 it->ascent += thick;
2283 it->descent += thick;
2284 }
2285 else
2286 thick = - thick;
2287
2288 if (it->start_of_box_run_p)
2289 it->pixel_width += thick;
2290 if (it->end_of_box_run_p)
2291 it->pixel_width += thick;
2292 }
2293
2294 /* If face has an overline, add the height of the overline
2295 (1 pixel) and a 1 pixel margin to the character height. */
2296 if (face->overline_p)
2297 it->ascent += 2;
2298
2299 take_vertical_position_into_account (it);
2300
2301 if (it->glyph_row)
2302 x_append_composite_glyph (it);
2303 }
2304 else if (it->what == IT_IMAGE)
2305 x_produce_image_glyph (it);
2306 else if (it->what == IT_STRETCH)
2307 x_produce_stretch_glyph (it);
2308
2309 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2310 because this isn't true for images with `:ascent 100'. */
2311 xassert (it->ascent >= 0 && it->descent >= 0);
2312 if (it->area == TEXT_AREA)
2313 it->current_x += it->pixel_width;
2314
2315 it->descent += it->extra_line_spacing;
2316
2317 it->max_ascent = max (it->max_ascent, it->ascent);
2318 it->max_descent = max (it->max_descent, it->descent);
2319 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2320 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2321 }
2322
2323
2324 /* Estimate the pixel height of the mode or top line on frame F.
2325 FACE_ID specifies what line's height to estimate. */
2326
2327 int
2328 x_estimate_mode_line_height (f, face_id)
2329 struct frame *f;
2330 enum face_id face_id;
2331 {
2332 int height = FONT_HEIGHT (FRAME_FONT (f));
2333
2334 /* This function is called so early when Emacs starts that the face
2335 cache and mode line face are not yet initialized. */
2336 if (FRAME_FACE_CACHE (f))
2337 {
2338 struct face *face = FACE_FROM_ID (f, face_id);
2339 if (face)
2340 {
2341 if (face->font)
2342 height = FONT_HEIGHT (face->font);
2343 if (face->box_line_width > 0)
2344 height += 2 * face->box_line_width;
2345 }
2346 }
2347
2348 return height;
2349 }
2350
2351 \f
2352 /***********************************************************************
2353 Glyph display
2354 ***********************************************************************/
2355
2356 /* A sequence of glyphs to be drawn in the same face.
2357
2358 This data structure is not really completely X specific, so it
2359 could possibly, at least partially, be useful for other systems. It
2360 is currently not part of the external redisplay interface because
2361 it's not clear what other systems will need. */
2362
2363 struct glyph_string
2364 {
2365 /* X-origin of the string. */
2366 int x;
2367
2368 /* Y-origin and y-position of the base line of this string. */
2369 int y, ybase;
2370
2371 /* The width of the string, not including a face extension. */
2372 int width;
2373
2374 /* The width of the string, including a face extension. */
2375 int background_width;
2376
2377 /* The height of this string. This is the height of the line this
2378 string is drawn in, and can be different from the height of the
2379 font the string is drawn in. */
2380 int height;
2381
2382 /* Number of pixels this string overwrites in front of its x-origin.
2383 This number is zero if the string has an lbearing >= 0; it is
2384 -lbearing, if the string has an lbearing < 0. */
2385 int left_overhang;
2386
2387 /* Number of pixels this string overwrites past its right-most
2388 nominal x-position, i.e. x + width. Zero if the string's
2389 rbearing is <= its nominal width, rbearing - width otherwise. */
2390 int right_overhang;
2391
2392 /* The frame on which the glyph string is drawn. */
2393 struct frame *f;
2394
2395 /* The window on which the glyph string is drawn. */
2396 struct window *w;
2397
2398 /* X display and window for convenience. */
2399 Display *display;
2400 Window window;
2401
2402 /* The glyph row for which this string was built. It determines the
2403 y-origin and height of the string. */
2404 struct glyph_row *row;
2405
2406 /* The area within row. */
2407 enum glyph_row_area area;
2408
2409 /* Characters to be drawn, and number of characters. */
2410 XChar2b *char2b;
2411 int nchars;
2412
2413 /* A face-override for drawing cursors, mouse face and similar. */
2414 enum draw_glyphs_face hl;
2415
2416 /* Face in which this string is to be drawn. */
2417 struct face *face;
2418
2419 /* Font in which this string is to be drawn. */
2420 XFontStruct *font;
2421
2422 /* Font info for this string. */
2423 struct font_info *font_info;
2424
2425 /* Non-null means this string describes (part of) a composition.
2426 All characters from char2b are drawn composed. */
2427 struct composition *cmp;
2428
2429 /* Index of this glyph string's first character in the glyph
2430 definition of CMP. If this is zero, this glyph string describes
2431 the first character of a composition. */
2432 int gidx;
2433
2434 /* 1 means this glyph strings face has to be drawn to the right end
2435 of the window's drawing area. */
2436 unsigned extends_to_end_of_line_p : 1;
2437
2438 /* 1 means the background of this string has been drawn. */
2439 unsigned background_filled_p : 1;
2440
2441 /* 1 means glyph string must be drawn with 16-bit functions. */
2442 unsigned two_byte_p : 1;
2443
2444 /* 1 means that the original font determined for drawing this glyph
2445 string could not be loaded. The member `font' has been set to
2446 the frame's default font in this case. */
2447 unsigned font_not_found_p : 1;
2448
2449 /* 1 means that the face in which this glyph string is drawn has a
2450 stipple pattern. */
2451 unsigned stippled_p : 1;
2452
2453 /* 1 means only the foreground of this glyph string must be drawn,
2454 and we should use the physical height of the line this glyph
2455 string appears in as clip rect. */
2456 unsigned for_overlaps_p : 1;
2457
2458 /* The GC to use for drawing this glyph string. */
2459 GC gc;
2460
2461 /* A pointer to the first glyph in the string. This glyph
2462 corresponds to char2b[0]. Needed to draw rectangles if
2463 font_not_found_p is 1. */
2464 struct glyph *first_glyph;
2465
2466 /* Image, if any. */
2467 struct image *img;
2468
2469 struct glyph_string *next, *prev;
2470 };
2471
2472
2473 #if GLYPH_DEBUG
2474
2475 static void
2476 x_dump_glyph_string (s)
2477 struct glyph_string *s;
2478 {
2479 fprintf (stderr, "glyph string\n");
2480 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2481 s->x, s->y, s->width, s->height);
2482 fprintf (stderr, " ybase = %d\n", s->ybase);
2483 fprintf (stderr, " hl = %d\n", s->hl);
2484 fprintf (stderr, " left overhang = %d, right = %d\n",
2485 s->left_overhang, s->right_overhang);
2486 fprintf (stderr, " nchars = %d\n", s->nchars);
2487 fprintf (stderr, " extends to end of line = %d\n",
2488 s->extends_to_end_of_line_p);
2489 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2490 fprintf (stderr, " bg width = %d\n", s->background_width);
2491 }
2492
2493 #endif /* GLYPH_DEBUG */
2494
2495
2496
2497 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2498 struct glyph_string **,
2499 struct glyph_string *,
2500 struct glyph_string *));
2501 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2502 struct glyph_string **,
2503 struct glyph_string *,
2504 struct glyph_string *));
2505 static void x_append_glyph_string P_ ((struct glyph_string **,
2506 struct glyph_string **,
2507 struct glyph_string *));
2508 static int x_left_overwritten P_ ((struct glyph_string *));
2509 static int x_left_overwriting P_ ((struct glyph_string *));
2510 static int x_right_overwritten P_ ((struct glyph_string *));
2511 static int x_right_overwriting P_ ((struct glyph_string *));
2512 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2513 int));
2514 static void x_init_glyph_string P_ ((struct glyph_string *,
2515 XChar2b *, struct window *,
2516 struct glyph_row *,
2517 enum glyph_row_area, int,
2518 enum draw_glyphs_face));
2519 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2520 enum glyph_row_area, int, int,
2521 enum draw_glyphs_face, int));
2522 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2523 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2524 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2525 int));
2526 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2527 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2528 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2529 static void x_draw_glyph_string P_ ((struct glyph_string *));
2530 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2531 static void x_set_cursor_gc P_ ((struct glyph_string *));
2532 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2533 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2534 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2535 int *, int *));
2536 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2537 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2538 unsigned long *, double, int));
2539 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2540 double, int, unsigned long));
2541 static void x_setup_relief_colors P_ ((struct glyph_string *));
2542 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2543 static void x_draw_image_relief P_ ((struct glyph_string *));
2544 static void x_draw_image_foreground P_ ((struct glyph_string *));
2545 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2546 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2547 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2548 int, int, int));
2549 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2550 int, int, int, int, XRectangle *));
2551 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2552 int, int, int, XRectangle *));
2553 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2554 enum glyph_row_area));
2555 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2556 struct glyph_row *,
2557 enum glyph_row_area, int, int));
2558
2559 #if GLYPH_DEBUG
2560 static void x_check_font P_ ((struct frame *, XFontStruct *));
2561 #endif
2562
2563
2564 /* Append the list of glyph strings with head H and tail T to the list
2565 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2566
2567 static INLINE void
2568 x_append_glyph_string_lists (head, tail, h, t)
2569 struct glyph_string **head, **tail;
2570 struct glyph_string *h, *t;
2571 {
2572 if (h)
2573 {
2574 if (*head)
2575 (*tail)->next = h;
2576 else
2577 *head = h;
2578 h->prev = *tail;
2579 *tail = t;
2580 }
2581 }
2582
2583
2584 /* Prepend the list of glyph strings with head H and tail T to the
2585 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2586 result. */
2587
2588 static INLINE void
2589 x_prepend_glyph_string_lists (head, tail, h, t)
2590 struct glyph_string **head, **tail;
2591 struct glyph_string *h, *t;
2592 {
2593 if (h)
2594 {
2595 if (*head)
2596 (*head)->prev = t;
2597 else
2598 *tail = t;
2599 t->next = *head;
2600 *head = h;
2601 }
2602 }
2603
2604
2605 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2606 Set *HEAD and *TAIL to the resulting list. */
2607
2608 static INLINE void
2609 x_append_glyph_string (head, tail, s)
2610 struct glyph_string **head, **tail;
2611 struct glyph_string *s;
2612 {
2613 s->next = s->prev = NULL;
2614 x_append_glyph_string_lists (head, tail, s, s);
2615 }
2616
2617
2618 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2619 face. */
2620
2621 static void
2622 x_set_cursor_gc (s)
2623 struct glyph_string *s;
2624 {
2625 if (s->font == FRAME_FONT (s->f)
2626 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2627 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2628 && !s->cmp)
2629 s->gc = s->f->output_data.x->cursor_gc;
2630 else
2631 {
2632 /* Cursor on non-default face: must merge. */
2633 XGCValues xgcv;
2634 unsigned long mask;
2635
2636 xgcv.background = s->f->output_data.x->cursor_pixel;
2637 xgcv.foreground = s->face->background;
2638
2639 /* If the glyph would be invisible, try a different foreground. */
2640 if (xgcv.foreground == xgcv.background)
2641 xgcv.foreground = s->face->foreground;
2642 if (xgcv.foreground == xgcv.background)
2643 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2644 if (xgcv.foreground == xgcv.background)
2645 xgcv.foreground = s->face->foreground;
2646
2647 /* Make sure the cursor is distinct from text in this face. */
2648 if (xgcv.background == s->face->background
2649 && xgcv.foreground == s->face->foreground)
2650 {
2651 xgcv.background = s->face->foreground;
2652 xgcv.foreground = s->face->background;
2653 }
2654
2655 IF_DEBUG (x_check_font (s->f, s->font));
2656 xgcv.font = s->font->fid;
2657 xgcv.graphics_exposures = False;
2658 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2659
2660 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2661 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2662 mask, &xgcv);
2663 else
2664 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2665 = XCreateGC (s->display, s->window, mask, &xgcv);
2666
2667 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2668 }
2669 }
2670
2671
2672 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2673
2674 static void
2675 x_set_mouse_face_gc (s)
2676 struct glyph_string *s;
2677 {
2678 int face_id;
2679 struct face *face;
2680
2681 /* What face has to be used last for the mouse face? */
2682 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2683 face = FACE_FROM_ID (s->f, face_id);
2684 if (face == NULL)
2685 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2686
2687 if (s->first_glyph->type == CHAR_GLYPH)
2688 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2689 else
2690 face_id = FACE_FOR_CHAR (s->f, face, 0);
2691 s->face = FACE_FROM_ID (s->f, face_id);
2692 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2693
2694 /* If font in this face is same as S->font, use it. */
2695 if (s->font == s->face->font)
2696 s->gc = s->face->gc;
2697 else
2698 {
2699 /* Otherwise construct scratch_cursor_gc with values from FACE
2700 but font FONT. */
2701 XGCValues xgcv;
2702 unsigned long mask;
2703
2704 xgcv.background = s->face->background;
2705 xgcv.foreground = s->face->foreground;
2706 IF_DEBUG (x_check_font (s->f, s->font));
2707 xgcv.font = s->font->fid;
2708 xgcv.graphics_exposures = False;
2709 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2710
2711 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2712 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2713 mask, &xgcv);
2714 else
2715 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2716 = XCreateGC (s->display, s->window, mask, &xgcv);
2717
2718 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2719 }
2720
2721 xassert (s->gc != 0);
2722 }
2723
2724
2725 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2726 Faces to use in the mode line have already been computed when the
2727 matrix was built, so there isn't much to do, here. */
2728
2729 static INLINE void
2730 x_set_mode_line_face_gc (s)
2731 struct glyph_string *s;
2732 {
2733 s->gc = s->face->gc;
2734 }
2735
2736
2737 /* Set S->gc of glyph string S for drawing that glyph string. Set
2738 S->stippled_p to a non-zero value if the face of S has a stipple
2739 pattern. */
2740
2741 static INLINE void
2742 x_set_glyph_string_gc (s)
2743 struct glyph_string *s;
2744 {
2745 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2746
2747 if (s->hl == DRAW_NORMAL_TEXT)
2748 {
2749 s->gc = s->face->gc;
2750 s->stippled_p = s->face->stipple != 0;
2751 }
2752 else if (s->hl == DRAW_INVERSE_VIDEO)
2753 {
2754 x_set_mode_line_face_gc (s);
2755 s->stippled_p = s->face->stipple != 0;
2756 }
2757 else if (s->hl == DRAW_CURSOR)
2758 {
2759 x_set_cursor_gc (s);
2760 s->stippled_p = 0;
2761 }
2762 else if (s->hl == DRAW_MOUSE_FACE)
2763 {
2764 x_set_mouse_face_gc (s);
2765 s->stippled_p = s->face->stipple != 0;
2766 }
2767 else if (s->hl == DRAW_IMAGE_RAISED
2768 || s->hl == DRAW_IMAGE_SUNKEN)
2769 {
2770 s->gc = s->face->gc;
2771 s->stippled_p = s->face->stipple != 0;
2772 }
2773 else
2774 {
2775 s->gc = s->face->gc;
2776 s->stippled_p = s->face->stipple != 0;
2777 }
2778
2779 /* GC must have been set. */
2780 xassert (s->gc != 0);
2781 }
2782
2783
2784 /* Return in *R the clipping rectangle for glyph string S. */
2785
2786 static void
2787 x_get_glyph_string_clip_rect (s, r)
2788 struct glyph_string *s;
2789 XRectangle *r;
2790 {
2791 if (s->row->full_width_p)
2792 {
2793 /* Draw full-width. X coordinates are relative to S->w->left. */
2794 int canon_x = CANON_X_UNIT (s->f);
2795
2796 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2797 r->width = XFASTINT (s->w->width) * canon_x;
2798
2799 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2800 {
2801 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2802 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2803 r->x -= width;
2804 }
2805
2806 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2807
2808 /* Unless displaying a mode or menu bar line, which are always
2809 fully visible, clip to the visible part of the row. */
2810 if (s->w->pseudo_window_p)
2811 r->height = s->row->visible_height;
2812 else
2813 r->height = s->height;
2814 }
2815 else
2816 {
2817 /* This is a text line that may be partially visible. */
2818 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2819 r->width = window_box_width (s->w, s->area);
2820 r->height = s->row->visible_height;
2821 }
2822
2823 /* If S draws overlapping rows, it's sufficient to use the top and
2824 bottom of the window for clipping because this glyph string
2825 intentionally draws over other lines. */
2826 if (s->for_overlaps_p)
2827 {
2828 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2829 r->height = window_text_bottom_y (s->w) - r->y;
2830 }
2831 else
2832 {
2833 /* Don't use S->y for clipping because it doesn't take partially
2834 visible lines into account. For example, it can be negative for
2835 partially visible lines at the top of a window. */
2836 if (!s->row->full_width_p
2837 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2838 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2839 else
2840 r->y = max (0, s->row->y);
2841
2842 /* If drawing a tool-bar window, draw it over the internal border
2843 at the top of the window. */
2844 if (s->w == XWINDOW (s->f->tool_bar_window))
2845 r->y -= s->f->output_data.x->internal_border_width;
2846 }
2847
2848 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2849 }
2850
2851
2852 /* Set clipping for output of glyph string S. S may be part of a mode
2853 line or menu if we don't have X toolkit support. */
2854
2855 static INLINE void
2856 x_set_glyph_string_clipping (s)
2857 struct glyph_string *s;
2858 {
2859 XRectangle r;
2860 x_get_glyph_string_clip_rect (s, &r);
2861 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2862 }
2863
2864
2865 /* Compute left and right overhang of glyph string S. If S is a glyph
2866 string for a composition, assume overhangs don't exist. */
2867
2868 static INLINE void
2869 x_compute_glyph_string_overhangs (s)
2870 struct glyph_string *s;
2871 {
2872 if (s->cmp == NULL
2873 && s->first_glyph->type == CHAR_GLYPH)
2874 {
2875 XCharStruct cs;
2876 int direction, font_ascent, font_descent;
2877 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2878 &font_ascent, &font_descent, &cs);
2879 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2880 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2881 }
2882 }
2883
2884
2885 /* Compute overhangs and x-positions for glyph string S and its
2886 predecessors, or successors. X is the starting x-position for S.
2887 BACKWARD_P non-zero means process predecessors. */
2888
2889 static void
2890 x_compute_overhangs_and_x (s, x, backward_p)
2891 struct glyph_string *s;
2892 int x;
2893 int backward_p;
2894 {
2895 if (backward_p)
2896 {
2897 while (s)
2898 {
2899 x_compute_glyph_string_overhangs (s);
2900 x -= s->width;
2901 s->x = x;
2902 s = s->prev;
2903 }
2904 }
2905 else
2906 {
2907 while (s)
2908 {
2909 x_compute_glyph_string_overhangs (s);
2910 s->x = x;
2911 x += s->width;
2912 s = s->next;
2913 }
2914 }
2915 }
2916
2917
2918 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2919 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2920 assumed to be zero. */
2921
2922 static void
2923 x_get_glyph_overhangs (glyph, f, left, right)
2924 struct glyph *glyph;
2925 struct frame *f;
2926 int *left, *right;
2927 {
2928 *left = *right = 0;
2929
2930 if (glyph->type == CHAR_GLYPH)
2931 {
2932 XFontStruct *font;
2933 struct face *face;
2934 struct font_info *font_info;
2935 XChar2b char2b;
2936 XCharStruct *pcm;
2937
2938 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2939 font = face->font;
2940 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2941 if (font
2942 && (pcm = x_per_char_metric (font, &char2b)))
2943 {
2944 if (pcm->rbearing > pcm->width)
2945 *right = pcm->rbearing - pcm->width;
2946 if (pcm->lbearing < 0)
2947 *left = -pcm->lbearing;
2948 }
2949 }
2950 }
2951
2952
2953 /* Return the index of the first glyph preceding glyph string S that
2954 is overwritten by S because of S's left overhang. Value is -1
2955 if no glyphs are overwritten. */
2956
2957 static int
2958 x_left_overwritten (s)
2959 struct glyph_string *s;
2960 {
2961 int k;
2962
2963 if (s->left_overhang)
2964 {
2965 int x = 0, i;
2966 struct glyph *glyphs = s->row->glyphs[s->area];
2967 int first = s->first_glyph - glyphs;
2968
2969 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2970 x -= glyphs[i].pixel_width;
2971
2972 k = i + 1;
2973 }
2974 else
2975 k = -1;
2976
2977 return k;
2978 }
2979
2980
2981 /* Return the index of the first glyph preceding glyph string S that
2982 is overwriting S because of its right overhang. Value is -1 if no
2983 glyph in front of S overwrites S. */
2984
2985 static int
2986 x_left_overwriting (s)
2987 struct glyph_string *s;
2988 {
2989 int i, k, x;
2990 struct glyph *glyphs = s->row->glyphs[s->area];
2991 int first = s->first_glyph - glyphs;
2992
2993 k = -1;
2994 x = 0;
2995 for (i = first - 1; i >= 0; --i)
2996 {
2997 int left, right;
2998 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2999 if (x + right > 0)
3000 k = i;
3001 x -= glyphs[i].pixel_width;
3002 }
3003
3004 return k;
3005 }
3006
3007
3008 /* Return the index of the last glyph following glyph string S that is
3009 not overwritten by S because of S's right overhang. Value is -1 if
3010 no such glyph is found. */
3011
3012 static int
3013 x_right_overwritten (s)
3014 struct glyph_string *s;
3015 {
3016 int k = -1;
3017
3018 if (s->right_overhang)
3019 {
3020 int x = 0, i;
3021 struct glyph *glyphs = s->row->glyphs[s->area];
3022 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3023 int end = s->row->used[s->area];
3024
3025 for (i = first; i < end && s->right_overhang > x; ++i)
3026 x += glyphs[i].pixel_width;
3027
3028 k = i;
3029 }
3030
3031 return k;
3032 }
3033
3034
3035 /* Return the index of the last glyph following glyph string S that
3036 overwrites S because of its left overhang. Value is negative
3037 if no such glyph is found. */
3038
3039 static int
3040 x_right_overwriting (s)
3041 struct glyph_string *s;
3042 {
3043 int i, k, x;
3044 int end = s->row->used[s->area];
3045 struct glyph *glyphs = s->row->glyphs[s->area];
3046 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3047
3048 k = -1;
3049 x = 0;
3050 for (i = first; i < end; ++i)
3051 {
3052 int left, right;
3053 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3054 if (x - left < 0)
3055 k = i;
3056 x += glyphs[i].pixel_width;
3057 }
3058
3059 return k;
3060 }
3061
3062
3063 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3064
3065 static INLINE void
3066 x_clear_glyph_string_rect (s, x, y, w, h)
3067 struct glyph_string *s;
3068 int x, y, w, h;
3069 {
3070 XGCValues xgcv;
3071 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3072 XSetForeground (s->display, s->gc, xgcv.background);
3073 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3074 XSetForeground (s->display, s->gc, xgcv.foreground);
3075 }
3076
3077
3078 /* Draw the background of glyph_string S. If S->background_filled_p
3079 is non-zero don't draw it. FORCE_P non-zero means draw the
3080 background even if it wouldn't be drawn normally. This is used
3081 when a string preceding S draws into the background of S, or S
3082 contains the first component of a composition. */
3083
3084 static void
3085 x_draw_glyph_string_background (s, force_p)
3086 struct glyph_string *s;
3087 int force_p;
3088 {
3089 /* Nothing to do if background has already been drawn or if it
3090 shouldn't be drawn in the first place. */
3091 if (!s->background_filled_p)
3092 {
3093 int box_line_width = max (s->face->box_line_width, 0);
3094
3095 if (s->stippled_p)
3096 {
3097 /* Fill background with a stipple pattern. */
3098 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3099 XFillRectangle (s->display, s->window, s->gc, s->x,
3100 s->y + box_line_width,
3101 s->background_width,
3102 s->height - 2 * box_line_width);
3103 XSetFillStyle (s->display, s->gc, FillSolid);
3104 s->background_filled_p = 1;
3105 }
3106 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3107 || s->font_not_found_p
3108 || s->extends_to_end_of_line_p
3109 || force_p)
3110 {
3111 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3112 s->background_width,
3113 s->height - 2 * box_line_width);
3114 s->background_filled_p = 1;
3115 }
3116 }
3117 }
3118
3119
3120 /* Draw the foreground of glyph string S. */
3121
3122 static void
3123 x_draw_glyph_string_foreground (s)
3124 struct glyph_string *s;
3125 {
3126 int i, x;
3127
3128 /* If first glyph of S has a left box line, start drawing the text
3129 of S to the right of that box line. */
3130 if (s->face->box != FACE_NO_BOX
3131 && s->first_glyph->left_box_line_p)
3132 x = s->x + abs (s->face->box_line_width);
3133 else
3134 x = s->x;
3135
3136 /* Draw characters of S as rectangles if S's font could not be
3137 loaded. */
3138 if (s->font_not_found_p)
3139 {
3140 for (i = 0; i < s->nchars; ++i)
3141 {
3142 struct glyph *g = s->first_glyph + i;
3143 XDrawRectangle (s->display, s->window,
3144 s->gc, x, s->y, g->pixel_width - 1,
3145 s->height - 1);
3146 x += g->pixel_width;
3147 }
3148 }
3149 else
3150 {
3151 char *char1b = (char *) s->char2b;
3152 int boff = s->font_info->baseline_offset;
3153
3154 if (s->font_info->vertical_centering)
3155 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3156
3157 /* If we can use 8-bit functions, condense S->char2b. */
3158 if (!s->two_byte_p)
3159 for (i = 0; i < s->nchars; ++i)
3160 char1b[i] = s->char2b[i].byte2;
3161
3162 /* Draw text with XDrawString if background has already been
3163 filled. Otherwise, use XDrawImageString. (Note that
3164 XDrawImageString is usually faster than XDrawString.) Always
3165 use XDrawImageString when drawing the cursor so that there is
3166 no chance that characters under a box cursor are invisible. */
3167 if (s->for_overlaps_p
3168 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3169 {
3170 /* Draw characters with 16-bit or 8-bit functions. */
3171 if (s->two_byte_p)
3172 XDrawString16 (s->display, s->window, s->gc, x,
3173 s->ybase - boff, s->char2b, s->nchars);
3174 else
3175 XDrawString (s->display, s->window, s->gc, x,
3176 s->ybase - boff, char1b, s->nchars);
3177 }
3178 else
3179 {
3180 if (s->two_byte_p)
3181 XDrawImageString16 (s->display, s->window, s->gc, x,
3182 s->ybase - boff, s->char2b, s->nchars);
3183 else
3184 XDrawImageString (s->display, s->window, s->gc, x,
3185 s->ybase - boff, char1b, s->nchars);
3186 }
3187 }
3188 }
3189
3190 /* Draw the foreground of composite glyph string S. */
3191
3192 static void
3193 x_draw_composite_glyph_string_foreground (s)
3194 struct glyph_string *s;
3195 {
3196 int i, x;
3197
3198 /* If first glyph of S has a left box line, start drawing the text
3199 of S to the right of that box line. */
3200 if (s->face->box != FACE_NO_BOX
3201 && s->first_glyph->left_box_line_p)
3202 x = s->x + abs (s->face->box_line_width);
3203 else
3204 x = s->x;
3205
3206 /* S is a glyph string for a composition. S->gidx is the index of
3207 the first character drawn for glyphs of this composition.
3208 S->gidx == 0 means we are drawing the very first character of
3209 this composition. */
3210
3211 /* Draw a rectangle for the composition if the font for the very
3212 first character of the composition could not be loaded. */
3213 if (s->font_not_found_p)
3214 {
3215 if (s->gidx == 0)
3216 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3217 s->width - 1, s->height - 1);
3218 }
3219 else
3220 {
3221 for (i = 0; i < s->nchars; i++, ++s->gidx)
3222 XDrawString16 (s->display, s->window, s->gc,
3223 x + s->cmp->offsets[s->gidx * 2],
3224 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3225 s->char2b + i, 1);
3226 }
3227 }
3228
3229
3230 #ifdef USE_X_TOOLKIT
3231
3232 static struct frame *x_frame_of_widget P_ ((Widget));
3233 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3234 XrmValue *, XrmValue *, XtPointer *));
3235 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3236 XrmValue *, Cardinal *));
3237
3238
3239 /* Return the frame on which widget WIDGET is used.. Abort if frame
3240 cannot be determined. */
3241
3242 static struct frame *
3243 x_frame_of_widget (widget)
3244 Widget widget;
3245 {
3246 struct x_display_info *dpyinfo;
3247 Lisp_Object tail;
3248 struct frame *f;
3249
3250 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3251
3252 /* Find the top-level shell of the widget. Note that this function
3253 can be called when the widget is not yet realized, so XtWindow
3254 (widget) == 0. That's the reason we can't simply use
3255 x_any_window_to_frame. */
3256 while (!XtIsTopLevelShell (widget))
3257 widget = XtParent (widget);
3258
3259 /* Look for a frame with that top-level widget. Allocate the color
3260 on that frame to get the right gamma correction value. */
3261 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3262 if (GC_FRAMEP (XCAR (tail))
3263 && (f = XFRAME (XCAR (tail)),
3264 (f->output_data.nothing != 1
3265 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3266 && f->output_data.x->widget == widget)
3267 return f;
3268
3269 abort ();
3270 }
3271
3272
3273 /* Allocate the color COLOR->pixel on the screen and display of
3274 widget WIDGET in colormap CMAP. If an exact match cannot be
3275 allocated, try the nearest color available. Value is non-zero
3276 if successful. This is called from lwlib. */
3277
3278 int
3279 x_alloc_nearest_color_for_widget (widget, cmap, color)
3280 Widget widget;
3281 Colormap cmap;
3282 XColor *color;
3283 {
3284 struct frame *f = x_frame_of_widget (widget);
3285 return x_alloc_nearest_color (f, cmap, color);
3286 }
3287
3288
3289 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3290 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3291 If this produces the same color as PIXEL, try a color where all RGB
3292 values have DELTA added. Return the allocated color in *PIXEL.
3293 DISPLAY is the X display, CMAP is the colormap to operate on.
3294 Value is non-zero if successful. */
3295
3296 int
3297 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3298 Widget widget;
3299 Display *display;
3300 Colormap cmap;
3301 unsigned long *pixel;
3302 double factor;
3303 int delta;
3304 {
3305 struct frame *f = x_frame_of_widget (widget);
3306 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3307 }
3308
3309
3310 /* Structure specifying which arguments should be passed by Xt to
3311 cvt_string_to_pixel. We want the widget's screen and colormap. */
3312
3313 static XtConvertArgRec cvt_string_to_pixel_args[] =
3314 {
3315 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3316 sizeof (Screen *)},
3317 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3318 sizeof (Colormap)}
3319 };
3320
3321
3322 /* The address of this variable is returned by
3323 cvt_string_to_pixel. */
3324
3325 static Pixel cvt_string_to_pixel_value;
3326
3327
3328 /* Convert a color name to a pixel color.
3329
3330 DPY is the display we are working on.
3331
3332 ARGS is an array of *NARGS XrmValue structures holding additional
3333 information about the widget for which the conversion takes place.
3334 The contents of this array are determined by the specification
3335 in cvt_string_to_pixel_args.
3336
3337 FROM is a pointer to an XrmValue which points to the color name to
3338 convert. TO is an XrmValue in which to return the pixel color.
3339
3340 CLOSURE_RET is a pointer to user-data, in which we record if
3341 we allocated the color or not.
3342
3343 Value is True if successful, False otherwise. */
3344
3345 static Boolean
3346 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3347 Display *dpy;
3348 XrmValue *args;
3349 Cardinal *nargs;
3350 XrmValue *from, *to;
3351 XtPointer *closure_ret;
3352 {
3353 Screen *screen;
3354 Colormap cmap;
3355 Pixel pixel;
3356 String color_name;
3357 XColor color;
3358
3359 if (*nargs != 2)
3360 {
3361 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3362 "wrongParameters", "cvt_string_to_pixel",
3363 "XtToolkitError",
3364 "Screen and colormap args required", NULL, NULL);
3365 return False;
3366 }
3367
3368 screen = *(Screen **) args[0].addr;
3369 cmap = *(Colormap *) args[1].addr;
3370 color_name = (String) from->addr;
3371
3372 if (strcmp (color_name, XtDefaultBackground) == 0)
3373 {
3374 *closure_ret = (XtPointer) False;
3375 pixel = WhitePixelOfScreen (screen);
3376 }
3377 else if (strcmp (color_name, XtDefaultForeground) == 0)
3378 {
3379 *closure_ret = (XtPointer) False;
3380 pixel = BlackPixelOfScreen (screen);
3381 }
3382 else if (XParseColor (dpy, cmap, color_name, &color)
3383 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3384 {
3385 pixel = color.pixel;
3386 *closure_ret = (XtPointer) True;
3387 }
3388 else
3389 {
3390 String params[1];
3391 Cardinal nparams = 1;
3392
3393 params[0] = color_name;
3394 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3395 "badValue", "cvt_string_to_pixel",
3396 "XtToolkitError", "Invalid color `%s'",
3397 params, &nparams);
3398 return False;
3399 }
3400
3401 if (to->addr != NULL)
3402 {
3403 if (to->size < sizeof (Pixel))
3404 {
3405 to->size = sizeof (Pixel);
3406 return False;
3407 }
3408
3409 *(Pixel *) to->addr = pixel;
3410 }
3411 else
3412 {
3413 cvt_string_to_pixel_value = pixel;
3414 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3415 }
3416
3417 to->size = sizeof (Pixel);
3418 return True;
3419 }
3420
3421
3422 /* Free a pixel color which was previously allocated via
3423 cvt_string_to_pixel. This is registered as the destructor
3424 for this type of resource via XtSetTypeConverter.
3425
3426 APP is the application context in which we work.
3427
3428 TO is a pointer to an XrmValue holding the color to free.
3429 CLOSURE is the value we stored in CLOSURE_RET for this color
3430 in cvt_string_to_pixel.
3431
3432 ARGS and NARGS are like for cvt_string_to_pixel. */
3433
3434 static void
3435 cvt_pixel_dtor (app, to, closure, args, nargs)
3436 XtAppContext app;
3437 XrmValuePtr to;
3438 XtPointer closure;
3439 XrmValuePtr args;
3440 Cardinal *nargs;
3441 {
3442 if (*nargs != 2)
3443 {
3444 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3445 "XtToolkitError",
3446 "Screen and colormap arguments required",
3447 NULL, NULL);
3448 }
3449 else if (closure != NULL)
3450 {
3451 /* We did allocate the pixel, so free it. */
3452 Screen *screen = *(Screen **) args[0].addr;
3453 Colormap cmap = *(Colormap *) args[1].addr;
3454 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3455 (Pixel *) to->addr, 1);
3456 }
3457 }
3458
3459
3460 #endif /* USE_X_TOOLKIT */
3461
3462
3463 /* Value is an array of XColor structures for the contents of the
3464 color map of display DPY. Set *NCELLS to the size of the array.
3465 Note that this probably shouldn't be called for large color maps,
3466 say a 24-bit TrueColor map. */
3467
3468 static const XColor *
3469 x_color_cells (dpy, ncells)
3470 Display *dpy;
3471 int *ncells;
3472 {
3473 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3474
3475 if (dpyinfo->color_cells == NULL)
3476 {
3477 Screen *screen = dpyinfo->screen;
3478 int i;
3479
3480 dpyinfo->ncolor_cells
3481 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3482 dpyinfo->color_cells
3483 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3484 * sizeof *dpyinfo->color_cells);
3485
3486 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3487 dpyinfo->color_cells[i].pixel = i;
3488
3489 XQueryColors (dpy, dpyinfo->cmap,
3490 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3491 }
3492
3493 *ncells = dpyinfo->ncolor_cells;
3494 return dpyinfo->color_cells;
3495 }
3496
3497
3498 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3499 colors in COLORS. Use cached information, if available. */
3500
3501 void
3502 x_query_colors (f, colors, ncolors)
3503 struct frame *f;
3504 XColor *colors;
3505 int ncolors;
3506 {
3507 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3508
3509 if (dpyinfo->color_cells)
3510 {
3511 int i;
3512 for (i = 0; i < ncolors; ++i)
3513 {
3514 unsigned long pixel = colors[i].pixel;
3515 xassert (pixel < dpyinfo->ncolor_cells);
3516 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3517 colors[i] = dpyinfo->color_cells[pixel];
3518 }
3519 }
3520 else
3521 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3522 }
3523
3524
3525 /* On frame F, translate pixel color to RGB values for the color in
3526 COLOR. Use cached information, if available. */
3527
3528 void
3529 x_query_color (f, color)
3530 struct frame *f;
3531 XColor *color;
3532 {
3533 x_query_colors (f, color, 1);
3534 }
3535
3536
3537 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3538 exact match can't be allocated, try the nearest color available.
3539 Value is non-zero if successful. Set *COLOR to the color
3540 allocated. */
3541
3542 static int
3543 x_alloc_nearest_color_1 (dpy, cmap, color)
3544 Display *dpy;
3545 Colormap cmap;
3546 XColor *color;
3547 {
3548 int rc;
3549
3550 rc = XAllocColor (dpy, cmap, color);
3551 if (rc == 0)
3552 {
3553 /* If we got to this point, the colormap is full, so we're going
3554 to try to get the next closest color. The algorithm used is
3555 a least-squares matching, which is what X uses for closest
3556 color matching with StaticColor visuals. */
3557 int nearest, i;
3558 unsigned long nearest_delta = ~0;
3559 int ncells;
3560 const XColor *cells = x_color_cells (dpy, &ncells);
3561
3562 for (nearest = i = 0; i < ncells; ++i)
3563 {
3564 long dred = (color->red >> 8) - (cells[i].red >> 8);
3565 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3566 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3567 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3568
3569 if (delta < nearest_delta)
3570 {
3571 nearest = i;
3572 nearest_delta = delta;
3573 }
3574 }
3575
3576 color->red = cells[nearest].red;
3577 color->green = cells[nearest].green;
3578 color->blue = cells[nearest].blue;
3579 rc = XAllocColor (dpy, cmap, color);
3580 }
3581 else
3582 {
3583 /* If allocation succeeded, and the allocated pixel color is not
3584 equal to a cached pixel color recorded earlier, there was a
3585 change in the colormap, so clear the color cache. */
3586 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3587 XColor *cached_color;
3588
3589 if (dpyinfo->color_cells
3590 && (cached_color = &dpyinfo->color_cells[color->pixel],
3591 (cached_color->red != color->red
3592 || cached_color->blue != color->blue
3593 || cached_color->green != color->green)))
3594 {
3595 xfree (dpyinfo->color_cells);
3596 dpyinfo->color_cells = NULL;
3597 dpyinfo->ncolor_cells = 0;
3598 }
3599 }
3600
3601 #ifdef DEBUG_X_COLORS
3602 if (rc)
3603 register_color (color->pixel);
3604 #endif /* DEBUG_X_COLORS */
3605
3606 return rc;
3607 }
3608
3609
3610 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3611 exact match can't be allocated, try the nearest color available.
3612 Value is non-zero if successful. Set *COLOR to the color
3613 allocated. */
3614
3615 int
3616 x_alloc_nearest_color (f, cmap, color)
3617 struct frame *f;
3618 Colormap cmap;
3619 XColor *color;
3620 {
3621 gamma_correct (f, color);
3622 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3623 }
3624
3625
3626 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3627 It's necessary to do this instead of just using PIXEL directly to
3628 get color reference counts right. */
3629
3630 unsigned long
3631 x_copy_color (f, pixel)
3632 struct frame *f;
3633 unsigned long pixel;
3634 {
3635 XColor color;
3636
3637 color.pixel = pixel;
3638 BLOCK_INPUT;
3639 x_query_color (f, &color);
3640 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3641 UNBLOCK_INPUT;
3642 #ifdef DEBUG_X_COLORS
3643 register_color (pixel);
3644 #endif
3645 return color.pixel;
3646 }
3647
3648
3649 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3650 It's necessary to do this instead of just using PIXEL directly to
3651 get color reference counts right. */
3652
3653 unsigned long
3654 x_copy_dpy_color (dpy, cmap, pixel)
3655 Display *dpy;
3656 Colormap cmap;
3657 unsigned long pixel;
3658 {
3659 XColor color;
3660
3661 color.pixel = pixel;
3662 BLOCK_INPUT;
3663 XQueryColor (dpy, cmap, &color);
3664 XAllocColor (dpy, cmap, &color);
3665 UNBLOCK_INPUT;
3666 #ifdef DEBUG_X_COLORS
3667 register_color (pixel);
3668 #endif
3669 return color.pixel;
3670 }
3671
3672
3673 /* Brightness beyond which a color won't have its highlight brightness
3674 boosted.
3675
3676 Nominally, highlight colors for `3d' faces are calculated by
3677 brightening an object's color by a constant scale factor, but this
3678 doesn't yield good results for dark colors, so for colors who's
3679 brightness is less than this value (on a scale of 0-65535) have an
3680 use an additional additive factor.
3681
3682 The value here is set so that the default menu-bar/mode-line color
3683 (grey75) will not have its highlights changed at all. */
3684 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3685
3686
3687 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3688 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3689 If this produces the same color as PIXEL, try a color where all RGB
3690 values have DELTA added. Return the allocated color in *PIXEL.
3691 DISPLAY is the X display, CMAP is the colormap to operate on.
3692 Value is non-zero if successful. */
3693
3694 static int
3695 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3696 struct frame *f;
3697 Display *display;
3698 Colormap cmap;
3699 unsigned long *pixel;
3700 double factor;
3701 int delta;
3702 {
3703 XColor color, new;
3704 long bright;
3705 int success_p;
3706
3707 /* Get RGB color values. */
3708 color.pixel = *pixel;
3709 x_query_color (f, &color);
3710
3711 /* Change RGB values by specified FACTOR. Avoid overflow! */
3712 xassert (factor >= 0);
3713 new.red = min (0xffff, factor * color.red);
3714 new.green = min (0xffff, factor * color.green);
3715 new.blue = min (0xffff, factor * color.blue);
3716
3717 /* Calculate brightness of COLOR. */
3718 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3719
3720 /* We only boost colors that are darker than
3721 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3722 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3723 /* Make an additive adjustment to NEW, because it's dark enough so
3724 that scaling by FACTOR alone isn't enough. */
3725 {
3726 /* How far below the limit this color is (0 - 1, 1 being darker). */
3727 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3728 /* The additive adjustment. */
3729 int min_delta = delta * dimness * factor / 2;
3730
3731 if (factor < 1)
3732 {
3733 new.red = max (0, new.red - min_delta);
3734 new.green = max (0, new.green - min_delta);
3735 new.blue = max (0, new.blue - min_delta);
3736 }
3737 else
3738 {
3739 new.red = min (0xffff, min_delta + new.red);
3740 new.green = min (0xffff, min_delta + new.green);
3741 new.blue = min (0xffff, min_delta + new.blue);
3742 }
3743 }
3744
3745 /* Try to allocate the color. */
3746 success_p = x_alloc_nearest_color (f, cmap, &new);
3747 if (success_p)
3748 {
3749 if (new.pixel == *pixel)
3750 {
3751 /* If we end up with the same color as before, try adding
3752 delta to the RGB values. */
3753 x_free_colors (f, &new.pixel, 1);
3754
3755 new.red = min (0xffff, delta + color.red);
3756 new.green = min (0xffff, delta + color.green);
3757 new.blue = min (0xffff, delta + color.blue);
3758 success_p = x_alloc_nearest_color (f, cmap, &new);
3759 }
3760 else
3761 success_p = 1;
3762 *pixel = new.pixel;
3763 }
3764
3765 return success_p;
3766 }
3767
3768
3769 /* Set up the foreground color for drawing relief lines of glyph
3770 string S. RELIEF is a pointer to a struct relief containing the GC
3771 with which lines will be drawn. Use a color that is FACTOR or
3772 DELTA lighter or darker than the relief's background which is found
3773 in S->f->output_data.x->relief_background. If such a color cannot
3774 be allocated, use DEFAULT_PIXEL, instead. */
3775
3776 static void
3777 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3778 struct frame *f;
3779 struct relief *relief;
3780 double factor;
3781 int delta;
3782 unsigned long default_pixel;
3783 {
3784 XGCValues xgcv;
3785 struct x_output *di = f->output_data.x;
3786 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3787 unsigned long pixel;
3788 unsigned long background = di->relief_background;
3789 Colormap cmap = FRAME_X_COLORMAP (f);
3790 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3791 Display *dpy = FRAME_X_DISPLAY (f);
3792
3793 xgcv.graphics_exposures = False;
3794 xgcv.line_width = 1;
3795
3796 /* Free previously allocated color. The color cell will be reused
3797 when it has been freed as many times as it was allocated, so this
3798 doesn't affect faces using the same colors. */
3799 if (relief->gc
3800 && relief->allocated_p)
3801 {
3802 x_free_colors (f, &relief->pixel, 1);
3803 relief->allocated_p = 0;
3804 }
3805
3806 /* Allocate new color. */
3807 xgcv.foreground = default_pixel;
3808 pixel = background;
3809 if (dpyinfo->n_planes != 1
3810 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3811 {
3812 relief->allocated_p = 1;
3813 xgcv.foreground = relief->pixel = pixel;
3814 }
3815
3816 if (relief->gc == 0)
3817 {
3818 xgcv.stipple = dpyinfo->gray;
3819 mask |= GCStipple;
3820 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3821 }
3822 else
3823 XChangeGC (dpy, relief->gc, mask, &xgcv);
3824 }
3825
3826
3827 /* Set up colors for the relief lines around glyph string S. */
3828
3829 static void
3830 x_setup_relief_colors (s)
3831 struct glyph_string *s;
3832 {
3833 struct x_output *di = s->f->output_data.x;
3834 unsigned long color;
3835
3836 if (s->face->use_box_color_for_shadows_p)
3837 color = s->face->box_color;
3838 else if (s->first_glyph->type == IMAGE_GLYPH
3839 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3840 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3841 else
3842 {
3843 XGCValues xgcv;
3844
3845 /* Get the background color of the face. */
3846 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3847 color = xgcv.background;
3848 }
3849
3850 if (di->white_relief.gc == 0
3851 || color != di->relief_background)
3852 {
3853 di->relief_background = color;
3854 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3855 WHITE_PIX_DEFAULT (s->f));
3856 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3857 BLACK_PIX_DEFAULT (s->f));
3858 }
3859 }
3860
3861
3862 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3863 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3864 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3865 relief. LEFT_P non-zero means draw a relief on the left side of
3866 the rectangle. RIGHT_P non-zero means draw a relief on the right
3867 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3868 when drawing. */
3869
3870 static void
3871 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3872 raised_p, left_p, right_p, clip_rect)
3873 struct frame *f;
3874 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3875 XRectangle *clip_rect;
3876 {
3877 Display *dpy = FRAME_X_DISPLAY (f);
3878 Window window = FRAME_X_WINDOW (f);
3879 int i;
3880 GC gc;
3881
3882 if (raised_p)
3883 gc = f->output_data.x->white_relief.gc;
3884 else
3885 gc = f->output_data.x->black_relief.gc;
3886 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3887
3888 /* Top. */
3889 for (i = 0; i < width; ++i)
3890 XDrawLine (dpy, window, gc,
3891 left_x + i * left_p, top_y + i,
3892 right_x + 1 - i * right_p, top_y + i);
3893
3894 /* Left. */
3895 if (left_p)
3896 for (i = 0; i < width; ++i)
3897 XDrawLine (dpy, window, gc,
3898 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3899
3900 XSetClipMask (dpy, gc, None);
3901 if (raised_p)
3902 gc = f->output_data.x->black_relief.gc;
3903 else
3904 gc = f->output_data.x->white_relief.gc;
3905 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3906
3907 /* Bottom. */
3908 for (i = 0; i < width; ++i)
3909 XDrawLine (dpy, window, gc,
3910 left_x + i * left_p, bottom_y - i,
3911 right_x + 1 - i * right_p, bottom_y - i);
3912
3913 /* Right. */
3914 if (right_p)
3915 for (i = 0; i < width; ++i)
3916 XDrawLine (dpy, window, gc,
3917 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3918
3919 XSetClipMask (dpy, gc, None);
3920 }
3921
3922
3923 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3924 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3925 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3926 left side of the rectangle. RIGHT_P non-zero means draw a line
3927 on the right side of the rectangle. CLIP_RECT is the clipping
3928 rectangle to use when drawing. */
3929
3930 static void
3931 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3932 left_p, right_p, clip_rect)
3933 struct glyph_string *s;
3934 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3935 XRectangle *clip_rect;
3936 {
3937 XGCValues xgcv;
3938
3939 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3940 XSetForeground (s->display, s->gc, s->face->box_color);
3941 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3942
3943 /* Top. */
3944 XFillRectangle (s->display, s->window, s->gc,
3945 left_x, top_y, right_x - left_x + 1, width);
3946
3947 /* Left. */
3948 if (left_p)
3949 XFillRectangle (s->display, s->window, s->gc,
3950 left_x, top_y, width, bottom_y - top_y + 1);
3951
3952 /* Bottom. */
3953 XFillRectangle (s->display, s->window, s->gc,
3954 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3955
3956 /* Right. */
3957 if (right_p)
3958 XFillRectangle (s->display, s->window, s->gc,
3959 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3960
3961 XSetForeground (s->display, s->gc, xgcv.foreground);
3962 XSetClipMask (s->display, s->gc, None);
3963 }
3964
3965
3966 /* Draw a box around glyph string S. */
3967
3968 static void
3969 x_draw_glyph_string_box (s)
3970 struct glyph_string *s;
3971 {
3972 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3973 int left_p, right_p;
3974 struct glyph *last_glyph;
3975 XRectangle clip_rect;
3976
3977 last_x = window_box_right (s->w, s->area);
3978 if (s->row->full_width_p
3979 && !s->w->pseudo_window_p)
3980 {
3981 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
3982 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3983 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3984 }
3985
3986 /* The glyph that may have a right box line. */
3987 last_glyph = (s->cmp || s->img
3988 ? s->first_glyph
3989 : s->first_glyph + s->nchars - 1);
3990
3991 width = abs (s->face->box_line_width);
3992 raised_p = s->face->box == FACE_RAISED_BOX;
3993 left_x = s->x;
3994 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3995 ? last_x - 1
3996 : min (last_x, s->x + s->background_width) - 1);
3997 top_y = s->y;
3998 bottom_y = top_y + s->height - 1;
3999
4000 left_p = (s->first_glyph->left_box_line_p
4001 || (s->hl == DRAW_MOUSE_FACE
4002 && (s->prev == NULL
4003 || s->prev->hl != s->hl)));
4004 right_p = (last_glyph->right_box_line_p
4005 || (s->hl == DRAW_MOUSE_FACE
4006 && (s->next == NULL
4007 || s->next->hl != s->hl)));
4008
4009 x_get_glyph_string_clip_rect (s, &clip_rect);
4010
4011 if (s->face->box == FACE_SIMPLE_BOX)
4012 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4013 left_p, right_p, &clip_rect);
4014 else
4015 {
4016 x_setup_relief_colors (s);
4017 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4018 width, raised_p, left_p, right_p, &clip_rect);
4019 }
4020 }
4021
4022
4023 /* Draw foreground of image glyph string S. */
4024
4025 static void
4026 x_draw_image_foreground (s)
4027 struct glyph_string *s;
4028 {
4029 int x;
4030 int y = s->ybase - image_ascent (s->img, s->face);
4031
4032 /* If first glyph of S has a left box line, start drawing it to the
4033 right of that line. */
4034 if (s->face->box != FACE_NO_BOX
4035 && s->first_glyph->left_box_line_p)
4036 x = s->x + abs (s->face->box_line_width);
4037 else
4038 x = s->x;
4039
4040 /* If there is a margin around the image, adjust x- and y-position
4041 by that margin. */
4042 x += s->img->hmargin;
4043 y += s->img->vmargin;
4044
4045 if (s->img->pixmap)
4046 {
4047 if (s->img->mask)
4048 {
4049 /* We can't set both a clip mask and use XSetClipRectangles
4050 because the latter also sets a clip mask. We also can't
4051 trust on the shape extension to be available
4052 (XShapeCombineRegion). So, compute the rectangle to draw
4053 manually. */
4054 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4055 | GCFunction);
4056 XGCValues xgcv;
4057 XRectangle clip_rect, image_rect, r;
4058
4059 xgcv.clip_mask = s->img->mask;
4060 xgcv.clip_x_origin = x;
4061 xgcv.clip_y_origin = y;
4062 xgcv.function = GXcopy;
4063 XChangeGC (s->display, s->gc, mask, &xgcv);
4064
4065 x_get_glyph_string_clip_rect (s, &clip_rect);
4066 image_rect.x = x;
4067 image_rect.y = y;
4068 image_rect.width = s->img->width;
4069 image_rect.height = s->img->height;
4070 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4071 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4072 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4073 }
4074 else
4075 {
4076 XRectangle clip_rect, image_rect, r;
4077
4078 x_get_glyph_string_clip_rect (s, &clip_rect);
4079 image_rect.x = x;
4080 image_rect.y = y;
4081 image_rect.width = s->img->width;
4082 image_rect.height = s->img->height;
4083 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4084 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4085 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4086
4087 /* When the image has a mask, we can expect that at
4088 least part of a mouse highlight or a block cursor will
4089 be visible. If the image doesn't have a mask, make
4090 a block cursor visible by drawing a rectangle around
4091 the image. I believe it's looking better if we do
4092 nothing here for mouse-face. */
4093 if (s->hl == DRAW_CURSOR)
4094 XDrawRectangle (s->display, s->window, s->gc, x, y,
4095 s->img->width - 1, s->img->height - 1);
4096 }
4097 }
4098 else
4099 /* Draw a rectangle if image could not be loaded. */
4100 XDrawRectangle (s->display, s->window, s->gc, x, y,
4101 s->img->width - 1, s->img->height - 1);
4102 }
4103
4104
4105 /* Draw a relief around the image glyph string S. */
4106
4107 static void
4108 x_draw_image_relief (s)
4109 struct glyph_string *s;
4110 {
4111 int x0, y0, x1, y1, thick, raised_p;
4112 XRectangle r;
4113 int x;
4114 int y = s->ybase - image_ascent (s->img, s->face);
4115
4116 /* If first glyph of S has a left box line, start drawing it to the
4117 right of that line. */
4118 if (s->face->box != FACE_NO_BOX
4119 && s->first_glyph->left_box_line_p)
4120 x = s->x + abs (s->face->box_line_width);
4121 else
4122 x = s->x;
4123
4124 /* If there is a margin around the image, adjust x- and y-position
4125 by that margin. */
4126 x += s->img->hmargin;
4127 y += s->img->vmargin;
4128
4129 if (s->hl == DRAW_IMAGE_SUNKEN
4130 || s->hl == DRAW_IMAGE_RAISED)
4131 {
4132 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : 3;
4133 raised_p = s->hl == DRAW_IMAGE_RAISED;
4134 }
4135 else
4136 {
4137 thick = abs (s->img->relief);
4138 raised_p = s->img->relief > 0;
4139 }
4140
4141 x0 = x - thick;
4142 y0 = y - thick;
4143 x1 = x + s->img->width + thick - 1;
4144 y1 = y + s->img->height + thick - 1;
4145
4146 x_setup_relief_colors (s);
4147 x_get_glyph_string_clip_rect (s, &r);
4148 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4149 }
4150
4151
4152 /* Draw the foreground of image glyph string S to PIXMAP. */
4153
4154 static void
4155 x_draw_image_foreground_1 (s, pixmap)
4156 struct glyph_string *s;
4157 Pixmap pixmap;
4158 {
4159 int x;
4160 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4161
4162 /* If first glyph of S has a left box line, start drawing it to the
4163 right of that line. */
4164 if (s->face->box != FACE_NO_BOX
4165 && s->first_glyph->left_box_line_p)
4166 x = abs (s->face->box_line_width);
4167 else
4168 x = 0;
4169
4170 /* If there is a margin around the image, adjust x- and y-position
4171 by that margin. */
4172 x += s->img->hmargin;
4173 y += s->img->vmargin;
4174
4175 if (s->img->pixmap)
4176 {
4177 if (s->img->mask)
4178 {
4179 /* We can't set both a clip mask and use XSetClipRectangles
4180 because the latter also sets a clip mask. We also can't
4181 trust on the shape extension to be available
4182 (XShapeCombineRegion). So, compute the rectangle to draw
4183 manually. */
4184 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4185 | GCFunction);
4186 XGCValues xgcv;
4187
4188 xgcv.clip_mask = s->img->mask;
4189 xgcv.clip_x_origin = x;
4190 xgcv.clip_y_origin = y;
4191 xgcv.function = GXcopy;
4192 XChangeGC (s->display, s->gc, mask, &xgcv);
4193
4194 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4195 0, 0, s->img->width, s->img->height, x, y);
4196 XSetClipMask (s->display, s->gc, None);
4197 }
4198 else
4199 {
4200 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4201 0, 0, s->img->width, s->img->height, x, y);
4202
4203 /* When the image has a mask, we can expect that at
4204 least part of a mouse highlight or a block cursor will
4205 be visible. If the image doesn't have a mask, make
4206 a block cursor visible by drawing a rectangle around
4207 the image. I believe it's looking better if we do
4208 nothing here for mouse-face. */
4209 if (s->hl == DRAW_CURSOR)
4210 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4211 s->img->width - 1, s->img->height - 1);
4212 }
4213 }
4214 else
4215 /* Draw a rectangle if image could not be loaded. */
4216 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4217 s->img->width - 1, s->img->height - 1);
4218 }
4219
4220
4221 /* Draw part of the background of glyph string S. X, Y, W, and H
4222 give the rectangle to draw. */
4223
4224 static void
4225 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4226 struct glyph_string *s;
4227 int x, y, w, h;
4228 {
4229 if (s->stippled_p)
4230 {
4231 /* Fill background with a stipple pattern. */
4232 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4233 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4234 XSetFillStyle (s->display, s->gc, FillSolid);
4235 }
4236 else
4237 x_clear_glyph_string_rect (s, x, y, w, h);
4238 }
4239
4240
4241 /* Draw image glyph string S.
4242
4243 s->y
4244 s->x +-------------------------
4245 | s->face->box
4246 |
4247 | +-------------------------
4248 | | s->img->margin
4249 | |
4250 | | +-------------------
4251 | | | the image
4252
4253 */
4254
4255 static void
4256 x_draw_image_glyph_string (s)
4257 struct glyph_string *s;
4258 {
4259 int x, y;
4260 int box_line_hwidth = abs (s->face->box_line_width);
4261 int box_line_vwidth = max (s->face->box_line_width, 0);
4262 int height;
4263 Pixmap pixmap = None;
4264
4265 height = s->height - 2 * box_line_vwidth;
4266
4267 /* Fill background with face under the image. Do it only if row is
4268 taller than image or if image has a clip mask to reduce
4269 flickering. */
4270 s->stippled_p = s->face->stipple != 0;
4271 if (height > s->img->height
4272 || s->img->hmargin
4273 || s->img->vmargin
4274 || s->img->mask
4275 || s->img->pixmap == 0
4276 || s->width != s->background_width)
4277 {
4278 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4279 x = s->x + box_line_hwidth;
4280 else
4281 x = s->x;
4282
4283 y = s->y + box_line_vwidth;
4284
4285 if (s->img->mask)
4286 {
4287 /* Create a pixmap as large as the glyph string. Fill it
4288 with the background color. Copy the image to it, using
4289 its mask. Copy the temporary pixmap to the display. */
4290 Screen *screen = FRAME_X_SCREEN (s->f);
4291 int depth = DefaultDepthOfScreen (screen);
4292
4293 /* Create a pixmap as large as the glyph string. */
4294 pixmap = XCreatePixmap (s->display, s->window,
4295 s->background_width,
4296 s->height, depth);
4297
4298 /* Don't clip in the following because we're working on the
4299 pixmap. */
4300 XSetClipMask (s->display, s->gc, None);
4301
4302 /* Fill the pixmap with the background color/stipple. */
4303 if (s->stippled_p)
4304 {
4305 /* Fill background with a stipple pattern. */
4306 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4307 XFillRectangle (s->display, pixmap, s->gc,
4308 0, 0, s->background_width, s->height);
4309 XSetFillStyle (s->display, s->gc, FillSolid);
4310 }
4311 else
4312 {
4313 XGCValues xgcv;
4314 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4315 &xgcv);
4316 XSetForeground (s->display, s->gc, xgcv.background);
4317 XFillRectangle (s->display, pixmap, s->gc,
4318 0, 0, s->background_width, s->height);
4319 XSetForeground (s->display, s->gc, xgcv.foreground);
4320 }
4321 }
4322 else
4323 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4324
4325 s->background_filled_p = 1;
4326 }
4327
4328 /* Draw the foreground. */
4329 if (pixmap != None)
4330 {
4331 x_draw_image_foreground_1 (s, pixmap);
4332 x_set_glyph_string_clipping (s);
4333 XCopyArea (s->display, pixmap, s->window, s->gc,
4334 0, 0, s->background_width, s->height, s->x, s->y);
4335 XFreePixmap (s->display, pixmap);
4336 }
4337 else
4338 x_draw_image_foreground (s);
4339
4340 /* If we must draw a relief around the image, do it. */
4341 if (s->img->relief
4342 || s->hl == DRAW_IMAGE_RAISED
4343 || s->hl == DRAW_IMAGE_SUNKEN)
4344 x_draw_image_relief (s);
4345 }
4346
4347
4348 /* Draw stretch glyph string S. */
4349
4350 static void
4351 x_draw_stretch_glyph_string (s)
4352 struct glyph_string *s;
4353 {
4354 xassert (s->first_glyph->type == STRETCH_GLYPH);
4355 s->stippled_p = s->face->stipple != 0;
4356
4357 if (s->hl == DRAW_CURSOR
4358 && !x_stretch_cursor_p)
4359 {
4360 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4361 as wide as the stretch glyph. */
4362 int width = min (CANON_X_UNIT (s->f), s->background_width);
4363
4364 /* Draw cursor. */
4365 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4366
4367 /* Clear rest using the GC of the original non-cursor face. */
4368 if (width < s->background_width)
4369 {
4370 int x = s->x + width, y = s->y;
4371 int w = s->background_width - width, h = s->height;
4372 XRectangle r;
4373 GC gc;
4374
4375 if (s->row->mouse_face_p
4376 && cursor_in_mouse_face_p (s->w))
4377 {
4378 x_set_mouse_face_gc (s);
4379 gc = s->gc;
4380 }
4381 else
4382 gc = s->face->gc;
4383
4384 x_get_glyph_string_clip_rect (s, &r);
4385 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4386
4387 if (s->face->stipple)
4388 {
4389 /* Fill background with a stipple pattern. */
4390 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4391 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4392 XSetFillStyle (s->display, gc, FillSolid);
4393 }
4394 else
4395 {
4396 XGCValues xgcv;
4397 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4398 XSetForeground (s->display, gc, xgcv.background);
4399 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4400 XSetForeground (s->display, gc, xgcv.foreground);
4401 }
4402 }
4403 }
4404 else if (!s->background_filled_p)
4405 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4406 s->height);
4407
4408 s->background_filled_p = 1;
4409 }
4410
4411
4412 /* Draw glyph string S. */
4413
4414 static void
4415 x_draw_glyph_string (s)
4416 struct glyph_string *s;
4417 {
4418 int relief_drawn_p = 0;
4419
4420 /* If S draws into the background of its successor, draw the
4421 background of the successor first so that S can draw into it.
4422 This makes S->next use XDrawString instead of XDrawImageString. */
4423 if (s->next && s->right_overhang && !s->for_overlaps_p)
4424 {
4425 xassert (s->next->img == NULL);
4426 x_set_glyph_string_gc (s->next);
4427 x_set_glyph_string_clipping (s->next);
4428 x_draw_glyph_string_background (s->next, 1);
4429 }
4430
4431 /* Set up S->gc, set clipping and draw S. */
4432 x_set_glyph_string_gc (s);
4433
4434 /* Draw relief (if any) in advance for char/composition so that the
4435 glyph string can be drawn over it. */
4436 if (!s->for_overlaps_p
4437 && s->face->box != FACE_NO_BOX
4438 && (s->first_glyph->type == CHAR_GLYPH
4439 || s->first_glyph->type == COMPOSITE_GLYPH))
4440
4441 {
4442 x_set_glyph_string_clipping (s);
4443 x_draw_glyph_string_background (s, 1);
4444 x_draw_glyph_string_box (s);
4445 x_set_glyph_string_clipping (s);
4446 relief_drawn_p = 1;
4447 }
4448 else
4449 x_set_glyph_string_clipping (s);
4450
4451 switch (s->first_glyph->type)
4452 {
4453 case IMAGE_GLYPH:
4454 x_draw_image_glyph_string (s);
4455 break;
4456
4457 case STRETCH_GLYPH:
4458 x_draw_stretch_glyph_string (s);
4459 break;
4460
4461 case CHAR_GLYPH:
4462 if (s->for_overlaps_p)
4463 s->background_filled_p = 1;
4464 else
4465 x_draw_glyph_string_background (s, 0);
4466 x_draw_glyph_string_foreground (s);
4467 break;
4468
4469 case COMPOSITE_GLYPH:
4470 if (s->for_overlaps_p || s->gidx > 0)
4471 s->background_filled_p = 1;
4472 else
4473 x_draw_glyph_string_background (s, 1);
4474 x_draw_composite_glyph_string_foreground (s);
4475 break;
4476
4477 default:
4478 abort ();
4479 }
4480
4481 if (!s->for_overlaps_p)
4482 {
4483 /* Draw underline. */
4484 if (s->face->underline_p)
4485 {
4486 unsigned long tem, h;
4487 int y;
4488
4489 /* Get the underline thickness. Default is 1 pixel. */
4490 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4491 h = 1;
4492
4493 /* Get the underline position. This is the recommended
4494 vertical offset in pixels from the baseline to the top of
4495 the underline. This is a signed value according to the
4496 specs, and its default is
4497
4498 ROUND ((maximum descent) / 2), with
4499 ROUND(x) = floor (x + 0.5) */
4500
4501 if (x_use_underline_position_properties
4502 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4503 y = s->ybase + (long) tem;
4504 else if (s->face->font)
4505 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4506 else
4507 y = s->y + s->height - h;
4508
4509 if (s->face->underline_defaulted_p)
4510 XFillRectangle (s->display, s->window, s->gc,
4511 s->x, y, s->width, h);
4512 else
4513 {
4514 XGCValues xgcv;
4515 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4516 XSetForeground (s->display, s->gc, s->face->underline_color);
4517 XFillRectangle (s->display, s->window, s->gc,
4518 s->x, y, s->width, h);
4519 XSetForeground (s->display, s->gc, xgcv.foreground);
4520 }
4521 }
4522
4523 /* Draw overline. */
4524 if (s->face->overline_p)
4525 {
4526 unsigned long dy = 0, h = 1;
4527
4528 if (s->face->overline_color_defaulted_p)
4529 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4530 s->width, h);
4531 else
4532 {
4533 XGCValues xgcv;
4534 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4535 XSetForeground (s->display, s->gc, s->face->overline_color);
4536 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4537 s->width, h);
4538 XSetForeground (s->display, s->gc, xgcv.foreground);
4539 }
4540 }
4541
4542 /* Draw strike-through. */
4543 if (s->face->strike_through_p)
4544 {
4545 unsigned long h = 1;
4546 unsigned long dy = (s->height - h) / 2;
4547
4548 if (s->face->strike_through_color_defaulted_p)
4549 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4550 s->width, h);
4551 else
4552 {
4553 XGCValues xgcv;
4554 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4555 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4556 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4557 s->width, h);
4558 XSetForeground (s->display, s->gc, xgcv.foreground);
4559 }
4560 }
4561
4562 /* Draw relief if not yet drawn. */
4563 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4564 x_draw_glyph_string_box (s);
4565 }
4566
4567 /* Reset clipping. */
4568 XSetClipMask (s->display, s->gc, None);
4569 }
4570
4571
4572 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4573 struct face **, int));
4574
4575
4576 /* Fill glyph string S with composition components specified by S->cmp.
4577
4578 FACES is an array of faces for all components of this composition.
4579 S->gidx is the index of the first component for S.
4580 OVERLAPS_P non-zero means S should draw the foreground only, and
4581 use its physical height for clipping.
4582
4583 Value is the index of a component not in S. */
4584
4585 static int
4586 x_fill_composite_glyph_string (s, faces, overlaps_p)
4587 struct glyph_string *s;
4588 struct face **faces;
4589 int overlaps_p;
4590 {
4591 int i;
4592
4593 xassert (s);
4594
4595 s->for_overlaps_p = overlaps_p;
4596
4597 s->face = faces[s->gidx];
4598 s->font = s->face->font;
4599 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4600
4601 /* For all glyphs of this composition, starting at the offset
4602 S->gidx, until we reach the end of the definition or encounter a
4603 glyph that requires the different face, add it to S. */
4604 ++s->nchars;
4605 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4606 ++s->nchars;
4607
4608 /* All glyph strings for the same composition has the same width,
4609 i.e. the width set for the first component of the composition. */
4610
4611 s->width = s->first_glyph->pixel_width;
4612
4613 /* If the specified font could not be loaded, use the frame's
4614 default font, but record the fact that we couldn't load it in
4615 the glyph string so that we can draw rectangles for the
4616 characters of the glyph string. */
4617 if (s->font == NULL)
4618 {
4619 s->font_not_found_p = 1;
4620 s->font = FRAME_FONT (s->f);
4621 }
4622
4623 /* Adjust base line for subscript/superscript text. */
4624 s->ybase += s->first_glyph->voffset;
4625
4626 xassert (s->face && s->face->gc);
4627
4628 /* This glyph string must always be drawn with 16-bit functions. */
4629 s->two_byte_p = 1;
4630
4631 return s->gidx + s->nchars;
4632 }
4633
4634
4635 /* Fill glyph string S from a sequence of character glyphs.
4636
4637 FACE_ID is the face id of the string. START is the index of the
4638 first glyph to consider, END is the index of the last + 1.
4639 OVERLAPS_P non-zero means S should draw the foreground only, and
4640 use its physical height for clipping.
4641
4642 Value is the index of the first glyph not in S. */
4643
4644 static int
4645 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4646 struct glyph_string *s;
4647 int face_id;
4648 int start, end, overlaps_p;
4649 {
4650 struct glyph *glyph, *last;
4651 int voffset;
4652 int glyph_not_available_p;
4653
4654 xassert (s->f == XFRAME (s->w->frame));
4655 xassert (s->nchars == 0);
4656 xassert (start >= 0 && end > start);
4657
4658 s->for_overlaps_p = overlaps_p,
4659 glyph = s->row->glyphs[s->area] + start;
4660 last = s->row->glyphs[s->area] + end;
4661 voffset = glyph->voffset;
4662
4663 glyph_not_available_p = glyph->glyph_not_available_p;
4664
4665 while (glyph < last
4666 && glyph->type == CHAR_GLYPH
4667 && glyph->voffset == voffset
4668 /* Same face id implies same font, nowadays. */
4669 && glyph->face_id == face_id
4670 && glyph->glyph_not_available_p == glyph_not_available_p)
4671 {
4672 int two_byte_p;
4673
4674 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4675 s->char2b + s->nchars,
4676 &two_byte_p);
4677 s->two_byte_p = two_byte_p;
4678 ++s->nchars;
4679 xassert (s->nchars <= end - start);
4680 s->width += glyph->pixel_width;
4681 ++glyph;
4682 }
4683
4684 s->font = s->face->font;
4685 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4686
4687 /* If the specified font could not be loaded, use the frame's font,
4688 but record the fact that we couldn't load it in
4689 S->font_not_found_p so that we can draw rectangles for the
4690 characters of the glyph string. */
4691 if (s->font == NULL || glyph_not_available_p)
4692 {
4693 s->font_not_found_p = 1;
4694 s->font = FRAME_FONT (s->f);
4695 }
4696
4697 /* Adjust base line for subscript/superscript text. */
4698 s->ybase += voffset;
4699
4700 xassert (s->face && s->face->gc);
4701 return glyph - s->row->glyphs[s->area];
4702 }
4703
4704
4705 /* Fill glyph string S from image glyph S->first_glyph. */
4706
4707 static void
4708 x_fill_image_glyph_string (s)
4709 struct glyph_string *s;
4710 {
4711 xassert (s->first_glyph->type == IMAGE_GLYPH);
4712 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4713 xassert (s->img);
4714 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4715 s->font = s->face->font;
4716 s->width = s->first_glyph->pixel_width;
4717
4718 /* Adjust base line for subscript/superscript text. */
4719 s->ybase += s->first_glyph->voffset;
4720 }
4721
4722
4723 /* Fill glyph string S from a sequence of stretch glyphs.
4724
4725 ROW is the glyph row in which the glyphs are found, AREA is the
4726 area within the row. START is the index of the first glyph to
4727 consider, END is the index of the last + 1.
4728
4729 Value is the index of the first glyph not in S. */
4730
4731 static int
4732 x_fill_stretch_glyph_string (s, row, area, start, end)
4733 struct glyph_string *s;
4734 struct glyph_row *row;
4735 enum glyph_row_area area;
4736 int start, end;
4737 {
4738 struct glyph *glyph, *last;
4739 int voffset, face_id;
4740
4741 xassert (s->first_glyph->type == STRETCH_GLYPH);
4742
4743 glyph = s->row->glyphs[s->area] + start;
4744 last = s->row->glyphs[s->area] + end;
4745 face_id = glyph->face_id;
4746 s->face = FACE_FROM_ID (s->f, face_id);
4747 s->font = s->face->font;
4748 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4749 s->width = glyph->pixel_width;
4750 voffset = glyph->voffset;
4751
4752 for (++glyph;
4753 (glyph < last
4754 && glyph->type == STRETCH_GLYPH
4755 && glyph->voffset == voffset
4756 && glyph->face_id == face_id);
4757 ++glyph)
4758 s->width += glyph->pixel_width;
4759
4760 /* Adjust base line for subscript/superscript text. */
4761 s->ybase += voffset;
4762
4763 /* The case that face->gc == 0 is handled when drawing the glyph
4764 string by calling PREPARE_FACE_FOR_DISPLAY. */
4765 xassert (s->face);
4766 return glyph - s->row->glyphs[s->area];
4767 }
4768
4769
4770 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4771 of XChar2b structures for S; it can't be allocated in
4772 x_init_glyph_string because it must be allocated via `alloca'. W
4773 is the window on which S is drawn. ROW and AREA are the glyph row
4774 and area within the row from which S is constructed. START is the
4775 index of the first glyph structure covered by S. HL is a
4776 face-override for drawing S. */
4777
4778 static void
4779 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4780 struct glyph_string *s;
4781 XChar2b *char2b;
4782 struct window *w;
4783 struct glyph_row *row;
4784 enum glyph_row_area area;
4785 int start;
4786 enum draw_glyphs_face hl;
4787 {
4788 bzero (s, sizeof *s);
4789 s->w = w;
4790 s->f = XFRAME (w->frame);
4791 s->display = FRAME_X_DISPLAY (s->f);
4792 s->window = FRAME_X_WINDOW (s->f);
4793 s->char2b = char2b;
4794 s->hl = hl;
4795 s->row = row;
4796 s->area = area;
4797 s->first_glyph = row->glyphs[area] + start;
4798 s->height = row->height;
4799 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4800
4801 /* Display the internal border below the tool-bar window. */
4802 if (s->w == XWINDOW (s->f->tool_bar_window))
4803 s->y -= s->f->output_data.x->internal_border_width;
4804
4805 s->ybase = s->y + row->ascent;
4806 }
4807
4808
4809 /* Set background width of glyph string S. START is the index of the
4810 first glyph following S. LAST_X is the right-most x-position + 1
4811 in the drawing area. */
4812
4813 static INLINE void
4814 x_set_glyph_string_background_width (s, start, last_x)
4815 struct glyph_string *s;
4816 int start;
4817 int last_x;
4818 {
4819 /* If the face of this glyph string has to be drawn to the end of
4820 the drawing area, set S->extends_to_end_of_line_p. */
4821 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4822
4823 if (start == s->row->used[s->area]
4824 && s->area == TEXT_AREA
4825 && ((s->hl == DRAW_NORMAL_TEXT
4826 && (s->row->fill_line_p
4827 || s->face->background != default_face->background
4828 || s->face->stipple != default_face->stipple
4829 || s->row->mouse_face_p))
4830 || s->hl == DRAW_MOUSE_FACE
4831 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4832 && s->row->fill_line_p)))
4833 s->extends_to_end_of_line_p = 1;
4834
4835 /* If S extends its face to the end of the line, set its
4836 background_width to the distance to the right edge of the drawing
4837 area. */
4838 if (s->extends_to_end_of_line_p)
4839 s->background_width = last_x - s->x + 1;
4840 else
4841 s->background_width = s->width;
4842 }
4843
4844
4845 /* Add a glyph string for a stretch glyph to the list of strings
4846 between HEAD and TAIL. START is the index of the stretch glyph in
4847 row area AREA of glyph row ROW. END is the index of the last glyph
4848 in that glyph row area. X is the current output position assigned
4849 to the new glyph string constructed. HL overrides that face of the
4850 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4851 is the right-most x-position of the drawing area. */
4852
4853 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4854 and below -- keep them on one line. */
4855 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4856 do \
4857 { \
4858 s = (struct glyph_string *) alloca (sizeof *s); \
4859 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4860 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4861 x_append_glyph_string (&HEAD, &TAIL, s); \
4862 s->x = (X); \
4863 } \
4864 while (0)
4865
4866
4867 /* Add a glyph string for an image glyph to the list of strings
4868 between HEAD and TAIL. START is the index of the image glyph in
4869 row area AREA of glyph row ROW. END is the index of the last glyph
4870 in that glyph row area. X is the current output position assigned
4871 to the new glyph string constructed. HL overrides that face of the
4872 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4873 is the right-most x-position of the drawing area. */
4874
4875 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4876 do \
4877 { \
4878 s = (struct glyph_string *) alloca (sizeof *s); \
4879 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4880 x_fill_image_glyph_string (s); \
4881 x_append_glyph_string (&HEAD, &TAIL, s); \
4882 ++START; \
4883 s->x = (X); \
4884 } \
4885 while (0)
4886
4887
4888 /* Add a glyph string for a sequence of character glyphs to the list
4889 of strings between HEAD and TAIL. START is the index of the first
4890 glyph in row area AREA of glyph row ROW that is part of the new
4891 glyph string. END is the index of the last glyph in that glyph row
4892 area. X is the current output position assigned to the new glyph
4893 string constructed. HL overrides that face of the glyph; e.g. it
4894 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4895 right-most x-position of the drawing area. */
4896
4897 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4898 do \
4899 { \
4900 int c, face_id; \
4901 XChar2b *char2b; \
4902 \
4903 c = (ROW)->glyphs[AREA][START].u.ch; \
4904 face_id = (ROW)->glyphs[AREA][START].face_id; \
4905 \
4906 s = (struct glyph_string *) alloca (sizeof *s); \
4907 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4908 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4909 x_append_glyph_string (&HEAD, &TAIL, s); \
4910 s->x = (X); \
4911 START = x_fill_glyph_string (s, face_id, START, END, \
4912 OVERLAPS_P); \
4913 } \
4914 while (0)
4915
4916
4917 /* Add a glyph string for a composite sequence to the list of strings
4918 between HEAD and TAIL. START is the index of the first glyph in
4919 row area AREA of glyph row ROW that is part of the new glyph
4920 string. END is the index of the last glyph in that glyph row area.
4921 X is the current output position assigned to the new glyph string
4922 constructed. HL overrides that face of the glyph; e.g. it is
4923 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4924 x-position of the drawing area. */
4925
4926 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4927 do { \
4928 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4929 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4930 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4931 struct composition *cmp = composition_table[cmp_id]; \
4932 int glyph_len = cmp->glyph_len; \
4933 XChar2b *char2b; \
4934 struct face **faces; \
4935 struct glyph_string *first_s = NULL; \
4936 int n; \
4937 \
4938 base_face = base_face->ascii_face; \
4939 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4940 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4941 /* At first, fill in `char2b' and `faces'. */ \
4942 for (n = 0; n < glyph_len; n++) \
4943 { \
4944 int c = COMPOSITION_GLYPH (cmp, n); \
4945 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4946 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4947 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4948 this_face_id, char2b + n, 1); \
4949 } \
4950 \
4951 /* Make glyph_strings for each glyph sequence that is drawable by \
4952 the same face, and append them to HEAD/TAIL. */ \
4953 for (n = 0; n < cmp->glyph_len;) \
4954 { \
4955 s = (struct glyph_string *) alloca (sizeof *s); \
4956 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4957 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4958 s->cmp = cmp; \
4959 s->gidx = n; \
4960 s->x = (X); \
4961 \
4962 if (n == 0) \
4963 first_s = s; \
4964 \
4965 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4966 } \
4967 \
4968 ++START; \
4969 s = first_s; \
4970 } while (0)
4971
4972
4973 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4974 of AREA of glyph row ROW on window W between indices START and END.
4975 HL overrides the face for drawing glyph strings, e.g. it is
4976 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4977 x-positions of the drawing area.
4978
4979 This is an ugly monster macro construct because we must use alloca
4980 to allocate glyph strings (because x_draw_glyphs can be called
4981 asynchronously). */
4982
4983 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4984 do \
4985 { \
4986 HEAD = TAIL = NULL; \
4987 while (START < END) \
4988 { \
4989 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4990 switch (first_glyph->type) \
4991 { \
4992 case CHAR_GLYPH: \
4993 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4994 TAIL, HL, X, LAST_X, \
4995 OVERLAPS_P); \
4996 break; \
4997 \
4998 case COMPOSITE_GLYPH: \
4999 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5000 HEAD, TAIL, HL, X, LAST_X,\
5001 OVERLAPS_P); \
5002 break; \
5003 \
5004 case STRETCH_GLYPH: \
5005 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5006 HEAD, TAIL, HL, X, LAST_X); \
5007 break; \
5008 \
5009 case IMAGE_GLYPH: \
5010 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5011 TAIL, HL, X, LAST_X); \
5012 break; \
5013 \
5014 default: \
5015 abort (); \
5016 } \
5017 \
5018 x_set_glyph_string_background_width (s, START, LAST_X); \
5019 (X) += s->width; \
5020 } \
5021 } \
5022 while (0)
5023
5024
5025 /* Draw glyphs between START and END in AREA of ROW on window W,
5026 starting at x-position X. X is relative to AREA in W. HL is a
5027 face-override with the following meaning:
5028
5029 DRAW_NORMAL_TEXT draw normally
5030 DRAW_CURSOR draw in cursor face
5031 DRAW_MOUSE_FACE draw in mouse face.
5032 DRAW_INVERSE_VIDEO draw in mode line face
5033 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5034 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5035
5036 If OVERLAPS_P is non-zero, draw only the foreground of characters
5037 and clip to the physical height of ROW.
5038
5039 Value is the x-position reached, relative to AREA of W. */
5040
5041 static int
5042 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5043 struct window *w;
5044 int x;
5045 struct glyph_row *row;
5046 enum glyph_row_area area;
5047 int start, end;
5048 enum draw_glyphs_face hl;
5049 int overlaps_p;
5050 {
5051 struct glyph_string *head, *tail;
5052 struct glyph_string *s;
5053 int last_x, area_width;
5054 int x_reached;
5055 int i, j;
5056
5057 /* Let's rather be paranoid than getting a SEGV. */
5058 end = min (end, row->used[area]);
5059 start = max (0, start);
5060 start = min (end, start);
5061
5062 /* Translate X to frame coordinates. Set last_x to the right
5063 end of the drawing area. */
5064 if (row->full_width_p)
5065 {
5066 /* X is relative to the left edge of W, without scroll bars
5067 or fringes. */
5068 struct frame *f = XFRAME (w->frame);
5069 /* int width = FRAME_FRINGE_WIDTH (f); */
5070 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5071
5072 x += window_left_x;
5073 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5074 last_x = window_left_x + area_width;
5075
5076 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5077 {
5078 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5079 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5080 last_x += width;
5081 else
5082 x -= width;
5083 }
5084
5085 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5086 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
5087 }
5088 else
5089 {
5090 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5091 area_width = window_box_width (w, area);
5092 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5093 }
5094
5095 /* Build a doubly-linked list of glyph_string structures between
5096 head and tail from what we have to draw. Note that the macro
5097 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5098 the reason we use a separate variable `i'. */
5099 i = start;
5100 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5101 overlaps_p);
5102 if (tail)
5103 x_reached = tail->x + tail->background_width;
5104 else
5105 x_reached = x;
5106
5107 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5108 the row, redraw some glyphs in front or following the glyph
5109 strings built above. */
5110 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5111 {
5112 int dummy_x = 0;
5113 struct glyph_string *h, *t;
5114
5115 /* Compute overhangs for all glyph strings. */
5116 for (s = head; s; s = s->next)
5117 x_compute_glyph_string_overhangs (s);
5118
5119 /* Prepend glyph strings for glyphs in front of the first glyph
5120 string that are overwritten because of the first glyph
5121 string's left overhang. The background of all strings
5122 prepended must be drawn because the first glyph string
5123 draws over it. */
5124 i = x_left_overwritten (head);
5125 if (i >= 0)
5126 {
5127 j = i;
5128 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5129 DRAW_NORMAL_TEXT, dummy_x, last_x,
5130 overlaps_p);
5131 start = i;
5132 x_compute_overhangs_and_x (t, head->x, 1);
5133 x_prepend_glyph_string_lists (&head, &tail, h, t);
5134 }
5135
5136 /* Prepend glyph strings for glyphs in front of the first glyph
5137 string that overwrite that glyph string because of their
5138 right overhang. For these strings, only the foreground must
5139 be drawn, because it draws over the glyph string at `head'.
5140 The background must not be drawn because this would overwrite
5141 right overhangs of preceding glyphs for which no glyph
5142 strings exist. */
5143 i = x_left_overwriting (head);
5144 if (i >= 0)
5145 {
5146 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5147 DRAW_NORMAL_TEXT, dummy_x, last_x,
5148 overlaps_p);
5149 for (s = h; s; s = s->next)
5150 s->background_filled_p = 1;
5151 x_compute_overhangs_and_x (t, head->x, 1);
5152 x_prepend_glyph_string_lists (&head, &tail, h, t);
5153 }
5154
5155 /* Append glyphs strings for glyphs following the last glyph
5156 string tail that are overwritten by tail. The background of
5157 these strings has to be drawn because tail's foreground draws
5158 over it. */
5159 i = x_right_overwritten (tail);
5160 if (i >= 0)
5161 {
5162 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5163 DRAW_NORMAL_TEXT, x, last_x,
5164 overlaps_p);
5165 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5166 x_append_glyph_string_lists (&head, &tail, h, t);
5167 }
5168
5169 /* Append glyph strings for glyphs following the last glyph
5170 string tail that overwrite tail. The foreground of such
5171 glyphs has to be drawn because it writes into the background
5172 of tail. The background must not be drawn because it could
5173 paint over the foreground of following glyphs. */
5174 i = x_right_overwriting (tail);
5175 if (i >= 0)
5176 {
5177 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5178 DRAW_NORMAL_TEXT, x, last_x,
5179 overlaps_p);
5180 for (s = h; s; s = s->next)
5181 s->background_filled_p = 1;
5182 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5183 x_append_glyph_string_lists (&head, &tail, h, t);
5184 }
5185 }
5186
5187 /* Draw all strings. */
5188 for (s = head; s; s = s->next)
5189 x_draw_glyph_string (s);
5190
5191 if (area == TEXT_AREA && !row->full_width_p)
5192 {
5193 int x0 = head ? head->x : x;
5194 int x1 = tail ? tail->x + tail->background_width : x;
5195
5196 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5197 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5198
5199 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5200 {
5201 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5202 x0 -= left_area_width;
5203 x1 -= left_area_width;
5204 }
5205
5206 notice_overwritten_cursor (w, x0, x1);
5207 }
5208
5209 /* Value is the x-position up to which drawn, relative to AREA of W.
5210 This doesn't include parts drawn because of overhangs. */
5211 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5212 if (!row->full_width_p)
5213 {
5214 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
5215 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5216 if (area > TEXT_AREA)
5217 x_reached -= window_box_width (w, TEXT_AREA);
5218 }
5219
5220 return x_reached;
5221 }
5222
5223
5224 /* Fix the display of area AREA of overlapping row ROW in window W. */
5225
5226 static void
5227 x_fix_overlapping_area (w, row, area)
5228 struct window *w;
5229 struct glyph_row *row;
5230 enum glyph_row_area area;
5231 {
5232 int i, x;
5233
5234 BLOCK_INPUT;
5235
5236 if (area == LEFT_MARGIN_AREA)
5237 x = 0;
5238 else if (area == TEXT_AREA)
5239 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5240 else
5241 x = (window_box_width (w, LEFT_MARGIN_AREA)
5242 + window_box_width (w, TEXT_AREA));
5243
5244 for (i = 0; i < row->used[area];)
5245 {
5246 if (row->glyphs[area][i].overlaps_vertically_p)
5247 {
5248 int start = i, start_x = x;
5249
5250 do
5251 {
5252 x += row->glyphs[area][i].pixel_width;
5253 ++i;
5254 }
5255 while (i < row->used[area]
5256 && row->glyphs[area][i].overlaps_vertically_p);
5257
5258 x_draw_glyphs (w, start_x, row, area, start, i,
5259 DRAW_NORMAL_TEXT, 1);
5260 }
5261 else
5262 {
5263 x += row->glyphs[area][i].pixel_width;
5264 ++i;
5265 }
5266 }
5267
5268 UNBLOCK_INPUT;
5269 }
5270
5271
5272 /* Output LEN glyphs starting at START at the nominal cursor position.
5273 Advance the nominal cursor over the text. The global variable
5274 updated_window contains the window being updated, updated_row is
5275 the glyph row being updated, and updated_area is the area of that
5276 row being updated. */
5277
5278 static void
5279 x_write_glyphs (start, len)
5280 struct glyph *start;
5281 int len;
5282 {
5283 int x, hpos;
5284
5285 xassert (updated_window && updated_row);
5286 BLOCK_INPUT;
5287
5288 /* Write glyphs. */
5289
5290 hpos = start - updated_row->glyphs[updated_area];
5291 x = x_draw_glyphs (updated_window, output_cursor.x,
5292 updated_row, updated_area,
5293 hpos, hpos + len,
5294 DRAW_NORMAL_TEXT, 0);
5295
5296 UNBLOCK_INPUT;
5297
5298 /* Advance the output cursor. */
5299 output_cursor.hpos += len;
5300 output_cursor.x = x;
5301 }
5302
5303
5304 /* Insert LEN glyphs from START at the nominal cursor position. */
5305
5306 static void
5307 x_insert_glyphs (start, len)
5308 struct glyph *start;
5309 register int len;
5310 {
5311 struct frame *f;
5312 struct window *w;
5313 int line_height, shift_by_width, shifted_region_width;
5314 struct glyph_row *row;
5315 struct glyph *glyph;
5316 int frame_x, frame_y, hpos;
5317
5318 xassert (updated_window && updated_row);
5319 BLOCK_INPUT;
5320 w = updated_window;
5321 f = XFRAME (WINDOW_FRAME (w));
5322
5323 /* Get the height of the line we are in. */
5324 row = updated_row;
5325 line_height = row->height;
5326
5327 /* Get the width of the glyphs to insert. */
5328 shift_by_width = 0;
5329 for (glyph = start; glyph < start + len; ++glyph)
5330 shift_by_width += glyph->pixel_width;
5331
5332 /* Get the width of the region to shift right. */
5333 shifted_region_width = (window_box_width (w, updated_area)
5334 - output_cursor.x
5335 - shift_by_width);
5336
5337 /* Shift right. */
5338 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5339 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5340 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5341 f->output_data.x->normal_gc,
5342 frame_x, frame_y,
5343 shifted_region_width, line_height,
5344 frame_x + shift_by_width, frame_y);
5345
5346 /* Write the glyphs. */
5347 hpos = start - row->glyphs[updated_area];
5348 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5349 DRAW_NORMAL_TEXT, 0);
5350
5351 /* Advance the output cursor. */
5352 output_cursor.hpos += len;
5353 output_cursor.x += shift_by_width;
5354 UNBLOCK_INPUT;
5355 }
5356
5357
5358 /* Delete N glyphs at the nominal cursor position. Not implemented
5359 for X frames. */
5360
5361 static void
5362 x_delete_glyphs (n)
5363 register int n;
5364 {
5365 abort ();
5366 }
5367
5368
5369 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5370 If they are <= 0, this is probably an error. */
5371
5372 void
5373 x_clear_area (dpy, window, x, y, width, height, exposures)
5374 Display *dpy;
5375 Window window;
5376 int x, y;
5377 int width, height;
5378 int exposures;
5379 {
5380 xassert (width > 0 && height > 0);
5381 XClearArea (dpy, window, x, y, width, height, exposures);
5382 }
5383
5384
5385 /* Erase the current text line from the nominal cursor position
5386 (inclusive) to pixel column TO_X (exclusive). The idea is that
5387 everything from TO_X onward is already erased.
5388
5389 TO_X is a pixel position relative to updated_area of
5390 updated_window. TO_X == -1 means clear to the end of this area. */
5391
5392 static void
5393 x_clear_end_of_line (to_x)
5394 int to_x;
5395 {
5396 struct frame *f;
5397 struct window *w = updated_window;
5398 int max_x, min_y, max_y;
5399 int from_x, from_y, to_y;
5400
5401 xassert (updated_window && updated_row);
5402 f = XFRAME (w->frame);
5403
5404 if (updated_row->full_width_p)
5405 {
5406 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5407 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5408 && !w->pseudo_window_p)
5409 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5410 }
5411 else
5412 max_x = window_box_width (w, updated_area);
5413 max_y = window_text_bottom_y (w);
5414
5415 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5416 of window. For TO_X > 0, truncate to end of drawing area. */
5417 if (to_x == 0)
5418 return;
5419 else if (to_x < 0)
5420 to_x = max_x;
5421 else
5422 to_x = min (to_x, max_x);
5423
5424 to_y = min (max_y, output_cursor.y + updated_row->height);
5425
5426 /* Notice if the cursor will be cleared by this operation. */
5427 if (!updated_row->full_width_p)
5428 notice_overwritten_cursor (w, output_cursor.x, -1);
5429
5430 from_x = output_cursor.x;
5431
5432 /* Translate to frame coordinates. */
5433 if (updated_row->full_width_p)
5434 {
5435 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5436 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5437 }
5438 else
5439 {
5440 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5441 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5442 }
5443
5444 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5445 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5446 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5447
5448 /* Prevent inadvertently clearing to end of the X window. */
5449 if (to_x > from_x && to_y > from_y)
5450 {
5451 BLOCK_INPUT;
5452 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5453 from_x, from_y, to_x - from_x, to_y - from_y,
5454 False);
5455 UNBLOCK_INPUT;
5456 }
5457 }
5458
5459
5460 /* Clear entire frame. If updating_frame is non-null, clear that
5461 frame. Otherwise clear the selected frame. */
5462
5463 static void
5464 x_clear_frame ()
5465 {
5466 struct frame *f;
5467
5468 if (updating_frame)
5469 f = updating_frame;
5470 else
5471 f = SELECTED_FRAME ();
5472
5473 /* Clearing the frame will erase any cursor, so mark them all as no
5474 longer visible. */
5475 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5476 output_cursor.hpos = output_cursor.vpos = 0;
5477 output_cursor.x = -1;
5478
5479 /* We don't set the output cursor here because there will always
5480 follow an explicit cursor_to. */
5481 BLOCK_INPUT;
5482 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5483
5484 /* We have to clear the scroll bars, too. If we have changed
5485 colors or something like that, then they should be notified. */
5486 x_scroll_bar_clear (f);
5487
5488 XFlush (FRAME_X_DISPLAY (f));
5489 UNBLOCK_INPUT;
5490 }
5491
5492
5493 \f
5494 /* Invert the middle quarter of the frame for .15 sec. */
5495
5496 /* We use the select system call to do the waiting, so we have to make
5497 sure it's available. If it isn't, we just won't do visual bells. */
5498
5499 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5500
5501
5502 /* Subtract the `struct timeval' values X and Y, storing the result in
5503 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5504
5505 static int
5506 timeval_subtract (result, x, y)
5507 struct timeval *result, x, y;
5508 {
5509 /* Perform the carry for the later subtraction by updating y. This
5510 is safer because on some systems the tv_sec member is unsigned. */
5511 if (x.tv_usec < y.tv_usec)
5512 {
5513 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5514 y.tv_usec -= 1000000 * nsec;
5515 y.tv_sec += nsec;
5516 }
5517
5518 if (x.tv_usec - y.tv_usec > 1000000)
5519 {
5520 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5521 y.tv_usec += 1000000 * nsec;
5522 y.tv_sec -= nsec;
5523 }
5524
5525 /* Compute the time remaining to wait. tv_usec is certainly
5526 positive. */
5527 result->tv_sec = x.tv_sec - y.tv_sec;
5528 result->tv_usec = x.tv_usec - y.tv_usec;
5529
5530 /* Return indication of whether the result should be considered
5531 negative. */
5532 return x.tv_sec < y.tv_sec;
5533 }
5534
5535 void
5536 XTflash (f)
5537 struct frame *f;
5538 {
5539 BLOCK_INPUT;
5540
5541 {
5542 GC gc;
5543
5544 /* Create a GC that will use the GXxor function to flip foreground
5545 pixels into background pixels. */
5546 {
5547 XGCValues values;
5548
5549 values.function = GXxor;
5550 values.foreground = (f->output_data.x->foreground_pixel
5551 ^ f->output_data.x->background_pixel);
5552
5553 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5554 GCFunction | GCForeground, &values);
5555 }
5556
5557 {
5558 /* Get the height not including a menu bar widget. */
5559 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5560 /* Height of each line to flash. */
5561 int flash_height = FRAME_LINE_HEIGHT (f);
5562 /* These will be the left and right margins of the rectangles. */
5563 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5564 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5565
5566 int width;
5567
5568 /* Don't flash the area between a scroll bar and the frame
5569 edge it is next to. */
5570 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5571 {
5572 case vertical_scroll_bar_left:
5573 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5574 break;
5575
5576 case vertical_scroll_bar_right:
5577 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5578 break;
5579
5580 default:
5581 break;
5582 }
5583
5584 width = flash_right - flash_left;
5585
5586 /* If window is tall, flash top and bottom line. */
5587 if (height > 3 * FRAME_LINE_HEIGHT (f))
5588 {
5589 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5590 flash_left,
5591 (FRAME_INTERNAL_BORDER_WIDTH (f)
5592 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5593 width, flash_height);
5594 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5595 flash_left,
5596 (height - flash_height
5597 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5598 width, flash_height);
5599 }
5600 else
5601 /* If it is short, flash it all. */
5602 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5603 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5604 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5605
5606 x_flush (f);
5607
5608 {
5609 struct timeval wakeup;
5610
5611 EMACS_GET_TIME (wakeup);
5612
5613 /* Compute time to wait until, propagating carry from usecs. */
5614 wakeup.tv_usec += 150000;
5615 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5616 wakeup.tv_usec %= 1000000;
5617
5618 /* Keep waiting until past the time wakeup or any input gets
5619 available. */
5620 while (! detect_input_pending ())
5621 {
5622 struct timeval current;
5623 struct timeval timeout;
5624
5625 EMACS_GET_TIME (current);
5626
5627 /* Break if result would be negative. */
5628 if (timeval_subtract (&current, wakeup, current))
5629 break;
5630
5631 /* How long `select' should wait. */
5632 timeout.tv_sec = 0;
5633 timeout.tv_usec = 10000;
5634
5635 /* Try to wait that long--but we might wake up sooner. */
5636 select (0, NULL, NULL, NULL, &timeout);
5637 }
5638 }
5639
5640 /* If window is tall, flash top and bottom line. */
5641 if (height > 3 * FRAME_LINE_HEIGHT (f))
5642 {
5643 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5644 flash_left,
5645 (FRAME_INTERNAL_BORDER_WIDTH (f)
5646 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5647 width, flash_height);
5648 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5649 flash_left,
5650 (height - flash_height
5651 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5652 width, flash_height);
5653 }
5654 else
5655 /* If it is short, flash it all. */
5656 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5657 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5658 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5659
5660 XFreeGC (FRAME_X_DISPLAY (f), gc);
5661 x_flush (f);
5662 }
5663 }
5664
5665 UNBLOCK_INPUT;
5666 }
5667
5668 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5669
5670
5671 /* Make audible bell. */
5672
5673 void
5674 XTring_bell ()
5675 {
5676 struct frame *f = SELECTED_FRAME ();
5677
5678 if (FRAME_X_DISPLAY (f))
5679 {
5680 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5681 if (visible_bell)
5682 XTflash (f);
5683 else
5684 #endif
5685 {
5686 BLOCK_INPUT;
5687 XBell (FRAME_X_DISPLAY (f), 0);
5688 XFlush (FRAME_X_DISPLAY (f));
5689 UNBLOCK_INPUT;
5690 }
5691 }
5692 }
5693
5694 \f
5695 /* Specify how many text lines, from the top of the window,
5696 should be affected by insert-lines and delete-lines operations.
5697 This, and those operations, are used only within an update
5698 that is bounded by calls to x_update_begin and x_update_end. */
5699
5700 static void
5701 XTset_terminal_window (n)
5702 register int n;
5703 {
5704 /* This function intentionally left blank. */
5705 }
5706
5707
5708 \f
5709 /***********************************************************************
5710 Line Dance
5711 ***********************************************************************/
5712
5713 /* Perform an insert-lines or delete-lines operation, inserting N
5714 lines or deleting -N lines at vertical position VPOS. */
5715
5716 static void
5717 x_ins_del_lines (vpos, n)
5718 int vpos, n;
5719 {
5720 abort ();
5721 }
5722
5723
5724 /* Scroll part of the display as described by RUN. */
5725
5726 static void
5727 x_scroll_run (w, run)
5728 struct window *w;
5729 struct run *run;
5730 {
5731 struct frame *f = XFRAME (w->frame);
5732 int x, y, width, height, from_y, to_y, bottom_y;
5733
5734 /* Get frame-relative bounding box of the text display area of W,
5735 without mode lines. Include in this box the left and right
5736 fringe of W. */
5737 window_box (w, -1, &x, &y, &width, &height);
5738 width += FRAME_X_FRINGE_WIDTH (f);
5739 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5740
5741 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5742 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5743 bottom_y = y + height;
5744
5745 if (to_y < from_y)
5746 {
5747 /* Scrolling up. Make sure we don't copy part of the mode
5748 line at the bottom. */
5749 if (from_y + run->height > bottom_y)
5750 height = bottom_y - from_y;
5751 else
5752 height = run->height;
5753 }
5754 else
5755 {
5756 /* Scolling down. Make sure we don't copy over the mode line.
5757 at the bottom. */
5758 if (to_y + run->height > bottom_y)
5759 height = bottom_y - to_y;
5760 else
5761 height = run->height;
5762 }
5763
5764 BLOCK_INPUT;
5765
5766 /* Cursor off. Will be switched on again in x_update_window_end. */
5767 updated_window = w;
5768 x_clear_cursor (w);
5769
5770 XCopyArea (FRAME_X_DISPLAY (f),
5771 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5772 f->output_data.x->normal_gc,
5773 x, from_y,
5774 width, height,
5775 x, to_y);
5776
5777 UNBLOCK_INPUT;
5778 }
5779
5780
5781 \f
5782 /***********************************************************************
5783 Exposure Events
5784 ***********************************************************************/
5785
5786 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5787 corner of the exposed rectangle. W and H are width and height of
5788 the exposed area. All are pixel values. W or H zero means redraw
5789 the entire frame. */
5790
5791 static void
5792 expose_frame (f, x, y, w, h)
5793 struct frame *f;
5794 int x, y, w, h;
5795 {
5796 XRectangle r;
5797 int mouse_face_overwritten_p = 0;
5798
5799 TRACE ((stderr, "expose_frame "));
5800
5801 /* No need to redraw if frame will be redrawn soon. */
5802 if (FRAME_GARBAGED_P (f))
5803 {
5804 TRACE ((stderr, " garbaged\n"));
5805 return;
5806 }
5807
5808 /* If basic faces haven't been realized yet, there is no point in
5809 trying to redraw anything. This can happen when we get an expose
5810 event while Emacs is starting, e.g. by moving another window. */
5811 if (FRAME_FACE_CACHE (f) == NULL
5812 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5813 {
5814 TRACE ((stderr, " no faces\n"));
5815 return;
5816 }
5817
5818 if (w == 0 || h == 0)
5819 {
5820 r.x = r.y = 0;
5821 r.width = CANON_X_UNIT (f) * f->width;
5822 r.height = CANON_Y_UNIT (f) * f->height;
5823 }
5824 else
5825 {
5826 r.x = x;
5827 r.y = y;
5828 r.width = w;
5829 r.height = h;
5830 }
5831
5832 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5833 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5834
5835 if (WINDOWP (f->tool_bar_window))
5836 mouse_face_overwritten_p
5837 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5838
5839 #ifndef USE_X_TOOLKIT
5840 if (WINDOWP (f->menu_bar_window))
5841 mouse_face_overwritten_p
5842 |= expose_window (XWINDOW (f->menu_bar_window), &r);
5843 #endif /* not USE_X_TOOLKIT */
5844
5845 /* Some window managers support a focus-follows-mouse style with
5846 delayed raising of frames. Imagine a partially obscured frame,
5847 and moving the mouse into partially obscured mouse-face on that
5848 frame. The visible part of the mouse-face will be highlighted,
5849 then the WM raises the obscured frame. With at least one WM, KDE
5850 2.1, Emacs is not getting any event for the raising of the frame
5851 (even tried with SubstructureRedirectMask), only Expose events.
5852 These expose events will draw text normally, i.e. not
5853 highlighted. Which means we must redo the highlight here.
5854 Subsume it under ``we love X''. --gerd 2001-08-15 */
5855 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5856 {
5857 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5858 if (f == dpyinfo->mouse_face_mouse_frame)
5859 {
5860 int x = dpyinfo->mouse_face_mouse_x;
5861 int y = dpyinfo->mouse_face_mouse_y;
5862 clear_mouse_face (dpyinfo);
5863 note_mouse_highlight (f, x, y);
5864 }
5865 }
5866 }
5867
5868
5869 /* Redraw (parts) of all windows in the window tree rooted at W that
5870 intersect R. R contains frame pixel coordinates. Value is
5871 non-zero if the exposure overwrites mouse-face. */
5872
5873 static int
5874 expose_window_tree (w, r)
5875 struct window *w;
5876 XRectangle *r;
5877 {
5878 struct frame *f = XFRAME (w->frame);
5879 int mouse_face_overwritten_p = 0;
5880
5881 while (w && !FRAME_GARBAGED_P (f))
5882 {
5883 if (!NILP (w->hchild))
5884 mouse_face_overwritten_p
5885 |= expose_window_tree (XWINDOW (w->hchild), r);
5886 else if (!NILP (w->vchild))
5887 mouse_face_overwritten_p
5888 |= expose_window_tree (XWINDOW (w->vchild), r);
5889 else
5890 mouse_face_overwritten_p |= expose_window (w, r);
5891
5892 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5893 }
5894
5895 return mouse_face_overwritten_p;
5896 }
5897
5898
5899 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5900 which intersects rectangle R. R is in window-relative coordinates. */
5901
5902 static void
5903 expose_area (w, row, r, area)
5904 struct window *w;
5905 struct glyph_row *row;
5906 XRectangle *r;
5907 enum glyph_row_area area;
5908 {
5909 struct glyph *first = row->glyphs[area];
5910 struct glyph *end = row->glyphs[area] + row->used[area];
5911 struct glyph *last;
5912 int first_x, start_x, x;
5913
5914 if (area == TEXT_AREA && row->fill_line_p)
5915 /* If row extends face to end of line write the whole line. */
5916 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
5917 DRAW_NORMAL_TEXT, 0);
5918 else
5919 {
5920 /* Set START_X to the window-relative start position for drawing glyphs of
5921 AREA. The first glyph of the text area can be partially visible.
5922 The first glyphs of other areas cannot. */
5923 if (area == LEFT_MARGIN_AREA)
5924 start_x = 0;
5925 else if (area == TEXT_AREA)
5926 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5927 else
5928 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5929 + window_box_width (w, TEXT_AREA));
5930 x = start_x;
5931
5932 /* Find the first glyph that must be redrawn. */
5933 while (first < end
5934 && x + first->pixel_width < r->x)
5935 {
5936 x += first->pixel_width;
5937 ++first;
5938 }
5939
5940 /* Find the last one. */
5941 last = first;
5942 first_x = x;
5943 while (last < end
5944 && x < r->x + r->width)
5945 {
5946 x += last->pixel_width;
5947 ++last;
5948 }
5949
5950 /* Repaint. */
5951 if (last > first)
5952 x_draw_glyphs (w, first_x - start_x, row, area,
5953 first - row->glyphs[area],
5954 last - row->glyphs[area],
5955 DRAW_NORMAL_TEXT, 0);
5956 }
5957 }
5958
5959
5960 /* Redraw the parts of the glyph row ROW on window W intersecting
5961 rectangle R. R is in window-relative coordinates. Value is
5962 non-zero if mouse-face was overwritten. */
5963
5964 static int
5965 expose_line (w, row, r)
5966 struct window *w;
5967 struct glyph_row *row;
5968 XRectangle *r;
5969 {
5970 xassert (row->enabled_p);
5971
5972 if (row->mode_line_p || w->pseudo_window_p)
5973 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5974 DRAW_NORMAL_TEXT, 0);
5975 else
5976 {
5977 if (row->used[LEFT_MARGIN_AREA])
5978 expose_area (w, row, r, LEFT_MARGIN_AREA);
5979 if (row->used[TEXT_AREA])
5980 expose_area (w, row, r, TEXT_AREA);
5981 if (row->used[RIGHT_MARGIN_AREA])
5982 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5983 x_draw_row_fringe_bitmaps (w, row);
5984 }
5985
5986 return row->mouse_face_p;
5987 }
5988
5989
5990 /* Return non-zero if W's cursor intersects rectangle R. */
5991
5992 static int
5993 x_phys_cursor_in_rect_p (w, r)
5994 struct window *w;
5995 XRectangle *r;
5996 {
5997 XRectangle cr, result;
5998 struct glyph *cursor_glyph;
5999
6000 cursor_glyph = get_phys_cursor_glyph (w);
6001 if (cursor_glyph)
6002 {
6003 cr.x = w->phys_cursor.x;
6004 cr.y = w->phys_cursor.y;
6005 cr.width = cursor_glyph->pixel_width;
6006 cr.height = w->phys_cursor_height;
6007 return x_intersect_rectangles (&cr, r, &result);
6008 }
6009 else
6010 return 0;
6011 }
6012
6013
6014 /* Redraw the part of window W intersection rectangle FR. Pixel
6015 coordinates in FR are frame-relative. Call this function with
6016 input blocked. Value is non-zero if the exposure overwrites
6017 mouse-face. */
6018
6019 static int
6020 expose_window (w, fr)
6021 struct window *w;
6022 XRectangle *fr;
6023 {
6024 struct frame *f = XFRAME (w->frame);
6025 XRectangle wr, r;
6026 int mouse_face_overwritten_p = 0;
6027
6028 /* If window is not yet fully initialized, do nothing. This can
6029 happen when toolkit scroll bars are used and a window is split.
6030 Reconfiguring the scroll bar will generate an expose for a newly
6031 created window. */
6032 if (w->current_matrix == NULL)
6033 return 0;
6034
6035 /* When we're currently updating the window, display and current
6036 matrix usually don't agree. Arrange for a thorough display
6037 later. */
6038 if (w == updated_window)
6039 {
6040 SET_FRAME_GARBAGED (f);
6041 return 0;
6042 }
6043
6044 /* Frame-relative pixel rectangle of W. */
6045 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6046 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6047 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6048 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6049
6050 if (x_intersect_rectangles (fr, &wr, &r))
6051 {
6052 int yb = window_text_bottom_y (w);
6053 struct glyph_row *row;
6054 int cursor_cleared_p;
6055
6056 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6057 r.x, r.y, r.width, r.height));
6058
6059 /* Convert to window coordinates. */
6060 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6061 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6062
6063 /* Turn off the cursor. */
6064 if (!w->pseudo_window_p
6065 && x_phys_cursor_in_rect_p (w, &r))
6066 {
6067 x_clear_cursor (w);
6068 cursor_cleared_p = 1;
6069 }
6070 else
6071 cursor_cleared_p = 0;
6072
6073 /* Find the first row intersecting the rectangle R. */
6074 for (row = w->current_matrix->rows;
6075 row->enabled_p;
6076 ++row)
6077 {
6078 int y0 = row->y;
6079 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6080
6081 if ((y0 >= r.y && y0 < r.y + r.height)
6082 || (y1 > r.y && y1 < r.y + r.height)
6083 || (r.y >= y0 && r.y < y1)
6084 || (r.y + r.height > y0 && r.y + r.height < y1))
6085 {
6086 if (expose_line (w, row, &r))
6087 mouse_face_overwritten_p = 1;
6088 }
6089
6090 if (y1 >= yb)
6091 break;
6092 }
6093
6094 /* Display the mode line if there is one. */
6095 if (WINDOW_WANTS_MODELINE_P (w)
6096 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6097 row->enabled_p)
6098 && row->y < r.y + r.height)
6099 {
6100 if (expose_line (w, row, &r))
6101 mouse_face_overwritten_p = 1;
6102 }
6103
6104 if (!w->pseudo_window_p)
6105 {
6106 /* Draw border between windows. */
6107 x_draw_vertical_border (w);
6108
6109 /* Turn the cursor on again. */
6110 if (cursor_cleared_p)
6111 x_update_window_cursor (w, 1);
6112 }
6113 }
6114
6115 return mouse_face_overwritten_p;
6116 }
6117
6118
6119 /* Determine the intersection of two rectangles R1 and R2. Return
6120 the intersection in *RESULT. Value is non-zero if RESULT is not
6121 empty. */
6122
6123 static int
6124 x_intersect_rectangles (r1, r2, result)
6125 XRectangle *r1, *r2, *result;
6126 {
6127 XRectangle *left, *right;
6128 XRectangle *upper, *lower;
6129 int intersection_p = 0;
6130
6131 /* Rearrange so that R1 is the left-most rectangle. */
6132 if (r1->x < r2->x)
6133 left = r1, right = r2;
6134 else
6135 left = r2, right = r1;
6136
6137 /* X0 of the intersection is right.x0, if this is inside R1,
6138 otherwise there is no intersection. */
6139 if (right->x <= left->x + left->width)
6140 {
6141 result->x = right->x;
6142
6143 /* The right end of the intersection is the minimum of the
6144 the right ends of left and right. */
6145 result->width = (min (left->x + left->width, right->x + right->width)
6146 - result->x);
6147
6148 /* Same game for Y. */
6149 if (r1->y < r2->y)
6150 upper = r1, lower = r2;
6151 else
6152 upper = r2, lower = r1;
6153
6154 /* The upper end of the intersection is lower.y0, if this is inside
6155 of upper. Otherwise, there is no intersection. */
6156 if (lower->y <= upper->y + upper->height)
6157 {
6158 result->y = lower->y;
6159
6160 /* The lower end of the intersection is the minimum of the lower
6161 ends of upper and lower. */
6162 result->height = (min (lower->y + lower->height,
6163 upper->y + upper->height)
6164 - result->y);
6165 intersection_p = 1;
6166 }
6167 }
6168
6169 return intersection_p;
6170 }
6171
6172
6173
6174
6175 \f
6176 static void
6177 frame_highlight (f)
6178 struct frame *f;
6179 {
6180 /* We used to only do this if Vx_no_window_manager was non-nil, but
6181 the ICCCM (section 4.1.6) says that the window's border pixmap
6182 and border pixel are window attributes which are "private to the
6183 client", so we can always change it to whatever we want. */
6184 BLOCK_INPUT;
6185 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6186 f->output_data.x->border_pixel);
6187 UNBLOCK_INPUT;
6188 x_update_cursor (f, 1);
6189 }
6190
6191 static void
6192 frame_unhighlight (f)
6193 struct frame *f;
6194 {
6195 /* We used to only do this if Vx_no_window_manager was non-nil, but
6196 the ICCCM (section 4.1.6) says that the window's border pixmap
6197 and border pixel are window attributes which are "private to the
6198 client", so we can always change it to whatever we want. */
6199 BLOCK_INPUT;
6200 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6201 f->output_data.x->border_tile);
6202 UNBLOCK_INPUT;
6203 x_update_cursor (f, 1);
6204 }
6205
6206 /* The focus has changed. Update the frames as necessary to reflect
6207 the new situation. Note that we can't change the selected frame
6208 here, because the Lisp code we are interrupting might become confused.
6209 Each event gets marked with the frame in which it occurred, so the
6210 Lisp code can tell when the switch took place by examining the events. */
6211
6212 static void
6213 x_new_focus_frame (dpyinfo, frame)
6214 struct x_display_info *dpyinfo;
6215 struct frame *frame;
6216 {
6217 struct frame *old_focus = dpyinfo->x_focus_frame;
6218
6219 if (frame != dpyinfo->x_focus_frame)
6220 {
6221 /* Set this before calling other routines, so that they see
6222 the correct value of x_focus_frame. */
6223 dpyinfo->x_focus_frame = frame;
6224
6225 if (old_focus && old_focus->auto_lower)
6226 x_lower_frame (old_focus);
6227
6228 #if 0
6229 selected_frame = frame;
6230 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6231 selected_frame);
6232 Fselect_window (selected_frame->selected_window);
6233 choose_minibuf_frame ();
6234 #endif /* ! 0 */
6235
6236 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6237 pending_autoraise_frame = dpyinfo->x_focus_frame;
6238 else
6239 pending_autoraise_frame = 0;
6240 }
6241
6242 x_frame_rehighlight (dpyinfo);
6243 }
6244
6245 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6246
6247 void
6248 x_mouse_leave (dpyinfo)
6249 struct x_display_info *dpyinfo;
6250 {
6251 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6252 }
6253
6254 /* The focus has changed, or we have redirected a frame's focus to
6255 another frame (this happens when a frame uses a surrogate
6256 mini-buffer frame). Shift the highlight as appropriate.
6257
6258 The FRAME argument doesn't necessarily have anything to do with which
6259 frame is being highlighted or un-highlighted; we only use it to find
6260 the appropriate X display info. */
6261
6262 static void
6263 XTframe_rehighlight (frame)
6264 struct frame *frame;
6265 {
6266 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6267 }
6268
6269 static void
6270 x_frame_rehighlight (dpyinfo)
6271 struct x_display_info *dpyinfo;
6272 {
6273 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6274
6275 if (dpyinfo->x_focus_frame)
6276 {
6277 dpyinfo->x_highlight_frame
6278 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6279 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6280 : dpyinfo->x_focus_frame);
6281 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6282 {
6283 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6284 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6285 }
6286 }
6287 else
6288 dpyinfo->x_highlight_frame = 0;
6289
6290 if (dpyinfo->x_highlight_frame != old_highlight)
6291 {
6292 if (old_highlight)
6293 frame_unhighlight (old_highlight);
6294 if (dpyinfo->x_highlight_frame)
6295 frame_highlight (dpyinfo->x_highlight_frame);
6296 }
6297 }
6298
6299
6300 \f
6301 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6302
6303 /* Initialize mode_switch_bit and modifier_meaning. */
6304 static void
6305 x_find_modifier_meanings (dpyinfo)
6306 struct x_display_info *dpyinfo;
6307 {
6308 int min_code, max_code;
6309 KeySym *syms;
6310 int syms_per_code;
6311 XModifierKeymap *mods;
6312
6313 dpyinfo->meta_mod_mask = 0;
6314 dpyinfo->shift_lock_mask = 0;
6315 dpyinfo->alt_mod_mask = 0;
6316 dpyinfo->super_mod_mask = 0;
6317 dpyinfo->hyper_mod_mask = 0;
6318
6319 #ifdef HAVE_X11R4
6320 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6321 #else
6322 min_code = dpyinfo->display->min_keycode;
6323 max_code = dpyinfo->display->max_keycode;
6324 #endif
6325
6326 syms = XGetKeyboardMapping (dpyinfo->display,
6327 min_code, max_code - min_code + 1,
6328 &syms_per_code);
6329 mods = XGetModifierMapping (dpyinfo->display);
6330
6331 /* Scan the modifier table to see which modifier bits the Meta and
6332 Alt keysyms are on. */
6333 {
6334 int row, col; /* The row and column in the modifier table. */
6335
6336 for (row = 3; row < 8; row++)
6337 for (col = 0; col < mods->max_keypermod; col++)
6338 {
6339 KeyCode code
6340 = mods->modifiermap[(row * mods->max_keypermod) + col];
6341
6342 /* Zeroes are used for filler. Skip them. */
6343 if (code == 0)
6344 continue;
6345
6346 /* Are any of this keycode's keysyms a meta key? */
6347 {
6348 int code_col;
6349
6350 for (code_col = 0; code_col < syms_per_code; code_col++)
6351 {
6352 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6353
6354 switch (sym)
6355 {
6356 case XK_Meta_L:
6357 case XK_Meta_R:
6358 dpyinfo->meta_mod_mask |= (1 << row);
6359 break;
6360
6361 case XK_Alt_L:
6362 case XK_Alt_R:
6363 dpyinfo->alt_mod_mask |= (1 << row);
6364 break;
6365
6366 case XK_Hyper_L:
6367 case XK_Hyper_R:
6368 dpyinfo->hyper_mod_mask |= (1 << row);
6369 break;
6370
6371 case XK_Super_L:
6372 case XK_Super_R:
6373 dpyinfo->super_mod_mask |= (1 << row);
6374 break;
6375
6376 case XK_Shift_Lock:
6377 /* Ignore this if it's not on the lock modifier. */
6378 if ((1 << row) == LockMask)
6379 dpyinfo->shift_lock_mask = LockMask;
6380 break;
6381 }
6382 }
6383 }
6384 }
6385 }
6386
6387 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6388 if (! dpyinfo->meta_mod_mask)
6389 {
6390 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6391 dpyinfo->alt_mod_mask = 0;
6392 }
6393
6394 /* If some keys are both alt and meta,
6395 make them just meta, not alt. */
6396 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6397 {
6398 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6399 }
6400
6401 XFree ((char *) syms);
6402 XFreeModifiermap (mods);
6403 }
6404
6405 /* Convert between the modifier bits X uses and the modifier bits
6406 Emacs uses. */
6407
6408 static unsigned int
6409 x_x_to_emacs_modifiers (dpyinfo, state)
6410 struct x_display_info *dpyinfo;
6411 unsigned int state;
6412 {
6413 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6414 | ((state & ControlMask) ? ctrl_modifier : 0)
6415 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6416 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6417 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6418 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6419 }
6420
6421 static unsigned int
6422 x_emacs_to_x_modifiers (dpyinfo, state)
6423 struct x_display_info *dpyinfo;
6424 unsigned int state;
6425 {
6426 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6427 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6428 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6429 | ((state & shift_modifier) ? ShiftMask : 0)
6430 | ((state & ctrl_modifier) ? ControlMask : 0)
6431 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6432 }
6433
6434 /* Convert a keysym to its name. */
6435
6436 char *
6437 x_get_keysym_name (keysym)
6438 KeySym keysym;
6439 {
6440 char *value;
6441
6442 BLOCK_INPUT;
6443 value = XKeysymToString (keysym);
6444 UNBLOCK_INPUT;
6445
6446 return value;
6447 }
6448
6449
6450 \f
6451 /* Mouse clicks and mouse movement. Rah. */
6452
6453 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6454 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6455 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6456 not force the value into range. */
6457
6458 void
6459 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6460 FRAME_PTR f;
6461 register int pix_x, pix_y;
6462 register int *x, *y;
6463 XRectangle *bounds;
6464 int noclip;
6465 {
6466 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6467 even for negative values. */
6468 if (pix_x < 0)
6469 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6470 if (pix_y < 0)
6471 pix_y -= (f)->output_data.x->line_height - 1;
6472
6473 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6474 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6475
6476 if (bounds)
6477 {
6478 bounds->width = FONT_WIDTH (f->output_data.x->font);
6479 bounds->height = f->output_data.x->line_height;
6480 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6481 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6482 }
6483
6484 if (!noclip)
6485 {
6486 if (pix_x < 0)
6487 pix_x = 0;
6488 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6489 pix_x = FRAME_WINDOW_WIDTH (f);
6490
6491 if (pix_y < 0)
6492 pix_y = 0;
6493 else if (pix_y > f->height)
6494 pix_y = f->height;
6495 }
6496
6497 *x = pix_x;
6498 *y = pix_y;
6499 }
6500
6501
6502 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6503 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6504 can't tell the positions because W's display is not up to date,
6505 return 0. */
6506
6507 int
6508 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6509 struct window *w;
6510 int hpos, vpos;
6511 int *frame_x, *frame_y;
6512 {
6513 int success_p;
6514
6515 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6516 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6517
6518 if (display_completed)
6519 {
6520 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6521 struct glyph *glyph = row->glyphs[TEXT_AREA];
6522 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6523
6524 *frame_y = row->y;
6525 *frame_x = row->x;
6526 while (glyph < end)
6527 {
6528 *frame_x += glyph->pixel_width;
6529 ++glyph;
6530 }
6531
6532 success_p = 1;
6533 }
6534 else
6535 {
6536 *frame_y = *frame_x = 0;
6537 success_p = 0;
6538 }
6539
6540 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6541 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6542 return success_p;
6543 }
6544
6545
6546 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6547
6548 If the event is a button press, then note that we have grabbed
6549 the mouse. */
6550
6551 static Lisp_Object
6552 construct_mouse_click (result, event, f)
6553 struct input_event *result;
6554 XButtonEvent *event;
6555 struct frame *f;
6556 {
6557 /* Make the event type no_event; we'll change that when we decide
6558 otherwise. */
6559 result->kind = mouse_click;
6560 result->code = event->button - Button1;
6561 result->timestamp = event->time;
6562 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6563 event->state)
6564 | (event->type == ButtonRelease
6565 ? up_modifier
6566 : down_modifier));
6567
6568 XSETINT (result->x, event->x);
6569 XSETINT (result->y, event->y);
6570 XSETFRAME (result->frame_or_window, f);
6571 result->arg = Qnil;
6572 return Qnil;
6573 }
6574
6575 \f
6576 /* Function to report a mouse movement to the mainstream Emacs code.
6577 The input handler calls this.
6578
6579 We have received a mouse movement event, which is given in *event.
6580 If the mouse is over a different glyph than it was last time, tell
6581 the mainstream emacs code by setting mouse_moved. If not, ask for
6582 another motion event, so we can check again the next time it moves. */
6583
6584 static XMotionEvent last_mouse_motion_event;
6585 static Lisp_Object last_mouse_motion_frame;
6586
6587 static void
6588 note_mouse_movement (frame, event)
6589 FRAME_PTR frame;
6590 XMotionEvent *event;
6591 {
6592 last_mouse_movement_time = event->time;
6593 last_mouse_motion_event = *event;
6594 XSETFRAME (last_mouse_motion_frame, frame);
6595
6596 if (event->window != FRAME_X_WINDOW (frame))
6597 {
6598 frame->mouse_moved = 1;
6599 last_mouse_scroll_bar = Qnil;
6600 note_mouse_highlight (frame, -1, -1);
6601 }
6602
6603 /* Has the mouse moved off the glyph it was on at the last sighting? */
6604 else if (event->x < last_mouse_glyph.x
6605 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6606 || event->y < last_mouse_glyph.y
6607 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6608 {
6609 frame->mouse_moved = 1;
6610 last_mouse_scroll_bar = Qnil;
6611 note_mouse_highlight (frame, event->x, event->y);
6612 }
6613 }
6614
6615 /* This is used for debugging, to turn off note_mouse_highlight. */
6616
6617 int disable_mouse_highlight;
6618
6619
6620 \f
6621 /************************************************************************
6622 Mouse Face
6623 ************************************************************************/
6624
6625 /* Find the glyph under window-relative coordinates X/Y in window W.
6626 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6627 strings. Return in *HPOS and *VPOS the row and column number of
6628 the glyph found. Return in *AREA the glyph area containing X.
6629 Value is a pointer to the glyph found or null if X/Y is not on
6630 text, or we can't tell because W's current matrix is not up to
6631 date. */
6632
6633 static struct glyph *
6634 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6635 struct window *w;
6636 int x, y;
6637 int *hpos, *vpos, *area;
6638 int buffer_only_p;
6639 {
6640 struct glyph *glyph, *end;
6641 struct glyph_row *row = NULL;
6642 int x0, i, left_area_width;
6643
6644 /* Find row containing Y. Give up if some row is not enabled. */
6645 for (i = 0; i < w->current_matrix->nrows; ++i)
6646 {
6647 row = MATRIX_ROW (w->current_matrix, i);
6648 if (!row->enabled_p)
6649 return NULL;
6650 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6651 break;
6652 }
6653
6654 *vpos = i;
6655 *hpos = 0;
6656
6657 /* Give up if Y is not in the window. */
6658 if (i == w->current_matrix->nrows)
6659 return NULL;
6660
6661 /* Get the glyph area containing X. */
6662 if (w->pseudo_window_p)
6663 {
6664 *area = TEXT_AREA;
6665 x0 = 0;
6666 }
6667 else
6668 {
6669 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6670 if (x < left_area_width)
6671 {
6672 *area = LEFT_MARGIN_AREA;
6673 x0 = 0;
6674 }
6675 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6676 {
6677 *area = TEXT_AREA;
6678 x0 = row->x + left_area_width;
6679 }
6680 else
6681 {
6682 *area = RIGHT_MARGIN_AREA;
6683 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6684 }
6685 }
6686
6687 /* Find glyph containing X. */
6688 glyph = row->glyphs[*area];
6689 end = glyph + row->used[*area];
6690 while (glyph < end)
6691 {
6692 if (x < x0 + glyph->pixel_width)
6693 {
6694 if (w->pseudo_window_p)
6695 break;
6696 else if (!buffer_only_p || BUFFERP (glyph->object))
6697 break;
6698 }
6699
6700 x0 += glyph->pixel_width;
6701 ++glyph;
6702 }
6703
6704 if (glyph == end)
6705 return NULL;
6706
6707 *hpos = glyph - row->glyphs[*area];
6708 return glyph;
6709 }
6710
6711
6712 /* Convert frame-relative x/y to coordinates relative to window W.
6713 Takes pseudo-windows into account. */
6714
6715 static void
6716 frame_to_window_pixel_xy (w, x, y)
6717 struct window *w;
6718 int *x, *y;
6719 {
6720 if (w->pseudo_window_p)
6721 {
6722 /* A pseudo-window is always full-width, and starts at the
6723 left edge of the frame, plus a frame border. */
6724 struct frame *f = XFRAME (w->frame);
6725 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6726 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6727 }
6728 else
6729 {
6730 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6731 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6732 }
6733 }
6734
6735
6736 /* Take proper action when mouse has moved to the mode or header line of
6737 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6738 mode line. X is relative to the start of the text display area of
6739 W, so the width of fringes and scroll bars must be subtracted
6740 to get a position relative to the start of the mode line. */
6741
6742 static void
6743 note_mode_line_highlight (w, x, mode_line_p)
6744 struct window *w;
6745 int x, mode_line_p;
6746 {
6747 struct frame *f = XFRAME (w->frame);
6748 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6749 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6750 struct glyph_row *row;
6751
6752 if (mode_line_p)
6753 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6754 else
6755 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6756
6757 if (row->enabled_p)
6758 {
6759 struct glyph *glyph, *end;
6760 Lisp_Object help, map;
6761 int x0;
6762
6763 /* Find the glyph under X. */
6764 glyph = row->glyphs[TEXT_AREA];
6765 end = glyph + row->used[TEXT_AREA];
6766 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6767 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6768
6769 while (glyph < end
6770 && x >= x0 + glyph->pixel_width)
6771 {
6772 x0 += glyph->pixel_width;
6773 ++glyph;
6774 }
6775
6776 if (glyph < end
6777 && STRINGP (glyph->object)
6778 && XSTRING (glyph->object)->intervals
6779 && glyph->charpos >= 0
6780 && glyph->charpos < XSTRING (glyph->object)->size)
6781 {
6782 /* If we're on a string with `help-echo' text property,
6783 arrange for the help to be displayed. This is done by
6784 setting the global variable help_echo to the help string. */
6785 help = Fget_text_property (make_number (glyph->charpos),
6786 Qhelp_echo, glyph->object);
6787 if (!NILP (help))
6788 {
6789 help_echo = help;
6790 XSETWINDOW (help_echo_window, w);
6791 help_echo_object = glyph->object;
6792 help_echo_pos = glyph->charpos;
6793 }
6794
6795 /* Change the mouse pointer according to what is under X/Y. */
6796 map = Fget_text_property (make_number (glyph->charpos),
6797 Qlocal_map, glyph->object);
6798 if (KEYMAPP (map))
6799 cursor = f->output_data.x->nontext_cursor;
6800 else
6801 {
6802 map = Fget_text_property (make_number (glyph->charpos),
6803 Qkeymap, glyph->object);
6804 if (KEYMAPP (map))
6805 cursor = f->output_data.x->nontext_cursor;
6806 }
6807 }
6808 }
6809
6810 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6811 }
6812
6813
6814 /* Take proper action when the mouse has moved to position X, Y on
6815 frame F as regards highlighting characters that have mouse-face
6816 properties. Also de-highlighting chars where the mouse was before.
6817 X and Y can be negative or out of range. */
6818
6819 static void
6820 note_mouse_highlight (f, x, y)
6821 struct frame *f;
6822 int x, y;
6823 {
6824 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6825 int portion;
6826 Lisp_Object window;
6827 struct window *w;
6828 Cursor cursor = None;
6829 struct buffer *b;
6830
6831 /* When a menu is active, don't highlight because this looks odd. */
6832 #ifdef USE_X_TOOLKIT
6833 if (popup_activated ())
6834 return;
6835 #endif
6836
6837 if (disable_mouse_highlight
6838 || !f->glyphs_initialized_p)
6839 return;
6840
6841 dpyinfo->mouse_face_mouse_x = x;
6842 dpyinfo->mouse_face_mouse_y = y;
6843 dpyinfo->mouse_face_mouse_frame = f;
6844
6845 if (dpyinfo->mouse_face_defer)
6846 return;
6847
6848 if (gc_in_progress)
6849 {
6850 dpyinfo->mouse_face_deferred_gc = 1;
6851 return;
6852 }
6853
6854 /* Which window is that in? */
6855 window = window_from_coordinates (f, x, y, &portion, 1);
6856
6857 /* If we were displaying active text in another window, clear that. */
6858 if (! EQ (window, dpyinfo->mouse_face_window))
6859 clear_mouse_face (dpyinfo);
6860
6861 /* Not on a window -> return. */
6862 if (!WINDOWP (window))
6863 return;
6864
6865 /* Convert to window-relative pixel coordinates. */
6866 w = XWINDOW (window);
6867 frame_to_window_pixel_xy (w, &x, &y);
6868
6869 /* Handle tool-bar window differently since it doesn't display a
6870 buffer. */
6871 if (EQ (window, f->tool_bar_window))
6872 {
6873 note_tool_bar_highlight (f, x, y);
6874 return;
6875 }
6876
6877 /* Mouse is on the mode or header line? */
6878 if (portion == 1 || portion == 3)
6879 {
6880 note_mode_line_highlight (w, x, portion == 1);
6881 return;
6882 }
6883
6884 if (portion == 2)
6885 cursor = f->output_data.x->horizontal_drag_cursor;
6886 else
6887 cursor = f->output_data.x->text_cursor;
6888
6889 /* Are we in a window whose display is up to date?
6890 And verify the buffer's text has not changed. */
6891 b = XBUFFER (w->buffer);
6892 if (/* Within text portion of the window. */
6893 portion == 0
6894 && EQ (w->window_end_valid, w->buffer)
6895 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6896 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6897 {
6898 int hpos, vpos, pos, i, area;
6899 struct glyph *glyph;
6900 Lisp_Object object;
6901 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6902 Lisp_Object *overlay_vec = NULL;
6903 int len, noverlays;
6904 struct buffer *obuf;
6905 int obegv, ozv, same_region;
6906
6907 /* Find the glyph under X/Y. */
6908 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6909
6910 /* Clear mouse face if X/Y not over text. */
6911 if (glyph == NULL
6912 || area != TEXT_AREA
6913 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6914 {
6915 if (clear_mouse_face (dpyinfo))
6916 cursor = None;
6917 goto set_cursor;
6918 }
6919
6920 pos = glyph->charpos;
6921 object = glyph->object;
6922 if (!STRINGP (object) && !BUFFERP (object))
6923 goto set_cursor;
6924
6925 /* If we get an out-of-range value, return now; avoid an error. */
6926 if (BUFFERP (object) && pos > BUF_Z (b))
6927 goto set_cursor;
6928
6929 /* Make the window's buffer temporarily current for
6930 overlays_at and compute_char_face. */
6931 obuf = current_buffer;
6932 current_buffer = b;
6933 obegv = BEGV;
6934 ozv = ZV;
6935 BEGV = BEG;
6936 ZV = Z;
6937
6938 /* Is this char mouse-active or does it have help-echo? */
6939 position = make_number (pos);
6940
6941 if (BUFFERP (object))
6942 {
6943 /* Put all the overlays we want in a vector in overlay_vec.
6944 Store the length in len. If there are more than 10, make
6945 enough space for all, and try again. */
6946 len = 10;
6947 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6948 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6949 if (noverlays > len)
6950 {
6951 len = noverlays;
6952 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6953 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6954 }
6955
6956 /* Sort overlays into increasing priority order. */
6957 noverlays = sort_overlays (overlay_vec, noverlays, w);
6958 }
6959 else
6960 noverlays = 0;
6961
6962 same_region = (EQ (window, dpyinfo->mouse_face_window)
6963 && vpos >= dpyinfo->mouse_face_beg_row
6964 && vpos <= dpyinfo->mouse_face_end_row
6965 && (vpos > dpyinfo->mouse_face_beg_row
6966 || hpos >= dpyinfo->mouse_face_beg_col)
6967 && (vpos < dpyinfo->mouse_face_end_row
6968 || hpos < dpyinfo->mouse_face_end_col
6969 || dpyinfo->mouse_face_past_end));
6970
6971 if (same_region)
6972 cursor = None;
6973
6974 /* Check mouse-face highlighting. */
6975 if (! same_region
6976 /* If there exists an overlay with mouse-face overlapping
6977 the one we are currently highlighting, we have to
6978 check if we enter the overlapping overlay, and then
6979 highlight only that. */
6980 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6981 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6982 {
6983 /* Find the highest priority overlay that has a mouse-face
6984 property. */
6985 overlay = Qnil;
6986 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6987 {
6988 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6989 if (!NILP (mouse_face))
6990 overlay = overlay_vec[i];
6991 }
6992
6993 /* If we're actually highlighting the same overlay as
6994 before, there's no need to do that again. */
6995 if (!NILP (overlay)
6996 && EQ (overlay, dpyinfo->mouse_face_overlay))
6997 goto check_help_echo;
6998
6999 dpyinfo->mouse_face_overlay = overlay;
7000
7001 /* Clear the display of the old active region, if any. */
7002 if (clear_mouse_face (dpyinfo))
7003 cursor = None;
7004
7005 /* If no overlay applies, get a text property. */
7006 if (NILP (overlay))
7007 mouse_face = Fget_text_property (position, Qmouse_face, object);
7008
7009 /* Handle the overlay case. */
7010 if (!NILP (overlay))
7011 {
7012 /* Find the range of text around this char that
7013 should be active. */
7014 Lisp_Object before, after;
7015 int ignore;
7016
7017 before = Foverlay_start (overlay);
7018 after = Foverlay_end (overlay);
7019 /* Record this as the current active region. */
7020 fast_find_position (w, XFASTINT (before),
7021 &dpyinfo->mouse_face_beg_col,
7022 &dpyinfo->mouse_face_beg_row,
7023 &dpyinfo->mouse_face_beg_x,
7024 &dpyinfo->mouse_face_beg_y, Qnil);
7025
7026 dpyinfo->mouse_face_past_end
7027 = !fast_find_position (w, XFASTINT (after),
7028 &dpyinfo->mouse_face_end_col,
7029 &dpyinfo->mouse_face_end_row,
7030 &dpyinfo->mouse_face_end_x,
7031 &dpyinfo->mouse_face_end_y, Qnil);
7032 dpyinfo->mouse_face_window = window;
7033 dpyinfo->mouse_face_face_id
7034 = face_at_buffer_position (w, pos, 0, 0,
7035 &ignore, pos + 1, 1);
7036
7037 /* Display it as active. */
7038 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7039 cursor = None;
7040 }
7041 /* Handle the text property case. */
7042 else if (!NILP (mouse_face) && BUFFERP (object))
7043 {
7044 /* Find the range of text around this char that
7045 should be active. */
7046 Lisp_Object before, after, beginning, end;
7047 int ignore;
7048
7049 beginning = Fmarker_position (w->start);
7050 end = make_number (BUF_Z (XBUFFER (object))
7051 - XFASTINT (w->window_end_pos));
7052 before
7053 = Fprevious_single_property_change (make_number (pos + 1),
7054 Qmouse_face,
7055 object, beginning);
7056 after
7057 = Fnext_single_property_change (position, Qmouse_face,
7058 object, end);
7059
7060 /* Record this as the current active region. */
7061 fast_find_position (w, XFASTINT (before),
7062 &dpyinfo->mouse_face_beg_col,
7063 &dpyinfo->mouse_face_beg_row,
7064 &dpyinfo->mouse_face_beg_x,
7065 &dpyinfo->mouse_face_beg_y, Qnil);
7066 dpyinfo->mouse_face_past_end
7067 = !fast_find_position (w, XFASTINT (after),
7068 &dpyinfo->mouse_face_end_col,
7069 &dpyinfo->mouse_face_end_row,
7070 &dpyinfo->mouse_face_end_x,
7071 &dpyinfo->mouse_face_end_y, Qnil);
7072 dpyinfo->mouse_face_window = window;
7073
7074 if (BUFFERP (object))
7075 dpyinfo->mouse_face_face_id
7076 = face_at_buffer_position (w, pos, 0, 0,
7077 &ignore, pos + 1, 1);
7078
7079 /* Display it as active. */
7080 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7081 cursor = None;
7082 }
7083 else if (!NILP (mouse_face) && STRINGP (object))
7084 {
7085 Lisp_Object b, e;
7086 int ignore;
7087
7088 b = Fprevious_single_property_change (make_number (pos + 1),
7089 Qmouse_face,
7090 object, Qnil);
7091 e = Fnext_single_property_change (position, Qmouse_face,
7092 object, Qnil);
7093 if (NILP (b))
7094 b = make_number (0);
7095 if (NILP (e))
7096 e = make_number (XSTRING (object)->size - 1);
7097 fast_find_string_pos (w, XINT (b), object,
7098 &dpyinfo->mouse_face_beg_col,
7099 &dpyinfo->mouse_face_beg_row,
7100 &dpyinfo->mouse_face_beg_x,
7101 &dpyinfo->mouse_face_beg_y, 0);
7102 fast_find_string_pos (w, XINT (e), object,
7103 &dpyinfo->mouse_face_end_col,
7104 &dpyinfo->mouse_face_end_row,
7105 &dpyinfo->mouse_face_end_x,
7106 &dpyinfo->mouse_face_end_y, 1);
7107 dpyinfo->mouse_face_past_end = 0;
7108 dpyinfo->mouse_face_window = window;
7109 dpyinfo->mouse_face_face_id
7110 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7111 glyph->face_id, 1);
7112 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7113 cursor = None;
7114 }
7115 else if (STRINGP (object) && NILP (mouse_face))
7116 {
7117 /* A string which doesn't have mouse-face, but
7118 the text ``under'' it might have. */
7119 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7120 int start = MATRIX_ROW_START_CHARPOS (r);
7121
7122 pos = string_buffer_position (w, object, start);
7123 if (pos > 0)
7124 mouse_face = get_char_property_and_overlay (make_number (pos),
7125 Qmouse_face,
7126 w->buffer,
7127 &overlay);
7128 if (!NILP (mouse_face) && !NILP (overlay))
7129 {
7130 Lisp_Object before = Foverlay_start (overlay);
7131 Lisp_Object after = Foverlay_end (overlay);
7132 Lisp_Object ignore;
7133
7134 /* Note that we might not be able to find position
7135 BEFORE in the glyph matrix if the overlay is
7136 entirely covered by a `display' property. In
7137 this case, we overshoot. So let's stop in
7138 the glyph matrix before glyphs for OBJECT. */
7139 fast_find_position (w, XFASTINT (before),
7140 &dpyinfo->mouse_face_beg_col,
7141 &dpyinfo->mouse_face_beg_row,
7142 &dpyinfo->mouse_face_beg_x,
7143 &dpyinfo->mouse_face_beg_y,
7144 object);
7145
7146 dpyinfo->mouse_face_past_end
7147 = !fast_find_position (w, XFASTINT (after),
7148 &dpyinfo->mouse_face_end_col,
7149 &dpyinfo->mouse_face_end_row,
7150 &dpyinfo->mouse_face_end_x,
7151 &dpyinfo->mouse_face_end_y,
7152 Qnil);
7153 dpyinfo->mouse_face_window = window;
7154 dpyinfo->mouse_face_face_id
7155 = face_at_buffer_position (w, pos, 0, 0,
7156 &ignore, pos + 1, 1);
7157
7158 /* Display it as active. */
7159 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7160 cursor = None;
7161 }
7162 }
7163 }
7164
7165 check_help_echo:
7166
7167 /* Look for a `help-echo' property. */
7168 {
7169 Lisp_Object help, overlay;
7170
7171 /* Check overlays first. */
7172 help = overlay = Qnil;
7173 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7174 {
7175 overlay = overlay_vec[i];
7176 help = Foverlay_get (overlay, Qhelp_echo);
7177 }
7178
7179 if (!NILP (help))
7180 {
7181 help_echo = help;
7182 help_echo_window = window;
7183 help_echo_object = overlay;
7184 help_echo_pos = pos;
7185 }
7186 else
7187 {
7188 Lisp_Object object = glyph->object;
7189 int charpos = glyph->charpos;
7190
7191 /* Try text properties. */
7192 if (STRINGP (object)
7193 && charpos >= 0
7194 && charpos < XSTRING (object)->size)
7195 {
7196 help = Fget_text_property (make_number (charpos),
7197 Qhelp_echo, object);
7198 if (NILP (help))
7199 {
7200 /* If the string itself doesn't specify a help-echo,
7201 see if the buffer text ``under'' it does. */
7202 struct glyph_row *r
7203 = MATRIX_ROW (w->current_matrix, vpos);
7204 int start = MATRIX_ROW_START_CHARPOS (r);
7205 int pos = string_buffer_position (w, object, start);
7206 if (pos > 0)
7207 {
7208 help = Fget_char_property (make_number (pos),
7209 Qhelp_echo, w->buffer);
7210 if (!NILP (help))
7211 {
7212 charpos = pos;
7213 object = w->buffer;
7214 }
7215 }
7216 }
7217 }
7218 else if (BUFFERP (object)
7219 && charpos >= BEGV
7220 && charpos < ZV)
7221 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7222 object);
7223
7224 if (!NILP (help))
7225 {
7226 help_echo = help;
7227 help_echo_window = window;
7228 help_echo_object = object;
7229 help_echo_pos = charpos;
7230 }
7231 }
7232 }
7233
7234 BEGV = obegv;
7235 ZV = ozv;
7236 current_buffer = obuf;
7237 }
7238
7239 set_cursor:
7240
7241 if (cursor != None)
7242 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7243 }
7244
7245 static void
7246 redo_mouse_highlight ()
7247 {
7248 if (!NILP (last_mouse_motion_frame)
7249 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7250 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7251 last_mouse_motion_event.x,
7252 last_mouse_motion_event.y);
7253 }
7254
7255
7256 \f
7257 /***********************************************************************
7258 Tool-bars
7259 ***********************************************************************/
7260
7261 static int x_tool_bar_item P_ ((struct frame *, int, int,
7262 struct glyph **, int *, int *, int *));
7263
7264 /* Tool-bar item index of the item on which a mouse button was pressed
7265 or -1. */
7266
7267 static int last_tool_bar_item;
7268
7269
7270 /* Get information about the tool-bar item at position X/Y on frame F.
7271 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7272 the current matrix of the tool-bar window of F, or NULL if not
7273 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7274 item in F->tool_bar_items. Value is
7275
7276 -1 if X/Y is not on a tool-bar item
7277 0 if X/Y is on the same item that was highlighted before.
7278 1 otherwise. */
7279
7280 static int
7281 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7282 struct frame *f;
7283 int x, y;
7284 struct glyph **glyph;
7285 int *hpos, *vpos, *prop_idx;
7286 {
7287 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7288 struct window *w = XWINDOW (f->tool_bar_window);
7289 int area;
7290
7291 /* Find the glyph under X/Y. */
7292 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7293 if (*glyph == NULL)
7294 return -1;
7295
7296 /* Get the start of this tool-bar item's properties in
7297 f->tool_bar_items. */
7298 if (!tool_bar_item_info (f, *glyph, prop_idx))
7299 return -1;
7300
7301 /* Is mouse on the highlighted item? */
7302 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7303 && *vpos >= dpyinfo->mouse_face_beg_row
7304 && *vpos <= dpyinfo->mouse_face_end_row
7305 && (*vpos > dpyinfo->mouse_face_beg_row
7306 || *hpos >= dpyinfo->mouse_face_beg_col)
7307 && (*vpos < dpyinfo->mouse_face_end_row
7308 || *hpos < dpyinfo->mouse_face_end_col
7309 || dpyinfo->mouse_face_past_end))
7310 return 0;
7311
7312 return 1;
7313 }
7314
7315
7316 /* Handle mouse button event on the tool-bar of frame F, at
7317 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7318 or ButtonRelase. */
7319
7320 static void
7321 x_handle_tool_bar_click (f, button_event)
7322 struct frame *f;
7323 XButtonEvent *button_event;
7324 {
7325 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7326 struct window *w = XWINDOW (f->tool_bar_window);
7327 int hpos, vpos, prop_idx;
7328 struct glyph *glyph;
7329 Lisp_Object enabled_p;
7330 int x = button_event->x;
7331 int y = button_event->y;
7332
7333 /* If not on the highlighted tool-bar item, return. */
7334 frame_to_window_pixel_xy (w, &x, &y);
7335 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7336 return;
7337
7338 /* If item is disabled, do nothing. */
7339 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7340 if (NILP (enabled_p))
7341 return;
7342
7343 if (button_event->type == ButtonPress)
7344 {
7345 /* Show item in pressed state. */
7346 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7347 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7348 last_tool_bar_item = prop_idx;
7349 }
7350 else
7351 {
7352 Lisp_Object key, frame;
7353 struct input_event event;
7354
7355 /* Show item in released state. */
7356 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7357 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7358
7359 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7360
7361 XSETFRAME (frame, f);
7362 event.kind = TOOL_BAR_EVENT;
7363 event.frame_or_window = frame;
7364 event.arg = frame;
7365 kbd_buffer_store_event (&event);
7366
7367 event.kind = TOOL_BAR_EVENT;
7368 event.frame_or_window = frame;
7369 event.arg = key;
7370 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7371 button_event->state);
7372 kbd_buffer_store_event (&event);
7373 last_tool_bar_item = -1;
7374 }
7375 }
7376
7377
7378 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7379 tool-bar window-relative coordinates X/Y. Called from
7380 note_mouse_highlight. */
7381
7382 static void
7383 note_tool_bar_highlight (f, x, y)
7384 struct frame *f;
7385 int x, y;
7386 {
7387 Lisp_Object window = f->tool_bar_window;
7388 struct window *w = XWINDOW (window);
7389 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7390 int hpos, vpos;
7391 struct glyph *glyph;
7392 struct glyph_row *row;
7393 int i;
7394 Lisp_Object enabled_p;
7395 int prop_idx;
7396 enum draw_glyphs_face draw;
7397 int mouse_down_p, rc;
7398
7399 /* Function note_mouse_highlight is called with negative x(y
7400 values when mouse moves outside of the frame. */
7401 if (x <= 0 || y <= 0)
7402 {
7403 clear_mouse_face (dpyinfo);
7404 return;
7405 }
7406
7407 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7408 if (rc < 0)
7409 {
7410 /* Not on tool-bar item. */
7411 clear_mouse_face (dpyinfo);
7412 return;
7413 }
7414 else if (rc == 0)
7415 goto set_help_echo;
7416
7417 clear_mouse_face (dpyinfo);
7418
7419 /* Mouse is down, but on different tool-bar item? */
7420 mouse_down_p = (dpyinfo->grabbed
7421 && f == last_mouse_frame
7422 && FRAME_LIVE_P (f));
7423 if (mouse_down_p
7424 && last_tool_bar_item != prop_idx)
7425 return;
7426
7427 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7428 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7429
7430 /* If tool-bar item is not enabled, don't highlight it. */
7431 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7432 if (!NILP (enabled_p))
7433 {
7434 /* Compute the x-position of the glyph. In front and past the
7435 image is a space. We include this is the highlighted area. */
7436 row = MATRIX_ROW (w->current_matrix, vpos);
7437 for (i = x = 0; i < hpos; ++i)
7438 x += row->glyphs[TEXT_AREA][i].pixel_width;
7439
7440 /* Record this as the current active region. */
7441 dpyinfo->mouse_face_beg_col = hpos;
7442 dpyinfo->mouse_face_beg_row = vpos;
7443 dpyinfo->mouse_face_beg_x = x;
7444 dpyinfo->mouse_face_beg_y = row->y;
7445 dpyinfo->mouse_face_past_end = 0;
7446
7447 dpyinfo->mouse_face_end_col = hpos + 1;
7448 dpyinfo->mouse_face_end_row = vpos;
7449 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7450 dpyinfo->mouse_face_end_y = row->y;
7451 dpyinfo->mouse_face_window = window;
7452 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7453
7454 /* Display it as active. */
7455 show_mouse_face (dpyinfo, draw);
7456 dpyinfo->mouse_face_image_state = draw;
7457 }
7458
7459 set_help_echo:
7460
7461 /* Set help_echo to a help string.to display for this tool-bar item.
7462 XTread_socket does the rest. */
7463 help_echo_object = help_echo_window = Qnil;
7464 help_echo_pos = -1;
7465 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7466 if (NILP (help_echo))
7467 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7468 }
7469
7470
7471 \f
7472 /* Find the glyph matrix position of buffer position CHARPOS in window
7473 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7474 current glyphs must be up to date. If CHARPOS is above window
7475 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7476 of last line in W. In the row containing CHARPOS, stop before glyphs
7477 having STOP as object. */
7478
7479 #if 0 /* This is a version of fast_find_position that's more correct
7480 in the presence of hscrolling, for example. I didn't install
7481 it right away because the problem fixed is minor, it failed
7482 in 20.x as well, and I think it's too risky to install
7483 so near the release of 21.1. 2001-09-25 gerd. */
7484
7485 static int
7486 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7487 struct window *w;
7488 int charpos;
7489 int *hpos, *vpos, *x, *y;
7490 Lisp_Object stop;
7491 {
7492 struct glyph_row *row, *first;
7493 struct glyph *glyph, *end;
7494 int i, past_end = 0;
7495
7496 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7497 row = row_containing_pos (w, charpos, first, NULL, 0);
7498 if (row == NULL)
7499 {
7500 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7501 {
7502 *x = *y = *hpos = *vpos = 0;
7503 return 0;
7504 }
7505 else
7506 {
7507 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7508 past_end = 1;
7509 }
7510 }
7511
7512 *x = row->x;
7513 *y = row->y;
7514 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7515
7516 glyph = row->glyphs[TEXT_AREA];
7517 end = glyph + row->used[TEXT_AREA];
7518
7519 /* Skip over glyphs not having an object at the start of the row.
7520 These are special glyphs like truncation marks on terminal
7521 frames. */
7522 if (row->displays_text_p)
7523 while (glyph < end
7524 && INTEGERP (glyph->object)
7525 && !EQ (stop, glyph->object)
7526 && glyph->charpos < 0)
7527 {
7528 *x += glyph->pixel_width;
7529 ++glyph;
7530 }
7531
7532 while (glyph < end
7533 && !INTEGERP (glyph->object)
7534 && !EQ (stop, glyph->object)
7535 && (!BUFFERP (glyph->object)
7536 || glyph->charpos < charpos))
7537 {
7538 *x += glyph->pixel_width;
7539 ++glyph;
7540 }
7541
7542 *hpos = glyph - row->glyphs[TEXT_AREA];
7543 return past_end;
7544 }
7545
7546 #else /* not 0 */
7547
7548 static int
7549 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7550 struct window *w;
7551 int pos;
7552 int *hpos, *vpos, *x, *y;
7553 Lisp_Object stop;
7554 {
7555 int i;
7556 int lastcol;
7557 int maybe_next_line_p = 0;
7558 int line_start_position;
7559 int yb = window_text_bottom_y (w);
7560 struct glyph_row *row, *best_row;
7561 int row_vpos, best_row_vpos;
7562 int current_x;
7563
7564 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7565 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7566
7567 while (row->y < yb)
7568 {
7569 if (row->used[TEXT_AREA])
7570 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7571 else
7572 line_start_position = 0;
7573
7574 if (line_start_position > pos)
7575 break;
7576 /* If the position sought is the end of the buffer,
7577 don't include the blank lines at the bottom of the window. */
7578 else if (line_start_position == pos
7579 && pos == BUF_ZV (XBUFFER (w->buffer)))
7580 {
7581 maybe_next_line_p = 1;
7582 break;
7583 }
7584 else if (line_start_position > 0)
7585 {
7586 best_row = row;
7587 best_row_vpos = row_vpos;
7588 }
7589
7590 if (row->y + row->height >= yb)
7591 break;
7592
7593 ++row;
7594 ++row_vpos;
7595 }
7596
7597 /* Find the right column within BEST_ROW. */
7598 lastcol = 0;
7599 current_x = best_row->x;
7600 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7601 {
7602 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7603 int charpos = glyph->charpos;
7604
7605 if (BUFFERP (glyph->object))
7606 {
7607 if (charpos == pos)
7608 {
7609 *hpos = i;
7610 *vpos = best_row_vpos;
7611 *x = current_x;
7612 *y = best_row->y;
7613 return 1;
7614 }
7615 else if (charpos > pos)
7616 break;
7617 }
7618 else if (EQ (glyph->object, stop))
7619 break;
7620
7621 if (charpos > 0)
7622 lastcol = i;
7623 current_x += glyph->pixel_width;
7624 }
7625
7626 /* If we're looking for the end of the buffer,
7627 and we didn't find it in the line we scanned,
7628 use the start of the following line. */
7629 if (maybe_next_line_p)
7630 {
7631 ++best_row;
7632 ++best_row_vpos;
7633 lastcol = 0;
7634 current_x = best_row->x;
7635 }
7636
7637 *vpos = best_row_vpos;
7638 *hpos = lastcol + 1;
7639 *x = current_x;
7640 *y = best_row->y;
7641 return 0;
7642 }
7643
7644 #endif /* not 0 */
7645
7646
7647 /* Find the position of the the glyph for position POS in OBJECT in
7648 window W's current matrix, and return in *X/*Y the pixel
7649 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7650
7651 RIGHT_P non-zero means return the position of the right edge of the
7652 glyph, RIGHT_P zero means return the left edge position.
7653
7654 If no glyph for POS exists in the matrix, return the position of
7655 the glyph with the next smaller position that is in the matrix, if
7656 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7657 exists in the matrix, return the position of the glyph with the
7658 next larger position in OBJECT.
7659
7660 Value is non-zero if a glyph was found. */
7661
7662 static int
7663 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7664 struct window *w;
7665 int pos;
7666 Lisp_Object object;
7667 int *hpos, *vpos, *x, *y;
7668 int right_p;
7669 {
7670 int yb = window_text_bottom_y (w);
7671 struct glyph_row *r;
7672 struct glyph *best_glyph = NULL;
7673 struct glyph_row *best_row = NULL;
7674 int best_x = 0;
7675
7676 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7677 r->enabled_p && r->y < yb;
7678 ++r)
7679 {
7680 struct glyph *g = r->glyphs[TEXT_AREA];
7681 struct glyph *e = g + r->used[TEXT_AREA];
7682 int gx;
7683
7684 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7685 if (EQ (g->object, object))
7686 {
7687 if (g->charpos == pos)
7688 {
7689 best_glyph = g;
7690 best_x = gx;
7691 best_row = r;
7692 goto found;
7693 }
7694 else if (best_glyph == NULL
7695 || ((abs (g->charpos - pos)
7696 < abs (best_glyph->charpos - pos))
7697 && (right_p
7698 ? g->charpos < pos
7699 : g->charpos > pos)))
7700 {
7701 best_glyph = g;
7702 best_x = gx;
7703 best_row = r;
7704 }
7705 }
7706 }
7707
7708 found:
7709
7710 if (best_glyph)
7711 {
7712 *x = best_x;
7713 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7714
7715 if (right_p)
7716 {
7717 *x += best_glyph->pixel_width;
7718 ++*hpos;
7719 }
7720
7721 *y = best_row->y;
7722 *vpos = best_row - w->current_matrix->rows;
7723 }
7724
7725 return best_glyph != NULL;
7726 }
7727
7728
7729 /* Display the active region described by mouse_face_*
7730 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7731
7732 static void
7733 show_mouse_face (dpyinfo, draw)
7734 struct x_display_info *dpyinfo;
7735 enum draw_glyphs_face draw;
7736 {
7737 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7738 struct frame *f = XFRAME (WINDOW_FRAME (w));
7739
7740 if (/* If window is in the process of being destroyed, don't bother
7741 to do anything. */
7742 w->current_matrix != NULL
7743 /* Recognize when we are called to operate on rows that don't exist
7744 anymore. This can happen when a window is split. */
7745 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7746 {
7747 int phys_cursor_on_p = w->phys_cursor_on_p;
7748 struct glyph_row *row, *first, *last;
7749
7750 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7751 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7752
7753 for (row = first; row <= last && row->enabled_p; ++row)
7754 {
7755 int start_hpos, end_hpos, start_x;
7756
7757 /* For all but the first row, the highlight starts at column 0. */
7758 if (row == first)
7759 {
7760 start_hpos = dpyinfo->mouse_face_beg_col;
7761 start_x = dpyinfo->mouse_face_beg_x;
7762 }
7763 else
7764 {
7765 start_hpos = 0;
7766 start_x = 0;
7767 }
7768
7769 if (row == last)
7770 end_hpos = dpyinfo->mouse_face_end_col;
7771 else
7772 end_hpos = row->used[TEXT_AREA];
7773
7774 if (end_hpos > start_hpos)
7775 {
7776 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7777 start_hpos, end_hpos, draw, 0);
7778
7779 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
7780 }
7781 }
7782
7783 /* When we've written over the cursor, arrange for it to
7784 be displayed again. */
7785 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7786 x_display_cursor (w, 1,
7787 w->phys_cursor.hpos, w->phys_cursor.vpos,
7788 w->phys_cursor.x, w->phys_cursor.y);
7789 }
7790
7791 /* Change the mouse cursor. */
7792 if (draw == DRAW_NORMAL_TEXT)
7793 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7794 f->output_data.x->text_cursor);
7795 else if (draw == DRAW_MOUSE_FACE)
7796 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7797 f->output_data.x->cross_cursor);
7798 else
7799 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7800 f->output_data.x->nontext_cursor);
7801 }
7802
7803 /* Clear out the mouse-highlighted active region.
7804 Redraw it un-highlighted first. Value is non-zero if mouse
7805 face was actually drawn unhighlighted. */
7806
7807 static int
7808 clear_mouse_face (dpyinfo)
7809 struct x_display_info *dpyinfo;
7810 {
7811 int cleared = 0;
7812
7813 if (!NILP (dpyinfo->mouse_face_window))
7814 {
7815 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7816 cleared = 1;
7817 }
7818
7819 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7820 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7821 dpyinfo->mouse_face_window = Qnil;
7822 dpyinfo->mouse_face_overlay = Qnil;
7823 return cleared;
7824 }
7825
7826
7827 /* Clear any mouse-face on window W. This function is part of the
7828 redisplay interface, and is called from try_window_id and similar
7829 functions to ensure the mouse-highlight is off. */
7830
7831 static void
7832 x_clear_mouse_face (w)
7833 struct window *w;
7834 {
7835 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7836 Lisp_Object window;
7837
7838 BLOCK_INPUT;
7839 XSETWINDOW (window, w);
7840 if (EQ (window, dpyinfo->mouse_face_window))
7841 clear_mouse_face (dpyinfo);
7842 UNBLOCK_INPUT;
7843 }
7844
7845
7846 /* Just discard the mouse face information for frame F, if any.
7847 This is used when the size of F is changed. */
7848
7849 void
7850 cancel_mouse_face (f)
7851 FRAME_PTR f;
7852 {
7853 Lisp_Object window;
7854 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7855
7856 window = dpyinfo->mouse_face_window;
7857 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7858 {
7859 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7860 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7861 dpyinfo->mouse_face_window = Qnil;
7862 }
7863 }
7864
7865 \f
7866 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7867
7868
7869 /* Try to determine frame pixel position and size of the glyph under
7870 frame pixel coordinates X/Y on frame F . Return the position and
7871 size in *RECT. Value is non-zero if we could compute these
7872 values. */
7873
7874 static int
7875 glyph_rect (f, x, y, rect)
7876 struct frame *f;
7877 int x, y;
7878 XRectangle *rect;
7879 {
7880 Lisp_Object window;
7881 int part, found = 0;
7882
7883 window = window_from_coordinates (f, x, y, &part, 0);
7884 if (!NILP (window))
7885 {
7886 struct window *w = XWINDOW (window);
7887 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7888 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7889
7890 frame_to_window_pixel_xy (w, &x, &y);
7891
7892 for (; !found && r < end && r->enabled_p; ++r)
7893 if (r->y >= y)
7894 {
7895 struct glyph *g = r->glyphs[TEXT_AREA];
7896 struct glyph *end = g + r->used[TEXT_AREA];
7897 int gx;
7898
7899 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7900 if (gx >= x)
7901 {
7902 rect->width = g->pixel_width;
7903 rect->height = r->height;
7904 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7905 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7906 found = 1;
7907 }
7908 }
7909 }
7910
7911 return found;
7912 }
7913
7914
7915 /* Return the current position of the mouse.
7916 *FP should be a frame which indicates which display to ask about.
7917
7918 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7919 and *PART to the frame, window, and scroll bar part that the mouse
7920 is over. Set *X and *Y to the portion and whole of the mouse's
7921 position on the scroll bar.
7922
7923 If the mouse movement started elsewhere, set *FP to the frame the
7924 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
7925 the mouse is over.
7926
7927 Set *TIME to the server time-stamp for the time at which the mouse
7928 was at this position.
7929
7930 Don't store anything if we don't have a valid set of values to report.
7931
7932 This clears the mouse_moved flag, so we can wait for the next mouse
7933 movement. */
7934
7935 static void
7936 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7937 FRAME_PTR *fp;
7938 int insist;
7939 Lisp_Object *bar_window;
7940 enum scroll_bar_part *part;
7941 Lisp_Object *x, *y;
7942 unsigned long *time;
7943 {
7944 FRAME_PTR f1;
7945
7946 BLOCK_INPUT;
7947
7948 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7949 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7950 else
7951 {
7952 Window root;
7953 int root_x, root_y;
7954
7955 Window dummy_window;
7956 int dummy;
7957
7958 Lisp_Object frame, tail;
7959
7960 /* Clear the mouse-moved flag for every frame on this display. */
7961 FOR_EACH_FRAME (tail, frame)
7962 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7963 XFRAME (frame)->mouse_moved = 0;
7964
7965 last_mouse_scroll_bar = Qnil;
7966
7967 /* Figure out which root window we're on. */
7968 XQueryPointer (FRAME_X_DISPLAY (*fp),
7969 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7970
7971 /* The root window which contains the pointer. */
7972 &root,
7973
7974 /* Trash which we can't trust if the pointer is on
7975 a different screen. */
7976 &dummy_window,
7977
7978 /* The position on that root window. */
7979 &root_x, &root_y,
7980
7981 /* More trash we can't trust. */
7982 &dummy, &dummy,
7983
7984 /* Modifier keys and pointer buttons, about which
7985 we don't care. */
7986 (unsigned int *) &dummy);
7987
7988 /* Now we have a position on the root; find the innermost window
7989 containing the pointer. */
7990 {
7991 Window win, child;
7992 int win_x, win_y;
7993 int parent_x = 0, parent_y = 0;
7994 int count;
7995
7996 win = root;
7997
7998 /* XTranslateCoordinates can get errors if the window
7999 structure is changing at the same time this function
8000 is running. So at least we must not crash from them. */
8001
8002 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
8003
8004 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
8005 && FRAME_LIVE_P (last_mouse_frame))
8006 {
8007 /* If mouse was grabbed on a frame, give coords for that frame
8008 even if the mouse is now outside it. */
8009 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8010
8011 /* From-window, to-window. */
8012 root, FRAME_X_WINDOW (last_mouse_frame),
8013
8014 /* From-position, to-position. */
8015 root_x, root_y, &win_x, &win_y,
8016
8017 /* Child of win. */
8018 &child);
8019 f1 = last_mouse_frame;
8020 }
8021 else
8022 {
8023 while (1)
8024 {
8025 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8026
8027 /* From-window, to-window. */
8028 root, win,
8029
8030 /* From-position, to-position. */
8031 root_x, root_y, &win_x, &win_y,
8032
8033 /* Child of win. */
8034 &child);
8035
8036 if (child == None || child == win)
8037 break;
8038
8039 win = child;
8040 parent_x = win_x;
8041 parent_y = win_y;
8042 }
8043
8044 /* Now we know that:
8045 win is the innermost window containing the pointer
8046 (XTC says it has no child containing the pointer),
8047 win_x and win_y are the pointer's position in it
8048 (XTC did this the last time through), and
8049 parent_x and parent_y are the pointer's position in win's parent.
8050 (They are what win_x and win_y were when win was child.
8051 If win is the root window, it has no parent, and
8052 parent_{x,y} are invalid, but that's okay, because we'll
8053 never use them in that case.) */
8054
8055 /* Is win one of our frames? */
8056 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
8057
8058 #ifdef USE_X_TOOLKIT
8059 /* If we end up with the menu bar window, say it's not
8060 on the frame. */
8061 if (f1 != NULL
8062 && f1->output_data.x->menubar_widget
8063 && win == XtWindow (f1->output_data.x->menubar_widget))
8064 f1 = NULL;
8065 #endif /* USE_X_TOOLKIT */
8066 }
8067
8068 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8069 f1 = 0;
8070
8071 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
8072
8073 /* If not, is it one of our scroll bars? */
8074 if (! f1)
8075 {
8076 struct scroll_bar *bar = x_window_to_scroll_bar (win);
8077
8078 if (bar)
8079 {
8080 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8081 win_x = parent_x;
8082 win_y = parent_y;
8083 }
8084 }
8085
8086 if (f1 == 0 && insist > 0)
8087 f1 = SELECTED_FRAME ();
8088
8089 if (f1)
8090 {
8091 /* Ok, we found a frame. Store all the values.
8092 last_mouse_glyph is a rectangle used to reduce the
8093 generation of mouse events. To not miss any motion
8094 events, we must divide the frame into rectangles of the
8095 size of the smallest character that could be displayed
8096 on it, i.e. into the same rectangles that matrices on
8097 the frame are divided into. */
8098
8099 int width, height, gx, gy;
8100 XRectangle rect;
8101
8102 if (glyph_rect (f1, win_x, win_y, &rect))
8103 last_mouse_glyph = rect;
8104 else
8105 {
8106 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8107 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8108 gx = win_x;
8109 gy = win_y;
8110
8111 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8112 round down even for negative values. */
8113 if (gx < 0)
8114 gx -= width - 1;
8115 if (gy < 0)
8116 gy -= height - 1;
8117 gx = (gx + width - 1) / width * width;
8118 gy = (gy + height - 1) / height * height;
8119
8120 last_mouse_glyph.width = width;
8121 last_mouse_glyph.height = height;
8122 last_mouse_glyph.x = gx;
8123 last_mouse_glyph.y = gy;
8124 }
8125
8126 *bar_window = Qnil;
8127 *part = 0;
8128 *fp = f1;
8129 XSETINT (*x, win_x);
8130 XSETINT (*y, win_y);
8131 *time = last_mouse_movement_time;
8132 }
8133 }
8134 }
8135
8136 UNBLOCK_INPUT;
8137 }
8138
8139
8140 #ifdef USE_X_TOOLKIT
8141
8142 /* Atimer callback function for TIMER. Called every 0.1s to process
8143 Xt timeouts, if needed. We must avoid calling XtAppPending as
8144 much as possible because that function does an implicit XFlush
8145 that slows us down. */
8146
8147 static void
8148 x_process_timeouts (timer)
8149 struct atimer *timer;
8150 {
8151 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8152 {
8153 BLOCK_INPUT;
8154 while (XtAppPending (Xt_app_con) & XtIMTimer)
8155 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8156 UNBLOCK_INPUT;
8157 }
8158 }
8159
8160 #endif /* USE_X_TOOLKIT */
8161
8162 \f
8163 /* Scroll bar support. */
8164
8165 /* Given an X window ID, find the struct scroll_bar which manages it.
8166 This can be called in GC, so we have to make sure to strip off mark
8167 bits. */
8168
8169 static struct scroll_bar *
8170 x_window_to_scroll_bar (window_id)
8171 Window window_id;
8172 {
8173 Lisp_Object tail;
8174
8175 for (tail = Vframe_list;
8176 XGCTYPE (tail) == Lisp_Cons;
8177 tail = XCDR (tail))
8178 {
8179 Lisp_Object frame, bar, condemned;
8180
8181 frame = XCAR (tail);
8182 /* All elements of Vframe_list should be frames. */
8183 if (! GC_FRAMEP (frame))
8184 abort ();
8185
8186 /* Scan this frame's scroll bar list for a scroll bar with the
8187 right window ID. */
8188 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8189 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8190 /* This trick allows us to search both the ordinary and
8191 condemned scroll bar lists with one loop. */
8192 ! GC_NILP (bar) || (bar = condemned,
8193 condemned = Qnil,
8194 ! GC_NILP (bar));
8195 bar = XSCROLL_BAR (bar)->next)
8196 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8197 return XSCROLL_BAR (bar);
8198 }
8199
8200 return 0;
8201 }
8202
8203
8204 #if defined USE_LUCID
8205
8206 /* Return the Lucid menu bar WINDOW is part of. Return null
8207 if WINDOW is not part of a menu bar. */
8208
8209 static Widget
8210 x_window_to_menu_bar (window)
8211 Window window;
8212 {
8213 Lisp_Object tail;
8214
8215 for (tail = Vframe_list;
8216 XGCTYPE (tail) == Lisp_Cons;
8217 tail = XCDR (tail))
8218 {
8219 Lisp_Object frame = XCAR (tail);
8220 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8221
8222 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8223 return menu_bar;
8224 }
8225
8226 return NULL;
8227 }
8228
8229 #endif /* USE_LUCID */
8230
8231 \f
8232 /************************************************************************
8233 Toolkit scroll bars
8234 ************************************************************************/
8235
8236 #ifdef USE_TOOLKIT_SCROLL_BARS
8237
8238 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8239 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8240 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8241 struct scroll_bar *));
8242 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8243 int, int, int));
8244
8245
8246 /* Id of action hook installed for scroll bars. */
8247
8248 static XtActionHookId action_hook_id;
8249
8250 /* Lisp window being scrolled. Set when starting to interact with
8251 a toolkit scroll bar, reset to nil when ending the interaction. */
8252
8253 static Lisp_Object window_being_scrolled;
8254
8255 /* Last scroll bar part sent in xm_scroll_callback. */
8256
8257 static int last_scroll_bar_part;
8258
8259 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8260 that movements of 1/20 of the screen size are mapped to up/down. */
8261
8262 static Boolean xaw3d_arrow_scroll;
8263
8264 /* Whether the drag scrolling maintains the mouse at the top of the
8265 thumb. If not, resizing the thumb needs to be done more carefully
8266 to avoid jerkyness. */
8267
8268 static Boolean xaw3d_pick_top;
8269
8270
8271 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8272 bars are used.. The hook is responsible for detecting when
8273 the user ends an interaction with the scroll bar, and generates
8274 a `end-scroll' scroll_bar_click' event if so. */
8275
8276 static void
8277 xt_action_hook (widget, client_data, action_name, event, params,
8278 num_params)
8279 Widget widget;
8280 XtPointer client_data;
8281 String action_name;
8282 XEvent *event;
8283 String *params;
8284 Cardinal *num_params;
8285 {
8286 int scroll_bar_p;
8287 char *end_action;
8288
8289 #ifdef USE_MOTIF
8290 scroll_bar_p = XmIsScrollBar (widget);
8291 end_action = "Release";
8292 #else /* !USE_MOTIF i.e. use Xaw */
8293 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8294 end_action = "EndScroll";
8295 #endif /* USE_MOTIF */
8296
8297 if (scroll_bar_p
8298 && strcmp (action_name, end_action) == 0
8299 && WINDOWP (window_being_scrolled))
8300 {
8301 struct window *w;
8302
8303 x_send_scroll_bar_event (window_being_scrolled,
8304 scroll_bar_end_scroll, 0, 0);
8305 w = XWINDOW (window_being_scrolled);
8306 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8307 window_being_scrolled = Qnil;
8308 last_scroll_bar_part = -1;
8309
8310 /* Xt timeouts no longer needed. */
8311 toolkit_scroll_bar_interaction = 0;
8312 }
8313 }
8314
8315 /* A vector of windows used for communication between
8316 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8317
8318 static struct window **scroll_bar_windows;
8319 static int scroll_bar_windows_size;
8320
8321
8322 /* Send a client message with message type Xatom_Scrollbar for a
8323 scroll action to the frame of WINDOW. PART is a value identifying
8324 the part of the scroll bar that was clicked on. PORTION is the
8325 amount to scroll of a whole of WHOLE. */
8326
8327 static void
8328 x_send_scroll_bar_event (window, part, portion, whole)
8329 Lisp_Object window;
8330 int part, portion, whole;
8331 {
8332 XEvent event;
8333 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8334 struct window *w = XWINDOW (window);
8335 struct frame *f = XFRAME (w->frame);
8336 int i;
8337
8338 BLOCK_INPUT;
8339
8340 /* Construct a ClientMessage event to send to the frame. */
8341 ev->type = ClientMessage;
8342 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8343 ev->display = FRAME_X_DISPLAY (f);
8344 ev->window = FRAME_X_WINDOW (f);
8345 ev->format = 32;
8346
8347 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8348 not enough to store a pointer or Lisp_Object on a 64 bit system.
8349 So, store the window in scroll_bar_windows and pass the index
8350 into that array in the event. */
8351 for (i = 0; i < scroll_bar_windows_size; ++i)
8352 if (scroll_bar_windows[i] == NULL)
8353 break;
8354
8355 if (i == scroll_bar_windows_size)
8356 {
8357 int new_size = max (10, 2 * scroll_bar_windows_size);
8358 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8359 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8360
8361 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8362 nbytes);
8363 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8364 scroll_bar_windows_size = new_size;
8365 }
8366
8367 scroll_bar_windows[i] = w;
8368 ev->data.l[0] = (long) i;
8369 ev->data.l[1] = (long) part;
8370 ev->data.l[2] = (long) 0;
8371 ev->data.l[3] = (long) portion;
8372 ev->data.l[4] = (long) whole;
8373
8374 /* Make Xt timeouts work while the scroll bar is active. */
8375 toolkit_scroll_bar_interaction = 1;
8376
8377 /* Setting the event mask to zero means that the message will
8378 be sent to the client that created the window, and if that
8379 window no longer exists, no event will be sent. */
8380 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8381 UNBLOCK_INPUT;
8382 }
8383
8384
8385 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8386 in *IEVENT. */
8387
8388 static void
8389 x_scroll_bar_to_input_event (event, ievent)
8390 XEvent *event;
8391 struct input_event *ievent;
8392 {
8393 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8394 Lisp_Object window;
8395 struct frame *f;
8396 struct window *w;
8397
8398 w = scroll_bar_windows[ev->data.l[0]];
8399 scroll_bar_windows[ev->data.l[0]] = NULL;
8400
8401 XSETWINDOW (window, w);
8402 f = XFRAME (w->frame);
8403
8404 ievent->kind = scroll_bar_click;
8405 ievent->frame_or_window = window;
8406 ievent->arg = Qnil;
8407 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8408 ievent->part = ev->data.l[1];
8409 ievent->code = ev->data.l[2];
8410 ievent->x = make_number ((int) ev->data.l[3]);
8411 ievent->y = make_number ((int) ev->data.l[4]);
8412 ievent->modifiers = 0;
8413 }
8414
8415
8416 #ifdef USE_MOTIF
8417
8418 /* Minimum and maximum values used for Motif scroll bars. */
8419
8420 #define XM_SB_MIN 1
8421 #define XM_SB_MAX 10000000
8422 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8423
8424
8425 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8426 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8427 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8428
8429 static void
8430 xm_scroll_callback (widget, client_data, call_data)
8431 Widget widget;
8432 XtPointer client_data, call_data;
8433 {
8434 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8435 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8436 int part = -1, whole = 0, portion = 0;
8437
8438 switch (cs->reason)
8439 {
8440 case XmCR_DECREMENT:
8441 bar->dragging = Qnil;
8442 part = scroll_bar_up_arrow;
8443 break;
8444
8445 case XmCR_INCREMENT:
8446 bar->dragging = Qnil;
8447 part = scroll_bar_down_arrow;
8448 break;
8449
8450 case XmCR_PAGE_DECREMENT:
8451 bar->dragging = Qnil;
8452 part = scroll_bar_above_handle;
8453 break;
8454
8455 case XmCR_PAGE_INCREMENT:
8456 bar->dragging = Qnil;
8457 part = scroll_bar_below_handle;
8458 break;
8459
8460 case XmCR_TO_TOP:
8461 bar->dragging = Qnil;
8462 part = scroll_bar_to_top;
8463 break;
8464
8465 case XmCR_TO_BOTTOM:
8466 bar->dragging = Qnil;
8467 part = scroll_bar_to_bottom;
8468 break;
8469
8470 case XmCR_DRAG:
8471 {
8472 int slider_size;
8473 int dragging_down_p = (INTEGERP (bar->dragging)
8474 && XINT (bar->dragging) <= cs->value);
8475
8476 /* Get the slider size. */
8477 BLOCK_INPUT;
8478 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8479 UNBLOCK_INPUT;
8480
8481 /* At the max position of the scroll bar, do a line-wise
8482 movement. Without doing anything, we would be called with
8483 the same cs->value again and again. If we want to make
8484 sure that we can reach the end of the buffer, we have to do
8485 something.
8486
8487 Implementation note: setting bar->dragging always to
8488 cs->value gives a smoother movement at the max position.
8489 Setting it to nil when doing line-wise movement gives
8490 a better slider behavior. */
8491
8492 if (cs->value + slider_size == XM_SB_MAX
8493 || (dragging_down_p
8494 && last_scroll_bar_part == scroll_bar_down_arrow))
8495 {
8496 part = scroll_bar_down_arrow;
8497 bar->dragging = Qnil;
8498 }
8499 else
8500 {
8501 whole = XM_SB_RANGE;
8502 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8503 part = scroll_bar_handle;
8504 bar->dragging = make_number (cs->value);
8505 }
8506 }
8507 break;
8508
8509 case XmCR_VALUE_CHANGED:
8510 break;
8511 };
8512
8513 if (part >= 0)
8514 {
8515 window_being_scrolled = bar->window;
8516 last_scroll_bar_part = part;
8517 x_send_scroll_bar_event (bar->window, part, portion, whole);
8518 }
8519 }
8520
8521
8522 #else /* !USE_MOTIF, i.e. Xaw. */
8523
8524
8525 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8526 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8527 scroll bar struct. CALL_DATA is a pointer to a float saying where
8528 the thumb is. */
8529
8530 static void
8531 xaw_jump_callback (widget, client_data, call_data)
8532 Widget widget;
8533 XtPointer client_data, call_data;
8534 {
8535 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8536 float top = *(float *) call_data;
8537 float shown;
8538 int whole, portion, height;
8539 int part;
8540
8541 /* Get the size of the thumb, a value between 0 and 1. */
8542 BLOCK_INPUT;
8543 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8544 UNBLOCK_INPUT;
8545
8546 whole = 10000000;
8547 portion = shown < 1 ? top * whole : 0;
8548
8549 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8550 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8551 the bottom, so we force the scrolling whenever we see that we're
8552 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8553 we try to ensure that we always stay two pixels away from the
8554 bottom). */
8555 part = scroll_bar_down_arrow;
8556 else
8557 part = scroll_bar_handle;
8558
8559 window_being_scrolled = bar->window;
8560 bar->dragging = make_number (portion);
8561 last_scroll_bar_part = part;
8562 x_send_scroll_bar_event (bar->window, part, portion, whole);
8563 }
8564
8565
8566 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8567 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8568 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8569 the scroll bar. CALL_DATA is an integer specifying the action that
8570 has taken place. It's magnitude is in the range 0..height of the
8571 scroll bar. Negative values mean scroll towards buffer start.
8572 Values < height of scroll bar mean line-wise movement. */
8573
8574 static void
8575 xaw_scroll_callback (widget, client_data, call_data)
8576 Widget widget;
8577 XtPointer client_data, call_data;
8578 {
8579 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8580 int position = (int) call_data;
8581 Dimension height;
8582 int part;
8583
8584 /* Get the height of the scroll bar. */
8585 BLOCK_INPUT;
8586 XtVaGetValues (widget, XtNheight, &height, NULL);
8587 UNBLOCK_INPUT;
8588
8589 if (abs (position) >= height)
8590 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8591
8592 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8593 it maps line-movement to call_data = max(5, height/20). */
8594 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8595 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8596 else
8597 part = scroll_bar_move_ratio;
8598
8599 window_being_scrolled = bar->window;
8600 bar->dragging = Qnil;
8601 last_scroll_bar_part = part;
8602 x_send_scroll_bar_event (bar->window, part, position, height);
8603 }
8604
8605
8606 #endif /* not USE_MOTIF */
8607
8608
8609 /* Create the widget for scroll bar BAR on frame F. Record the widget
8610 and X window of the scroll bar in BAR. */
8611
8612 static void
8613 x_create_toolkit_scroll_bar (f, bar)
8614 struct frame *f;
8615 struct scroll_bar *bar;
8616 {
8617 Window xwindow;
8618 Widget widget;
8619 Arg av[20];
8620 int ac = 0;
8621 char *scroll_bar_name = "verticalScrollBar";
8622 unsigned long pixel;
8623
8624 BLOCK_INPUT;
8625
8626 #ifdef USE_MOTIF
8627 /* Set resources. Create the widget. */
8628 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8629 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8630 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8631 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8632 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8633 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8634 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8635
8636 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8637 if (pixel != -1)
8638 {
8639 XtSetArg (av[ac], XmNforeground, pixel);
8640 ++ac;
8641 }
8642
8643 pixel = f->output_data.x->scroll_bar_background_pixel;
8644 if (pixel != -1)
8645 {
8646 XtSetArg (av[ac], XmNbackground, pixel);
8647 ++ac;
8648 }
8649
8650 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8651 scroll_bar_name, av, ac);
8652
8653 /* Add one callback for everything that can happen. */
8654 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8655 (XtPointer) bar);
8656 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8657 (XtPointer) bar);
8658 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8659 (XtPointer) bar);
8660 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8661 (XtPointer) bar);
8662 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8663 (XtPointer) bar);
8664 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8665 (XtPointer) bar);
8666 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8667 (XtPointer) bar);
8668
8669 /* Realize the widget. Only after that is the X window created. */
8670 XtRealizeWidget (widget);
8671
8672 /* Set the cursor to an arrow. I didn't find a resource to do that.
8673 And I'm wondering why it hasn't an arrow cursor by default. */
8674 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8675 f->output_data.x->nontext_cursor);
8676
8677 #else /* !USE_MOTIF i.e. use Xaw */
8678
8679 /* Set resources. Create the widget. The background of the
8680 Xaw3d scroll bar widget is a little bit light for my taste.
8681 We don't alter it here to let users change it according
8682 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8683 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8684 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8685 /* For smoother scrolling with Xaw3d -sm */
8686 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8687
8688 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8689 if (pixel != -1)
8690 {
8691 XtSetArg (av[ac], XtNforeground, pixel);
8692 ++ac;
8693 }
8694
8695 pixel = f->output_data.x->scroll_bar_background_pixel;
8696 if (pixel != -1)
8697 {
8698 XtSetArg (av[ac], XtNbackground, pixel);
8699 ++ac;
8700 }
8701
8702 /* Top/bottom shadow colors. */
8703
8704 /* Allocate them, if necessary. */
8705 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8706 {
8707 pixel = f->output_data.x->scroll_bar_background_pixel;
8708 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8709 &pixel, 1.2, 0x8000))
8710 pixel = -1;
8711 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8712 }
8713 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8714 {
8715 pixel = f->output_data.x->scroll_bar_background_pixel;
8716 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8717 &pixel, 0.6, 0x4000))
8718 pixel = -1;
8719 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8720 }
8721
8722 /* Tell the toolkit about them. */
8723 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8724 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8725 /* We tried to allocate a color for the top/bottom shadow, and
8726 failed, so tell Xaw3d to use dithering instead. */
8727 {
8728 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8729 ++ac;
8730 }
8731 else
8732 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8733 be more consistent with other emacs 3d colors, and since Xaw3d is
8734 not good at dealing with allocation failure. */
8735 {
8736 /* This tells Xaw3d to use real colors instead of dithering for
8737 the shadows. */
8738 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8739 ++ac;
8740
8741 /* Specify the colors. */
8742 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8743 if (pixel != -1)
8744 {
8745 XtSetArg (av[ac], "topShadowPixel", pixel);
8746 ++ac;
8747 }
8748 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8749 if (pixel != -1)
8750 {
8751 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8752 ++ac;
8753 }
8754 }
8755
8756 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8757 f->output_data.x->edit_widget, av, ac);
8758
8759 {
8760 char *initial = "";
8761 char *val = initial;
8762 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8763 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8764 if (val == initial)
8765 { /* ARROW_SCROLL */
8766 xaw3d_arrow_scroll = True;
8767 /* Isn't that just a personal preference ? -sm */
8768 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8769 }
8770 }
8771
8772 /* Define callbacks. */
8773 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8774 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8775 (XtPointer) bar);
8776
8777 /* Realize the widget. Only after that is the X window created. */
8778 XtRealizeWidget (widget);
8779
8780 #endif /* !USE_MOTIF */
8781
8782 /* Install an action hook that let's us detect when the user
8783 finishes interacting with a scroll bar. */
8784 if (action_hook_id == 0)
8785 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8786
8787 /* Remember X window and widget in the scroll bar vector. */
8788 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8789 xwindow = XtWindow (widget);
8790 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8791
8792 UNBLOCK_INPUT;
8793 }
8794
8795
8796 /* Set the thumb size and position of scroll bar BAR. We are currently
8797 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8798
8799 static void
8800 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8801 struct scroll_bar *bar;
8802 int portion, position, whole;
8803 {
8804 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8805 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8806 float top, shown;
8807
8808 if (whole == 0)
8809 top = 0, shown = 1;
8810 else
8811 {
8812 top = (float) position / whole;
8813 shown = (float) portion / whole;
8814 }
8815
8816 BLOCK_INPUT;
8817
8818 #ifdef USE_MOTIF
8819 {
8820 int size, value;
8821
8822 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8823 is the scroll bar's maximum and MIN is the scroll bar's minimum
8824 value. */
8825 size = shown * XM_SB_RANGE;
8826 size = min (size, XM_SB_RANGE);
8827 size = max (size, 1);
8828
8829 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8830 value = top * XM_SB_RANGE;
8831 value = min (value, XM_SB_MAX - size);
8832 value = max (value, XM_SB_MIN);
8833
8834 if (NILP (bar->dragging))
8835 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8836 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8837 /* This has the negative side effect that the slider value is
8838 not what it would be if we scrolled here using line-wise or
8839 page-wise movement. */
8840 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8841 else
8842 {
8843 /* If currently dragging, only update the slider size.
8844 This reduces flicker effects. */
8845 int old_value, old_size, increment, page_increment;
8846
8847 XmScrollBarGetValues (widget, &old_value, &old_size,
8848 &increment, &page_increment);
8849 XmScrollBarSetValues (widget, old_value,
8850 min (size, XM_SB_RANGE - old_value),
8851 0, 0, False);
8852 }
8853 }
8854 #else /* !USE_MOTIF i.e. use Xaw */
8855 {
8856 float old_top, old_shown;
8857 Dimension height;
8858 XtVaGetValues (widget,
8859 XtNtopOfThumb, &old_top,
8860 XtNshown, &old_shown,
8861 XtNheight, &height,
8862 NULL);
8863
8864 /* Massage the top+shown values. */
8865 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8866 top = max (0, min (1, top));
8867 else
8868 top = old_top;
8869 /* Keep two pixels available for moving the thumb down. */
8870 shown = max (0, min (1 - top - (2.0 / height), shown));
8871
8872 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8873 check that your system's configuration file contains a define
8874 for `NARROWPROTO'. See s/freebsd.h for an example. */
8875 if (top != old_top || shown != old_shown)
8876 {
8877 if (NILP (bar->dragging))
8878 XawScrollbarSetThumb (widget, top, shown);
8879 else
8880 {
8881 #ifdef HAVE_XAW3D
8882 ScrollbarWidget sb = (ScrollbarWidget) widget;
8883 int scroll_mode = 0;
8884
8885 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8886 if (xaw3d_arrow_scroll)
8887 {
8888 /* Xaw3d stupidly ignores resize requests while dragging
8889 so we have to make it believe it's not in dragging mode. */
8890 scroll_mode = sb->scrollbar.scroll_mode;
8891 if (scroll_mode == 2)
8892 sb->scrollbar.scroll_mode = 0;
8893 }
8894 #endif
8895 /* Try to make the scrolling a tad smoother. */
8896 if (!xaw3d_pick_top)
8897 shown = min (shown, old_shown);
8898
8899 XawScrollbarSetThumb (widget, top, shown);
8900
8901 #ifdef HAVE_XAW3D
8902 if (xaw3d_arrow_scroll && scroll_mode == 2)
8903 sb->scrollbar.scroll_mode = scroll_mode;
8904 #endif
8905 }
8906 }
8907 }
8908 #endif /* !USE_MOTIF */
8909
8910 UNBLOCK_INPUT;
8911 }
8912
8913 #endif /* USE_TOOLKIT_SCROLL_BARS */
8914
8915
8916 \f
8917 /************************************************************************
8918 Scroll bars, general
8919 ************************************************************************/
8920
8921 /* Create a scroll bar and return the scroll bar vector for it. W is
8922 the Emacs window on which to create the scroll bar. TOP, LEFT,
8923 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8924 scroll bar. */
8925
8926 static struct scroll_bar *
8927 x_scroll_bar_create (w, top, left, width, height)
8928 struct window *w;
8929 int top, left, width, height;
8930 {
8931 struct frame *f = XFRAME (w->frame);
8932 struct scroll_bar *bar
8933 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8934
8935 BLOCK_INPUT;
8936
8937 #ifdef USE_TOOLKIT_SCROLL_BARS
8938 x_create_toolkit_scroll_bar (f, bar);
8939 #else /* not USE_TOOLKIT_SCROLL_BARS */
8940 {
8941 XSetWindowAttributes a;
8942 unsigned long mask;
8943 Window window;
8944
8945 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8946 if (a.background_pixel == -1)
8947 a.background_pixel = f->output_data.x->background_pixel;
8948
8949 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8950 | ButtonMotionMask | PointerMotionHintMask
8951 | ExposureMask);
8952 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8953
8954 mask = (CWBackPixel | CWEventMask | CWCursor);
8955
8956 /* Clear the area of W that will serve as a scroll bar. This is
8957 for the case that a window has been split horizontally. In
8958 this case, no clear_frame is generated to reduce flickering. */
8959 if (width > 0 && height > 0)
8960 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8961 left, top, width,
8962 window_box_height (w), False);
8963
8964 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8965 /* Position and size of scroll bar. */
8966 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8967 top,
8968 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8969 height,
8970 /* Border width, depth, class, and visual. */
8971 0,
8972 CopyFromParent,
8973 CopyFromParent,
8974 CopyFromParent,
8975 /* Attributes. */
8976 mask, &a);
8977 SET_SCROLL_BAR_X_WINDOW (bar, window);
8978 }
8979 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8980
8981 XSETWINDOW (bar->window, w);
8982 XSETINT (bar->top, top);
8983 XSETINT (bar->left, left);
8984 XSETINT (bar->width, width);
8985 XSETINT (bar->height, height);
8986 XSETINT (bar->start, 0);
8987 XSETINT (bar->end, 0);
8988 bar->dragging = Qnil;
8989
8990 /* Add bar to its frame's list of scroll bars. */
8991 bar->next = FRAME_SCROLL_BARS (f);
8992 bar->prev = Qnil;
8993 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8994 if (!NILP (bar->next))
8995 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8996
8997 /* Map the window/widget. */
8998 #ifdef USE_TOOLKIT_SCROLL_BARS
8999 {
9000 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9001 XtConfigureWidget (scroll_bar,
9002 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9003 top,
9004 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9005 max (height, 1), 0);
9006 XtMapWidget (scroll_bar);
9007 }
9008 #else /* not USE_TOOLKIT_SCROLL_BARS */
9009 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9010 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9011
9012 UNBLOCK_INPUT;
9013 return bar;
9014 }
9015
9016
9017 /* Draw BAR's handle in the proper position.
9018
9019 If the handle is already drawn from START to END, don't bother
9020 redrawing it, unless REBUILD is non-zero; in that case, always
9021 redraw it. (REBUILD is handy for drawing the handle after expose
9022 events.)
9023
9024 Normally, we want to constrain the start and end of the handle to
9025 fit inside its rectangle, but if the user is dragging the scroll
9026 bar handle, we want to let them drag it down all the way, so that
9027 the bar's top is as far down as it goes; otherwise, there's no way
9028 to move to the very end of the buffer. */
9029
9030 #ifndef USE_TOOLKIT_SCROLL_BARS
9031
9032 static void
9033 x_scroll_bar_set_handle (bar, start, end, rebuild)
9034 struct scroll_bar *bar;
9035 int start, end;
9036 int rebuild;
9037 {
9038 int dragging = ! NILP (bar->dragging);
9039 Window w = SCROLL_BAR_X_WINDOW (bar);
9040 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9041 GC gc = f->output_data.x->normal_gc;
9042
9043 /* If the display is already accurate, do nothing. */
9044 if (! rebuild
9045 && start == XINT (bar->start)
9046 && end == XINT (bar->end))
9047 return;
9048
9049 BLOCK_INPUT;
9050
9051 {
9052 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9053 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9054 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9055
9056 /* Make sure the values are reasonable, and try to preserve
9057 the distance between start and end. */
9058 {
9059 int length = end - start;
9060
9061 if (start < 0)
9062 start = 0;
9063 else if (start > top_range)
9064 start = top_range;
9065 end = start + length;
9066
9067 if (end < start)
9068 end = start;
9069 else if (end > top_range && ! dragging)
9070 end = top_range;
9071 }
9072
9073 /* Store the adjusted setting in the scroll bar. */
9074 XSETINT (bar->start, start);
9075 XSETINT (bar->end, end);
9076
9077 /* Clip the end position, just for display. */
9078 if (end > top_range)
9079 end = top_range;
9080
9081 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9082 below top positions, to make sure the handle is always at least
9083 that many pixels tall. */
9084 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
9085
9086 /* Draw the empty space above the handle. Note that we can't clear
9087 zero-height areas; that means "clear to end of window." */
9088 if (0 < start)
9089 x_clear_area (FRAME_X_DISPLAY (f), w,
9090 /* x, y, width, height, and exposures. */
9091 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9092 VERTICAL_SCROLL_BAR_TOP_BORDER,
9093 inside_width, start,
9094 False);
9095
9096 /* Change to proper foreground color if one is specified. */
9097 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9098 XSetForeground (FRAME_X_DISPLAY (f), gc,
9099 f->output_data.x->scroll_bar_foreground_pixel);
9100
9101 /* Draw the handle itself. */
9102 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
9103 /* x, y, width, height */
9104 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9105 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
9106 inside_width, end - start);
9107
9108 /* Restore the foreground color of the GC if we changed it above. */
9109 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9110 XSetForeground (FRAME_X_DISPLAY (f), gc,
9111 f->output_data.x->foreground_pixel);
9112
9113 /* Draw the empty space below the handle. Note that we can't
9114 clear zero-height areas; that means "clear to end of window." */
9115 if (end < inside_height)
9116 x_clear_area (FRAME_X_DISPLAY (f), w,
9117 /* x, y, width, height, and exposures. */
9118 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9119 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9120 inside_width, inside_height - end,
9121 False);
9122
9123 }
9124
9125 UNBLOCK_INPUT;
9126 }
9127
9128 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9129
9130 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9131 nil. */
9132
9133 static void
9134 x_scroll_bar_remove (bar)
9135 struct scroll_bar *bar;
9136 {
9137 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9138 BLOCK_INPUT;
9139
9140 #ifdef USE_TOOLKIT_SCROLL_BARS
9141 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9142 #else
9143 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9144 #endif
9145
9146 /* Disassociate this scroll bar from its window. */
9147 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
9148
9149 UNBLOCK_INPUT;
9150 }
9151
9152
9153 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9154 that we are displaying PORTION characters out of a total of WHOLE
9155 characters, starting at POSITION. If WINDOW has no scroll bar,
9156 create one. */
9157
9158 static void
9159 XTset_vertical_scroll_bar (w, portion, whole, position)
9160 struct window *w;
9161 int portion, whole, position;
9162 {
9163 struct frame *f = XFRAME (w->frame);
9164 struct scroll_bar *bar;
9165 int top, height, left, sb_left, width, sb_width;
9166 int window_x, window_y, window_width, window_height;
9167
9168 /* Get window dimensions. */
9169 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9170 top = window_y;
9171 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9172 height = window_height;
9173
9174 /* Compute the left edge of the scroll bar area. */
9175 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9176 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9177 else
9178 left = XFASTINT (w->left);
9179 left *= CANON_X_UNIT (f);
9180 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9181
9182 /* Compute the width of the scroll bar which might be less than
9183 the width of the area reserved for the scroll bar. */
9184 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9185 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
9186 else
9187 sb_width = width;
9188
9189 /* Compute the left edge of the scroll bar. */
9190 #ifdef USE_TOOLKIT_SCROLL_BARS
9191 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9192 sb_left = left + width - sb_width - (width - sb_width) / 2;
9193 else
9194 sb_left = left + (width - sb_width) / 2;
9195 #else
9196 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9197 sb_left = left + width - sb_width;
9198 else
9199 sb_left = left;
9200 #endif
9201
9202 /* Does the scroll bar exist yet? */
9203 if (NILP (w->vertical_scroll_bar))
9204 {
9205 if (width > 0 && height > 0)
9206 {
9207 BLOCK_INPUT;
9208 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9209 left, top, width, height, False);
9210 UNBLOCK_INPUT;
9211 }
9212
9213 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9214 }
9215 else
9216 {
9217 /* It may just need to be moved and resized. */
9218 unsigned int mask = 0;
9219
9220 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9221
9222 BLOCK_INPUT;
9223
9224 if (sb_left != XINT (bar->left))
9225 mask |= CWX;
9226 if (top != XINT (bar->top))
9227 mask |= CWY;
9228 if (sb_width != XINT (bar->width))
9229 mask |= CWWidth;
9230 if (height != XINT (bar->height))
9231 mask |= CWHeight;
9232
9233 #ifdef USE_TOOLKIT_SCROLL_BARS
9234
9235 /* Since toolkit scroll bars are smaller than the space reserved
9236 for them on the frame, we have to clear "under" them. */
9237 if (width > 0 && height > 0)
9238 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9239 left, top, width, height, False);
9240
9241 /* Move/size the scroll bar widget. */
9242 if (mask)
9243 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9244 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9245 top,
9246 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9247 max (height, 1), 0);
9248
9249 #else /* not USE_TOOLKIT_SCROLL_BARS */
9250
9251 /* Clear areas not covered by the scroll bar because of
9252 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9253 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9254 {
9255 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9256 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9257 height, False);
9258 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9259 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9260 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9261 height, False);
9262 }
9263
9264 /* Clear areas not covered by the scroll bar because it's not as
9265 wide as the area reserved for it . This makes sure a
9266 previous mode line display is cleared after C-x 2 C-x 1, for
9267 example. */
9268 {
9269 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9270 int rest = area_width - sb_width;
9271 if (rest > 0 && height > 0)
9272 {
9273 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
9274 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9275 left + area_width - rest, top,
9276 rest, height, False);
9277 else
9278 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9279 left, top, rest, height, False);
9280 }
9281 }
9282
9283 /* Move/size the scroll bar window. */
9284 if (mask)
9285 {
9286 XWindowChanges wc;
9287
9288 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9289 wc.y = top;
9290 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9291 wc.height = height;
9292 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9293 mask, &wc);
9294 }
9295
9296 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9297
9298 /* Remember new settings. */
9299 XSETINT (bar->left, sb_left);
9300 XSETINT (bar->top, top);
9301 XSETINT (bar->width, sb_width);
9302 XSETINT (bar->height, height);
9303
9304 UNBLOCK_INPUT;
9305 }
9306
9307 #ifdef USE_TOOLKIT_SCROLL_BARS
9308 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9309 #else /* not USE_TOOLKIT_SCROLL_BARS */
9310 /* Set the scroll bar's current state, unless we're currently being
9311 dragged. */
9312 if (NILP (bar->dragging))
9313 {
9314 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9315
9316 if (whole == 0)
9317 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9318 else
9319 {
9320 int start = ((double) position * top_range) / whole;
9321 int end = ((double) (position + portion) * top_range) / whole;
9322 x_scroll_bar_set_handle (bar, start, end, 0);
9323 }
9324 }
9325 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9326
9327 XSETVECTOR (w->vertical_scroll_bar, bar);
9328 }
9329
9330
9331 /* The following three hooks are used when we're doing a thorough
9332 redisplay of the frame. We don't explicitly know which scroll bars
9333 are going to be deleted, because keeping track of when windows go
9334 away is a real pain - "Can you say set-window-configuration, boys
9335 and girls?" Instead, we just assert at the beginning of redisplay
9336 that *all* scroll bars are to be removed, and then save a scroll bar
9337 from the fiery pit when we actually redisplay its window. */
9338
9339 /* Arrange for all scroll bars on FRAME to be removed at the next call
9340 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9341 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9342
9343 static void
9344 XTcondemn_scroll_bars (frame)
9345 FRAME_PTR frame;
9346 {
9347 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9348 while (! NILP (FRAME_SCROLL_BARS (frame)))
9349 {
9350 Lisp_Object bar;
9351 bar = FRAME_SCROLL_BARS (frame);
9352 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9353 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9354 XSCROLL_BAR (bar)->prev = Qnil;
9355 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9356 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9357 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9358 }
9359 }
9360
9361
9362 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9363 Note that WINDOW isn't necessarily condemned at all. */
9364
9365 static void
9366 XTredeem_scroll_bar (window)
9367 struct window *window;
9368 {
9369 struct scroll_bar *bar;
9370 struct frame *f;
9371
9372 /* We can't redeem this window's scroll bar if it doesn't have one. */
9373 if (NILP (window->vertical_scroll_bar))
9374 abort ();
9375
9376 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9377
9378 /* Unlink it from the condemned list. */
9379 f = XFRAME (WINDOW_FRAME (window));
9380 if (NILP (bar->prev))
9381 {
9382 /* If the prev pointer is nil, it must be the first in one of
9383 the lists. */
9384 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9385 /* It's not condemned. Everything's fine. */
9386 return;
9387 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9388 window->vertical_scroll_bar))
9389 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9390 else
9391 /* If its prev pointer is nil, it must be at the front of
9392 one or the other! */
9393 abort ();
9394 }
9395 else
9396 XSCROLL_BAR (bar->prev)->next = bar->next;
9397
9398 if (! NILP (bar->next))
9399 XSCROLL_BAR (bar->next)->prev = bar->prev;
9400
9401 bar->next = FRAME_SCROLL_BARS (f);
9402 bar->prev = Qnil;
9403 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9404 if (! NILP (bar->next))
9405 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9406 }
9407
9408 /* Remove all scroll bars on FRAME that haven't been saved since the
9409 last call to `*condemn_scroll_bars_hook'. */
9410
9411 static void
9412 XTjudge_scroll_bars (f)
9413 FRAME_PTR f;
9414 {
9415 Lisp_Object bar, next;
9416
9417 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9418
9419 /* Clear out the condemned list now so we won't try to process any
9420 more events on the hapless scroll bars. */
9421 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9422
9423 for (; ! NILP (bar); bar = next)
9424 {
9425 struct scroll_bar *b = XSCROLL_BAR (bar);
9426
9427 x_scroll_bar_remove (b);
9428
9429 next = b->next;
9430 b->next = b->prev = Qnil;
9431 }
9432
9433 /* Now there should be no references to the condemned scroll bars,
9434 and they should get garbage-collected. */
9435 }
9436
9437
9438 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9439 is a no-op when using toolkit scroll bars.
9440
9441 This may be called from a signal handler, so we have to ignore GC
9442 mark bits. */
9443
9444 static void
9445 x_scroll_bar_expose (bar, event)
9446 struct scroll_bar *bar;
9447 XEvent *event;
9448 {
9449 #ifndef USE_TOOLKIT_SCROLL_BARS
9450
9451 Window w = SCROLL_BAR_X_WINDOW (bar);
9452 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9453 GC gc = f->output_data.x->normal_gc;
9454 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9455
9456 BLOCK_INPUT;
9457
9458 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9459
9460 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9461 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9462
9463 /* x, y, width, height */
9464 0, 0,
9465 XINT (bar->width) - 1 - width_trim - width_trim,
9466 XINT (bar->height) - 1);
9467
9468 UNBLOCK_INPUT;
9469
9470 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9471 }
9472
9473 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9474 is set to something other than no_event, it is enqueued.
9475
9476 This may be called from a signal handler, so we have to ignore GC
9477 mark bits. */
9478
9479 #ifndef USE_TOOLKIT_SCROLL_BARS
9480
9481 static void
9482 x_scroll_bar_handle_click (bar, event, emacs_event)
9483 struct scroll_bar *bar;
9484 XEvent *event;
9485 struct input_event *emacs_event;
9486 {
9487 if (! GC_WINDOWP (bar->window))
9488 abort ();
9489
9490 emacs_event->kind = scroll_bar_click;
9491 emacs_event->code = event->xbutton.button - Button1;
9492 emacs_event->modifiers
9493 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9494 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9495 event->xbutton.state)
9496 | (event->type == ButtonRelease
9497 ? up_modifier
9498 : down_modifier));
9499 emacs_event->frame_or_window = bar->window;
9500 emacs_event->arg = Qnil;
9501 emacs_event->timestamp = event->xbutton.time;
9502 {
9503 #if 0
9504 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9505 int internal_height
9506 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9507 #endif
9508 int top_range
9509 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9510 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9511
9512 if (y < 0) y = 0;
9513 if (y > top_range) y = top_range;
9514
9515 if (y < XINT (bar->start))
9516 emacs_event->part = scroll_bar_above_handle;
9517 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9518 emacs_event->part = scroll_bar_handle;
9519 else
9520 emacs_event->part = scroll_bar_below_handle;
9521
9522 /* Just because the user has clicked on the handle doesn't mean
9523 they want to drag it. Lisp code needs to be able to decide
9524 whether or not we're dragging. */
9525 #if 0
9526 /* If the user has just clicked on the handle, record where they're
9527 holding it. */
9528 if (event->type == ButtonPress
9529 && emacs_event->part == scroll_bar_handle)
9530 XSETINT (bar->dragging, y - XINT (bar->start));
9531 #endif
9532
9533 /* If the user has released the handle, set it to its final position. */
9534 if (event->type == ButtonRelease
9535 && ! NILP (bar->dragging))
9536 {
9537 int new_start = y - XINT (bar->dragging);
9538 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9539
9540 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9541 bar->dragging = Qnil;
9542 }
9543
9544 /* Same deal here as the other #if 0. */
9545 #if 0
9546 /* Clicks on the handle are always reported as occurring at the top of
9547 the handle. */
9548 if (emacs_event->part == scroll_bar_handle)
9549 emacs_event->x = bar->start;
9550 else
9551 XSETINT (emacs_event->x, y);
9552 #else
9553 XSETINT (emacs_event->x, y);
9554 #endif
9555
9556 XSETINT (emacs_event->y, top_range);
9557 }
9558 }
9559
9560 /* Handle some mouse motion while someone is dragging the scroll bar.
9561
9562 This may be called from a signal handler, so we have to ignore GC
9563 mark bits. */
9564
9565 static void
9566 x_scroll_bar_note_movement (bar, event)
9567 struct scroll_bar *bar;
9568 XEvent *event;
9569 {
9570 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9571
9572 last_mouse_movement_time = event->xmotion.time;
9573
9574 f->mouse_moved = 1;
9575 XSETVECTOR (last_mouse_scroll_bar, bar);
9576
9577 /* If we're dragging the bar, display it. */
9578 if (! GC_NILP (bar->dragging))
9579 {
9580 /* Where should the handle be now? */
9581 int new_start = event->xmotion.y - XINT (bar->dragging);
9582
9583 if (new_start != XINT (bar->start))
9584 {
9585 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9586
9587 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9588 }
9589 }
9590 }
9591
9592 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9593
9594 /* Return information to the user about the current position of the mouse
9595 on the scroll bar. */
9596
9597 static void
9598 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9599 FRAME_PTR *fp;
9600 Lisp_Object *bar_window;
9601 enum scroll_bar_part *part;
9602 Lisp_Object *x, *y;
9603 unsigned long *time;
9604 {
9605 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9606 Window w = SCROLL_BAR_X_WINDOW (bar);
9607 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9608 int win_x, win_y;
9609 Window dummy_window;
9610 int dummy_coord;
9611 unsigned int dummy_mask;
9612
9613 BLOCK_INPUT;
9614
9615 /* Get the mouse's position relative to the scroll bar window, and
9616 report that. */
9617 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9618
9619 /* Root, child, root x and root y. */
9620 &dummy_window, &dummy_window,
9621 &dummy_coord, &dummy_coord,
9622
9623 /* Position relative to scroll bar. */
9624 &win_x, &win_y,
9625
9626 /* Mouse buttons and modifier keys. */
9627 &dummy_mask))
9628 ;
9629 else
9630 {
9631 #if 0
9632 int inside_height
9633 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9634 #endif
9635 int top_range
9636 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9637
9638 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9639
9640 if (! NILP (bar->dragging))
9641 win_y -= XINT (bar->dragging);
9642
9643 if (win_y < 0)
9644 win_y = 0;
9645 if (win_y > top_range)
9646 win_y = top_range;
9647
9648 *fp = f;
9649 *bar_window = bar->window;
9650
9651 if (! NILP (bar->dragging))
9652 *part = scroll_bar_handle;
9653 else if (win_y < XINT (bar->start))
9654 *part = scroll_bar_above_handle;
9655 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9656 *part = scroll_bar_handle;
9657 else
9658 *part = scroll_bar_below_handle;
9659
9660 XSETINT (*x, win_y);
9661 XSETINT (*y, top_range);
9662
9663 f->mouse_moved = 0;
9664 last_mouse_scroll_bar = Qnil;
9665 }
9666
9667 *time = last_mouse_movement_time;
9668
9669 UNBLOCK_INPUT;
9670 }
9671
9672
9673 /* The screen has been cleared so we may have changed foreground or
9674 background colors, and the scroll bars may need to be redrawn.
9675 Clear out the scroll bars, and ask for expose events, so we can
9676 redraw them. */
9677
9678 void
9679 x_scroll_bar_clear (f)
9680 FRAME_PTR f;
9681 {
9682 #ifndef USE_TOOLKIT_SCROLL_BARS
9683 Lisp_Object bar;
9684
9685 /* We can have scroll bars even if this is 0,
9686 if we just turned off scroll bar mode.
9687 But in that case we should not clear them. */
9688 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9689 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9690 bar = XSCROLL_BAR (bar)->next)
9691 XClearArea (FRAME_X_DISPLAY (f),
9692 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9693 0, 0, 0, 0, True);
9694 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9695 }
9696
9697 /* This processes Expose events from the menu-bar specific X event
9698 loop in xmenu.c. This allows to redisplay the frame if necessary
9699 when handling menu-bar or pop-up items. */
9700
9701 int
9702 process_expose_from_menu (event)
9703 XEvent event;
9704 {
9705 FRAME_PTR f;
9706 struct x_display_info *dpyinfo;
9707 int frame_exposed_p = 0;
9708
9709 BLOCK_INPUT;
9710
9711 dpyinfo = x_display_info_for_display (event.xexpose.display);
9712 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9713 if (f)
9714 {
9715 if (f->async_visible == 0)
9716 {
9717 f->async_visible = 1;
9718 f->async_iconified = 0;
9719 f->output_data.x->has_been_visible = 1;
9720 SET_FRAME_GARBAGED (f);
9721 }
9722 else
9723 {
9724 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9725 event.xexpose.x, event.xexpose.y,
9726 event.xexpose.width, event.xexpose.height);
9727 frame_exposed_p = 1;
9728 }
9729 }
9730 else
9731 {
9732 struct scroll_bar *bar
9733 = x_window_to_scroll_bar (event.xexpose.window);
9734
9735 if (bar)
9736 x_scroll_bar_expose (bar, &event);
9737 }
9738
9739 UNBLOCK_INPUT;
9740 return frame_exposed_p;
9741 }
9742 \f
9743 /* Define a queue to save up SelectionRequest events for later handling. */
9744
9745 struct selection_event_queue
9746 {
9747 XEvent event;
9748 struct selection_event_queue *next;
9749 };
9750
9751 static struct selection_event_queue *queue;
9752
9753 /* Nonzero means queue up certain events--don't process them yet. */
9754
9755 static int x_queue_selection_requests;
9756
9757 /* Queue up an X event *EVENT, to be processed later. */
9758
9759 static void
9760 x_queue_event (f, event)
9761 FRAME_PTR f;
9762 XEvent *event;
9763 {
9764 struct selection_event_queue *queue_tmp
9765 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9766
9767 if (queue_tmp != NULL)
9768 {
9769 queue_tmp->event = *event;
9770 queue_tmp->next = queue;
9771 queue = queue_tmp;
9772 }
9773 }
9774
9775 /* Take all the queued events and put them back
9776 so that they get processed afresh. */
9777
9778 static void
9779 x_unqueue_events (display)
9780 Display *display;
9781 {
9782 while (queue != NULL)
9783 {
9784 struct selection_event_queue *queue_tmp = queue;
9785 XPutBackEvent (display, &queue_tmp->event);
9786 queue = queue_tmp->next;
9787 xfree ((char *)queue_tmp);
9788 }
9789 }
9790
9791 /* Start queuing SelectionRequest events. */
9792
9793 void
9794 x_start_queuing_selection_requests (display)
9795 Display *display;
9796 {
9797 x_queue_selection_requests++;
9798 }
9799
9800 /* Stop queuing SelectionRequest events. */
9801
9802 void
9803 x_stop_queuing_selection_requests (display)
9804 Display *display;
9805 {
9806 x_queue_selection_requests--;
9807 x_unqueue_events (display);
9808 }
9809 \f
9810 /* The main X event-reading loop - XTread_socket. */
9811
9812 /* Time stamp of enter window event. This is only used by XTread_socket,
9813 but we have to put it out here, since static variables within functions
9814 sometimes don't work. */
9815
9816 static Time enter_timestamp;
9817
9818 /* This holds the state XLookupString needs to implement dead keys
9819 and other tricks known as "compose processing". _X Window System_
9820 says that a portable program can't use this, but Stephen Gildea assures
9821 me that letting the compiler initialize it to zeros will work okay.
9822
9823 This must be defined outside of XTread_socket, for the same reasons
9824 given for enter_time stamp, above. */
9825
9826 static XComposeStatus compose_status;
9827
9828 /* Record the last 100 characters stored
9829 to help debug the loss-of-chars-during-GC problem. */
9830
9831 static int temp_index;
9832 static short temp_buffer[100];
9833
9834 /* Set this to nonzero to fake an "X I/O error"
9835 on a particular display. */
9836
9837 struct x_display_info *XTread_socket_fake_io_error;
9838
9839 /* When we find no input here, we occasionally do a no-op command
9840 to verify that the X server is still running and we can still talk with it.
9841 We try all the open displays, one by one.
9842 This variable is used for cycling thru the displays. */
9843
9844 static struct x_display_info *next_noop_dpyinfo;
9845
9846 #define SET_SAVED_MENU_EVENT(size) \
9847 do \
9848 { \
9849 if (f->output_data.x->saved_menu_event == 0) \
9850 f->output_data.x->saved_menu_event \
9851 = (XEvent *) xmalloc (sizeof (XEvent)); \
9852 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9853 if (numchars >= 1) \
9854 { \
9855 bufp->kind = menu_bar_activate_event; \
9856 XSETFRAME (bufp->frame_or_window, f); \
9857 bufp->arg = Qnil; \
9858 bufp++; \
9859 count++; \
9860 numchars--; \
9861 } \
9862 } \
9863 while (0)
9864
9865 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9866 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9867
9868 /* Read events coming from the X server.
9869 This routine is called by the SIGIO handler.
9870 We return as soon as there are no more events to be read.
9871
9872 Events representing keys are stored in buffer BUFP,
9873 which can hold up to NUMCHARS characters.
9874 We return the number of characters stored into the buffer,
9875 thus pretending to be `read'.
9876
9877 EXPECTED is nonzero if the caller knows input is available. */
9878
9879 int
9880 XTread_socket (sd, bufp, numchars, expected)
9881 register int sd;
9882 /* register */ struct input_event *bufp;
9883 /* register */ int numchars;
9884 int expected;
9885 {
9886 int count = 0;
9887 int nbytes = 0;
9888 XEvent event;
9889 struct frame *f;
9890 int event_found = 0;
9891 struct x_display_info *dpyinfo;
9892 struct coding_system coding;
9893
9894 if (interrupt_input_blocked)
9895 {
9896 interrupt_input_pending = 1;
9897 return -1;
9898 }
9899
9900 interrupt_input_pending = 0;
9901 BLOCK_INPUT;
9902
9903 /* So people can tell when we have read the available input. */
9904 input_signal_count++;
9905
9906 if (numchars <= 0)
9907 abort (); /* Don't think this happens. */
9908
9909 ++handling_signal;
9910
9911 /* The input should be decoded if it is from XIM. Currently the
9912 locale of XIM is the same as that of the system. So, we can use
9913 Vlocale_coding_system which is initialized properly at Emacs
9914 startup time. */
9915 setup_coding_system (Vlocale_coding_system, &coding);
9916 coding.src_multibyte = 0;
9917 coding.dst_multibyte = 1;
9918 /* The input is converted to events, thus we can't handle
9919 composition. Anyway, there's no XIM that gives us composition
9920 information. */
9921 coding.composing = COMPOSITION_DISABLED;
9922
9923 /* Find the display we are supposed to read input for.
9924 It's the one communicating on descriptor SD. */
9925 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9926 {
9927 #if 0 /* This ought to be unnecessary; let's verify it. */
9928 #ifdef FIOSNBIO
9929 /* If available, Xlib uses FIOSNBIO to make the socket
9930 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9931 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9932 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9933 fcntl (dpyinfo->connection, F_SETFL, 0);
9934 #endif /* ! defined (FIOSNBIO) */
9935 #endif
9936
9937 #if 0 /* This code can't be made to work, with multiple displays,
9938 and appears not to be used on any system any more.
9939 Also keyboard.c doesn't turn O_NDELAY on and off
9940 for X connections. */
9941 #ifndef SIGIO
9942 #ifndef HAVE_SELECT
9943 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9944 {
9945 extern int read_alarm_should_throw;
9946 read_alarm_should_throw = 1;
9947 XPeekEvent (dpyinfo->display, &event);
9948 read_alarm_should_throw = 0;
9949 }
9950 #endif /* HAVE_SELECT */
9951 #endif /* SIGIO */
9952 #endif
9953
9954 /* For debugging, this gives a way to fake an I/O error. */
9955 if (dpyinfo == XTread_socket_fake_io_error)
9956 {
9957 XTread_socket_fake_io_error = 0;
9958 x_io_error_quitter (dpyinfo->display);
9959 }
9960
9961 while (XPending (dpyinfo->display))
9962 {
9963 XNextEvent (dpyinfo->display, &event);
9964
9965 #ifdef HAVE_X_I18N
9966 {
9967 /* Filter events for the current X input method.
9968 XFilterEvent returns non-zero if the input method has
9969 consumed the event. We pass the frame's X window to
9970 XFilterEvent because that's the one for which the IC
9971 was created. */
9972 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9973 event.xclient.window);
9974 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9975 break;
9976 }
9977 #endif
9978 event_found = 1;
9979
9980 switch (event.type)
9981 {
9982 case ClientMessage:
9983 {
9984 if (event.xclient.message_type
9985 == dpyinfo->Xatom_wm_protocols
9986 && event.xclient.format == 32)
9987 {
9988 if (event.xclient.data.l[0]
9989 == dpyinfo->Xatom_wm_take_focus)
9990 {
9991 /* Use x_any_window_to_frame because this
9992 could be the shell widget window
9993 if the frame has no title bar. */
9994 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9995 #ifdef HAVE_X_I18N
9996 /* Not quite sure this is needed -pd */
9997 if (f && FRAME_XIC (f))
9998 XSetICFocus (FRAME_XIC (f));
9999 #endif
10000 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10001 instructs the WM to set the input focus automatically for
10002 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10003 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10004 it has set the focus. So, XSetInputFocus below is not
10005 needed.
10006
10007 The call to XSetInputFocus below has also caused trouble. In
10008 cases where the XSetInputFocus done by the WM and the one
10009 below are temporally close (on a fast machine), the call
10010 below can generate additional FocusIn events which confuse
10011 Emacs. */
10012
10013 /* Since we set WM_TAKE_FOCUS, we must call
10014 XSetInputFocus explicitly. But not if f is null,
10015 since that might be an event for a deleted frame. */
10016 if (f)
10017 {
10018 Display *d = event.xclient.display;
10019 /* Catch and ignore errors, in case window has been
10020 iconified by a window manager such as GWM. */
10021 int count = x_catch_errors (d);
10022 XSetInputFocus (d, event.xclient.window,
10023 /* The ICCCM says this is
10024 the only valid choice. */
10025 RevertToParent,
10026 event.xclient.data.l[1]);
10027 /* This is needed to detect the error
10028 if there is an error. */
10029 XSync (d, False);
10030 x_uncatch_errors (d, count);
10031 }
10032 /* Not certain about handling scroll bars here */
10033 #endif /* 0 */
10034 }
10035 else if (event.xclient.data.l[0]
10036 == dpyinfo->Xatom_wm_save_yourself)
10037 {
10038 /* Save state modify the WM_COMMAND property to
10039 something which can reinstate us. This notifies
10040 the session manager, who's looking for such a
10041 PropertyNotify. Can restart processing when
10042 a keyboard or mouse event arrives. */
10043 if (numchars > 0)
10044 {
10045 f = x_top_window_to_frame (dpyinfo,
10046 event.xclient.window);
10047
10048 /* This is just so we only give real data once
10049 for a single Emacs process. */
10050 if (f == SELECTED_FRAME ())
10051 XSetCommand (FRAME_X_DISPLAY (f),
10052 event.xclient.window,
10053 initial_argv, initial_argc);
10054 else if (f)
10055 XSetCommand (FRAME_X_DISPLAY (f),
10056 event.xclient.window,
10057 0, 0);
10058 }
10059 }
10060 else if (event.xclient.data.l[0]
10061 == dpyinfo->Xatom_wm_delete_window)
10062 {
10063 struct frame *f
10064 = x_any_window_to_frame (dpyinfo,
10065 event.xclient.window);
10066
10067 if (f)
10068 {
10069 if (numchars == 0)
10070 abort ();
10071
10072 bufp->kind = delete_window_event;
10073 XSETFRAME (bufp->frame_or_window, f);
10074 bufp->arg = Qnil;
10075 bufp++;
10076
10077 count += 1;
10078 numchars -= 1;
10079 }
10080 }
10081 }
10082 else if (event.xclient.message_type
10083 == dpyinfo->Xatom_wm_configure_denied)
10084 {
10085 }
10086 else if (event.xclient.message_type
10087 == dpyinfo->Xatom_wm_window_moved)
10088 {
10089 int new_x, new_y;
10090 struct frame *f
10091 = x_window_to_frame (dpyinfo, event.xclient.window);
10092
10093 new_x = event.xclient.data.s[0];
10094 new_y = event.xclient.data.s[1];
10095
10096 if (f)
10097 {
10098 f->output_data.x->left_pos = new_x;
10099 f->output_data.x->top_pos = new_y;
10100 }
10101 }
10102 #ifdef HACK_EDITRES
10103 else if (event.xclient.message_type
10104 == dpyinfo->Xatom_editres)
10105 {
10106 struct frame *f
10107 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10108 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10109 &event, NULL);
10110 }
10111 #endif /* HACK_EDITRES */
10112 else if ((event.xclient.message_type
10113 == dpyinfo->Xatom_DONE)
10114 || (event.xclient.message_type
10115 == dpyinfo->Xatom_PAGE))
10116 {
10117 /* Ghostview job completed. Kill it. We could
10118 reply with "Next" if we received "Page", but we
10119 currently never do because we are interested in
10120 images, only, which should have 1 page. */
10121 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10122 struct frame *f
10123 = x_window_to_frame (dpyinfo, event.xclient.window);
10124 x_kill_gs_process (pixmap, f);
10125 expose_frame (f, 0, 0, 0, 0);
10126 }
10127 #ifdef USE_TOOLKIT_SCROLL_BARS
10128 /* Scroll bar callbacks send a ClientMessage from which
10129 we construct an input_event. */
10130 else if (event.xclient.message_type
10131 == dpyinfo->Xatom_Scrollbar)
10132 {
10133 x_scroll_bar_to_input_event (&event, bufp);
10134 ++bufp, ++count, --numchars;
10135 goto out;
10136 }
10137 #endif /* USE_TOOLKIT_SCROLL_BARS */
10138 else
10139 goto OTHER;
10140 }
10141 break;
10142
10143 case SelectionNotify:
10144 #ifdef USE_X_TOOLKIT
10145 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10146 goto OTHER;
10147 #endif /* not USE_X_TOOLKIT */
10148 x_handle_selection_notify (&event.xselection);
10149 break;
10150
10151 case SelectionClear: /* Someone has grabbed ownership. */
10152 #ifdef USE_X_TOOLKIT
10153 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10154 goto OTHER;
10155 #endif /* USE_X_TOOLKIT */
10156 {
10157 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10158
10159 if (numchars == 0)
10160 abort ();
10161
10162 bufp->kind = selection_clear_event;
10163 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10164 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10165 SELECTION_EVENT_TIME (bufp) = eventp->time;
10166 bufp->frame_or_window = Qnil;
10167 bufp->arg = Qnil;
10168 bufp++;
10169
10170 count += 1;
10171 numchars -= 1;
10172 }
10173 break;
10174
10175 case SelectionRequest: /* Someone wants our selection. */
10176 #ifdef USE_X_TOOLKIT
10177 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10178 goto OTHER;
10179 #endif /* USE_X_TOOLKIT */
10180 if (x_queue_selection_requests)
10181 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10182 &event);
10183 else
10184 {
10185 XSelectionRequestEvent *eventp
10186 = (XSelectionRequestEvent *) &event;
10187
10188 if (numchars == 0)
10189 abort ();
10190
10191 bufp->kind = selection_request_event;
10192 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10193 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10194 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10195 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10196 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10197 SELECTION_EVENT_TIME (bufp) = eventp->time;
10198 bufp->frame_or_window = Qnil;
10199 bufp->arg = Qnil;
10200 bufp++;
10201
10202 count += 1;
10203 numchars -= 1;
10204 }
10205 break;
10206
10207 case PropertyNotify:
10208 #if 0 /* This is plain wrong. In the case that we are waiting for a
10209 PropertyNotify used as an ACK in incremental selection
10210 transfer, the property will be on the receiver's window. */
10211 #if defined USE_X_TOOLKIT
10212 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10213 goto OTHER;
10214 #endif
10215 #endif
10216 x_handle_property_notify (&event.xproperty);
10217 goto OTHER;
10218
10219 case ReparentNotify:
10220 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10221 if (f)
10222 {
10223 int x, y;
10224 f->output_data.x->parent_desc = event.xreparent.parent;
10225 x_real_positions (f, &x, &y);
10226 f->output_data.x->left_pos = x;
10227 f->output_data.x->top_pos = y;
10228 }
10229 break;
10230
10231 case Expose:
10232 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10233 if (f)
10234 {
10235 if (f->async_visible == 0)
10236 {
10237 f->async_visible = 1;
10238 f->async_iconified = 0;
10239 f->output_data.x->has_been_visible = 1;
10240 SET_FRAME_GARBAGED (f);
10241 }
10242 else
10243 expose_frame (x_window_to_frame (dpyinfo,
10244 event.xexpose.window),
10245 event.xexpose.x, event.xexpose.y,
10246 event.xexpose.width, event.xexpose.height);
10247 }
10248 else
10249 {
10250 #ifndef USE_TOOLKIT_SCROLL_BARS
10251 struct scroll_bar *bar;
10252 #endif
10253 #if defined USE_LUCID
10254 /* Submenus of the Lucid menu bar aren't widgets
10255 themselves, so there's no way to dispatch events
10256 to them. Recognize this case separately. */
10257 {
10258 Widget widget
10259 = x_window_to_menu_bar (event.xexpose.window);
10260 if (widget)
10261 xlwmenu_redisplay (widget);
10262 }
10263 #endif /* USE_LUCID */
10264
10265 #ifdef USE_TOOLKIT_SCROLL_BARS
10266 /* Dispatch event to the widget. */
10267 goto OTHER;
10268 #else /* not USE_TOOLKIT_SCROLL_BARS */
10269 bar = x_window_to_scroll_bar (event.xexpose.window);
10270
10271 if (bar)
10272 x_scroll_bar_expose (bar, &event);
10273 #ifdef USE_X_TOOLKIT
10274 else
10275 goto OTHER;
10276 #endif /* USE_X_TOOLKIT */
10277 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10278 }
10279 break;
10280
10281 case GraphicsExpose: /* This occurs when an XCopyArea's
10282 source area was obscured or not
10283 available. */
10284 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10285 if (f)
10286 {
10287 expose_frame (f,
10288 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10289 event.xgraphicsexpose.width,
10290 event.xgraphicsexpose.height);
10291 }
10292 #ifdef USE_X_TOOLKIT
10293 else
10294 goto OTHER;
10295 #endif /* USE_X_TOOLKIT */
10296 break;
10297
10298 case NoExpose: /* This occurs when an XCopyArea's
10299 source area was completely
10300 available. */
10301 break;
10302
10303 case UnmapNotify:
10304 /* Redo the mouse-highlight after the tooltip has gone. */
10305 if (event.xmap.window == tip_window)
10306 {
10307 tip_window = 0;
10308 redo_mouse_highlight ();
10309 }
10310
10311 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10312 if (f) /* F may no longer exist if
10313 the frame was deleted. */
10314 {
10315 /* While a frame is unmapped, display generation is
10316 disabled; you don't want to spend time updating a
10317 display that won't ever be seen. */
10318 f->async_visible = 0;
10319 /* We can't distinguish, from the event, whether the window
10320 has become iconified or invisible. So assume, if it
10321 was previously visible, than now it is iconified.
10322 But x_make_frame_invisible clears both
10323 the visible flag and the iconified flag;
10324 and that way, we know the window is not iconified now. */
10325 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10326 {
10327 f->async_iconified = 1;
10328
10329 bufp->kind = iconify_event;
10330 XSETFRAME (bufp->frame_or_window, f);
10331 bufp->arg = Qnil;
10332 bufp++;
10333 count++;
10334 numchars--;
10335 }
10336 }
10337 goto OTHER;
10338
10339 case MapNotify:
10340 if (event.xmap.window == tip_window)
10341 /* The tooltip has been drawn already. Avoid
10342 the SET_FRAME_GARBAGED below. */
10343 goto OTHER;
10344
10345 /* We use x_top_window_to_frame because map events can
10346 come for sub-windows and they don't mean that the
10347 frame is visible. */
10348 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10349 if (f)
10350 {
10351 f->async_visible = 1;
10352 f->async_iconified = 0;
10353 f->output_data.x->has_been_visible = 1;
10354
10355 /* wait_reading_process_input will notice this and update
10356 the frame's display structures. */
10357 SET_FRAME_GARBAGED (f);
10358
10359 if (f->iconified)
10360 {
10361 bufp->kind = deiconify_event;
10362 XSETFRAME (bufp->frame_or_window, f);
10363 bufp->arg = Qnil;
10364 bufp++;
10365 count++;
10366 numchars--;
10367 }
10368 else if (! NILP (Vframe_list)
10369 && ! NILP (XCDR (Vframe_list)))
10370 /* Force a redisplay sooner or later
10371 to update the frame titles
10372 in case this is the second frame. */
10373 record_asynch_buffer_change ();
10374 }
10375 goto OTHER;
10376
10377 case KeyPress:
10378 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10379
10380 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10381 if (f == 0)
10382 {
10383 /* Scroll bars consume key events, but we want
10384 the keys to go to the scroll bar's frame. */
10385 Widget widget = XtWindowToWidget (dpyinfo->display,
10386 event.xkey.window);
10387 if (widget && XmIsScrollBar (widget))
10388 {
10389 widget = XtParent (widget);
10390 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10391 }
10392 }
10393 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10394
10395 if (f != 0)
10396 {
10397 KeySym keysym, orig_keysym;
10398 /* al%imercury@uunet.uu.net says that making this 81
10399 instead of 80 fixed a bug whereby meta chars made
10400 his Emacs hang.
10401
10402 It seems that some version of XmbLookupString has
10403 a bug of not returning XBufferOverflow in
10404 status_return even if the input is too long to
10405 fit in 81 bytes. So, we must prepare sufficient
10406 bytes for copy_buffer. 513 bytes (256 chars for
10407 two-byte character set) seems to be a faily good
10408 approximation. -- 2000.8.10 handa@etl.go.jp */
10409 unsigned char copy_buffer[513];
10410 unsigned char *copy_bufptr = copy_buffer;
10411 int copy_bufsiz = sizeof (copy_buffer);
10412 int modifiers;
10413
10414 event.xkey.state
10415 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10416 extra_keyboard_modifiers);
10417 modifiers = event.xkey.state;
10418
10419 /* This will have to go some day... */
10420
10421 /* make_lispy_event turns chars into control chars.
10422 Don't do it here because XLookupString is too eager. */
10423 event.xkey.state &= ~ControlMask;
10424 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10425 | dpyinfo->super_mod_mask
10426 | dpyinfo->hyper_mod_mask
10427 | dpyinfo->alt_mod_mask);
10428
10429 /* In case Meta is ComposeCharacter,
10430 clear its status. According to Markus Ehrnsperger
10431 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10432 this enables ComposeCharacter to work whether or
10433 not it is combined with Meta. */
10434 if (modifiers & dpyinfo->meta_mod_mask)
10435 bzero (&compose_status, sizeof (compose_status));
10436
10437 #ifdef HAVE_X_I18N
10438 if (FRAME_XIC (f))
10439 {
10440 Status status_return;
10441
10442 nbytes = XmbLookupString (FRAME_XIC (f),
10443 &event.xkey, copy_bufptr,
10444 copy_bufsiz, &keysym,
10445 &status_return);
10446 if (status_return == XBufferOverflow)
10447 {
10448 copy_bufsiz = nbytes + 1;
10449 copy_bufptr = (char *) alloca (copy_bufsiz);
10450 nbytes = XmbLookupString (FRAME_XIC (f),
10451 &event.xkey, copy_bufptr,
10452 copy_bufsiz, &keysym,
10453 &status_return);
10454 }
10455
10456 if (status_return == XLookupNone)
10457 break;
10458 else if (status_return == XLookupChars)
10459 {
10460 keysym = NoSymbol;
10461 modifiers = 0;
10462 }
10463 else if (status_return != XLookupKeySym
10464 && status_return != XLookupBoth)
10465 abort ();
10466 }
10467 else
10468 nbytes = XLookupString (&event.xkey, copy_bufptr,
10469 copy_bufsiz, &keysym,
10470 &compose_status);
10471 #else
10472 nbytes = XLookupString (&event.xkey, copy_bufptr,
10473 copy_bufsiz, &keysym,
10474 &compose_status);
10475 #endif
10476
10477 orig_keysym = keysym;
10478
10479 if (numchars > 1)
10480 {
10481 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10482 || keysym == XK_Delete
10483 #ifdef XK_ISO_Left_Tab
10484 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
10485 #endif
10486 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
10487 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10488 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10489 #ifdef HPUX
10490 /* This recognizes the "extended function keys".
10491 It seems there's no cleaner way.
10492 Test IsModifierKey to avoid handling mode_switch
10493 incorrectly. */
10494 || ((unsigned) (keysym) >= XK_Select
10495 && (unsigned)(keysym) < XK_KP_Space)
10496 #endif
10497 #ifdef XK_dead_circumflex
10498 || orig_keysym == XK_dead_circumflex
10499 #endif
10500 #ifdef XK_dead_grave
10501 || orig_keysym == XK_dead_grave
10502 #endif
10503 #ifdef XK_dead_tilde
10504 || orig_keysym == XK_dead_tilde
10505 #endif
10506 #ifdef XK_dead_diaeresis
10507 || orig_keysym == XK_dead_diaeresis
10508 #endif
10509 #ifdef XK_dead_macron
10510 || orig_keysym == XK_dead_macron
10511 #endif
10512 #ifdef XK_dead_degree
10513 || orig_keysym == XK_dead_degree
10514 #endif
10515 #ifdef XK_dead_acute
10516 || orig_keysym == XK_dead_acute
10517 #endif
10518 #ifdef XK_dead_cedilla
10519 || orig_keysym == XK_dead_cedilla
10520 #endif
10521 #ifdef XK_dead_breve
10522 || orig_keysym == XK_dead_breve
10523 #endif
10524 #ifdef XK_dead_ogonek
10525 || orig_keysym == XK_dead_ogonek
10526 #endif
10527 #ifdef XK_dead_caron
10528 || orig_keysym == XK_dead_caron
10529 #endif
10530 #ifdef XK_dead_doubleacute
10531 || orig_keysym == XK_dead_doubleacute
10532 #endif
10533 #ifdef XK_dead_abovedot
10534 || orig_keysym == XK_dead_abovedot
10535 #endif
10536 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10537 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10538 /* Any "vendor-specific" key is ok. */
10539 || (orig_keysym & (1 << 28))
10540 || (keysym != NoSymbol && nbytes == 0))
10541 && ! (IsModifierKey (orig_keysym)
10542 #ifndef HAVE_X11R5
10543 #ifdef XK_Mode_switch
10544 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10545 #endif
10546 #ifdef XK_Num_Lock
10547 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10548 #endif
10549 #endif /* not HAVE_X11R5 */
10550 ))
10551 {
10552 if (temp_index == sizeof temp_buffer / sizeof (short))
10553 temp_index = 0;
10554 temp_buffer[temp_index++] = keysym;
10555 bufp->kind = non_ascii_keystroke;
10556 bufp->code = keysym;
10557 XSETFRAME (bufp->frame_or_window, f);
10558 bufp->arg = Qnil;
10559 bufp->modifiers
10560 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10561 modifiers);
10562 bufp->timestamp = event.xkey.time;
10563 bufp++;
10564 count++;
10565 numchars--;
10566 }
10567 else if (numchars > nbytes)
10568 {
10569 register int i;
10570 register int c;
10571 int nchars, len;
10572
10573 for (i = 0; i < nbytes; i++)
10574 {
10575 if (temp_index == (sizeof temp_buffer
10576 / sizeof (short)))
10577 temp_index = 0;
10578 temp_buffer[temp_index++] = copy_bufptr[i];
10579 }
10580
10581 if (/* If the event is not from XIM, */
10582 event.xkey.keycode != 0
10583 /* or the current locale doesn't request
10584 decoding of the intup data, ... */
10585 || coding.type == coding_type_raw_text
10586 || coding.type == coding_type_no_conversion)
10587 {
10588 /* ... we can use the input data as is. */
10589 nchars = nbytes;
10590 }
10591 else
10592 {
10593 /* We have to decode the input data. */
10594 int require;
10595 unsigned char *p;
10596
10597 require = decoding_buffer_size (&coding, nbytes);
10598 p = (unsigned char *) alloca (require);
10599 coding.mode |= CODING_MODE_LAST_BLOCK;
10600 decode_coding (&coding, copy_bufptr, p,
10601 nbytes, require);
10602 nbytes = coding.produced;
10603 nchars = coding.produced_char;
10604 copy_bufptr = p;
10605 }
10606
10607 /* Convert the input data to a sequence of
10608 character events. */
10609 for (i = 0; i < nbytes; i += len)
10610 {
10611 if (nchars == nbytes)
10612 c = copy_bufptr[i], len = 1;
10613 else
10614 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10615 nbytes - i, len);
10616
10617 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10618 ? ascii_keystroke
10619 : multibyte_char_keystroke);
10620 bufp->code = c;
10621 XSETFRAME (bufp->frame_or_window, f);
10622 bufp->arg = Qnil;
10623 bufp->modifiers
10624 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10625 modifiers);
10626 bufp->timestamp = event.xkey.time;
10627 bufp++;
10628 }
10629
10630 count += nchars;
10631 numchars -= nchars;
10632
10633 if (keysym == NoSymbol)
10634 break;
10635 }
10636 else
10637 abort ();
10638 }
10639 else
10640 abort ();
10641 }
10642 #ifdef HAVE_X_I18N
10643 /* Don't dispatch this event since XtDispatchEvent calls
10644 XFilterEvent, and two calls in a row may freeze the
10645 client. */
10646 break;
10647 #else
10648 goto OTHER;
10649 #endif
10650
10651 case KeyRelease:
10652 #ifdef HAVE_X_I18N
10653 /* Don't dispatch this event since XtDispatchEvent calls
10654 XFilterEvent, and two calls in a row may freeze the
10655 client. */
10656 break;
10657 #else
10658 goto OTHER;
10659 #endif
10660
10661 /* Here's a possible interpretation of the whole
10662 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10663 you get a FocusIn event, you have to get a FocusOut
10664 event before you relinquish the focus. If you
10665 haven't received a FocusIn event, then a mere
10666 LeaveNotify is enough to free you. */
10667
10668 case EnterNotify:
10669 {
10670 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10671
10672 #if 0
10673 if (event.xcrossing.focus)
10674 {
10675 /* Avoid nasty pop/raise loops. */
10676 if (f && (!(f->auto_raise)
10677 || !(f->auto_lower)
10678 || (event.xcrossing.time - enter_timestamp) > 500))
10679 {
10680 x_new_focus_frame (dpyinfo, f);
10681 enter_timestamp = event.xcrossing.time;
10682 }
10683 }
10684 else if (f == dpyinfo->x_focus_frame)
10685 x_new_focus_frame (dpyinfo, 0);
10686 #endif
10687
10688 /* EnterNotify counts as mouse movement,
10689 so update things that depend on mouse position. */
10690 if (f && !f->output_data.x->hourglass_p)
10691 note_mouse_movement (f, &event.xmotion);
10692 goto OTHER;
10693 }
10694
10695 case FocusIn:
10696 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10697 if (event.xfocus.detail != NotifyPointer)
10698 dpyinfo->x_focus_event_frame = f;
10699 if (f)
10700 {
10701 x_new_focus_frame (dpyinfo, f);
10702
10703 /* Don't stop displaying the initial startup message
10704 for a switch-frame event we don't need. */
10705 if (GC_NILP (Vterminal_frame)
10706 && GC_CONSP (Vframe_list)
10707 && !GC_NILP (XCDR (Vframe_list)))
10708 {
10709 bufp->kind = FOCUS_IN_EVENT;
10710 XSETFRAME (bufp->frame_or_window, f);
10711 bufp->arg = Qnil;
10712 ++bufp, ++count, --numchars;
10713 }
10714 }
10715
10716 #ifdef HAVE_X_I18N
10717 if (f && FRAME_XIC (f))
10718 XSetICFocus (FRAME_XIC (f));
10719 #endif
10720
10721 goto OTHER;
10722
10723 case LeaveNotify:
10724 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10725 if (f)
10726 {
10727 if (f == dpyinfo->mouse_face_mouse_frame)
10728 {
10729 /* If we move outside the frame, then we're
10730 certainly no longer on any text in the frame. */
10731 clear_mouse_face (dpyinfo);
10732 dpyinfo->mouse_face_mouse_frame = 0;
10733 }
10734
10735 /* Generate a nil HELP_EVENT to cancel a help-echo.
10736 Do it only if there's something to cancel.
10737 Otherwise, the startup message is cleared when
10738 the mouse leaves the frame. */
10739 if (any_help_event_p)
10740 {
10741 Lisp_Object frame;
10742 int n;
10743
10744 XSETFRAME (frame, f);
10745 help_echo = Qnil;
10746 n = gen_help_event (bufp, numchars,
10747 Qnil, frame, Qnil, Qnil, 0);
10748 bufp += n, count += n, numchars -= n;
10749 }
10750
10751 #if 0
10752 if (event.xcrossing.focus)
10753 x_mouse_leave (dpyinfo);
10754 else
10755 {
10756 if (f == dpyinfo->x_focus_event_frame)
10757 dpyinfo->x_focus_event_frame = 0;
10758 if (f == dpyinfo->x_focus_frame)
10759 x_new_focus_frame (dpyinfo, 0);
10760 }
10761 #endif
10762 }
10763 goto OTHER;
10764
10765 case FocusOut:
10766 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10767 if (event.xfocus.detail != NotifyPointer
10768 && f == dpyinfo->x_focus_event_frame)
10769 dpyinfo->x_focus_event_frame = 0;
10770 if (f && f == dpyinfo->x_focus_frame)
10771 x_new_focus_frame (dpyinfo, 0);
10772
10773 #ifdef HAVE_X_I18N
10774 if (f && FRAME_XIC (f))
10775 XUnsetICFocus (FRAME_XIC (f));
10776 #endif
10777
10778 goto OTHER;
10779
10780 case MotionNotify:
10781 {
10782 previous_help_echo = help_echo;
10783 help_echo = help_echo_object = help_echo_window = Qnil;
10784 help_echo_pos = -1;
10785
10786 if (dpyinfo->grabbed && last_mouse_frame
10787 && FRAME_LIVE_P (last_mouse_frame))
10788 f = last_mouse_frame;
10789 else
10790 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10791
10792 if (f)
10793 note_mouse_movement (f, &event.xmotion);
10794 else
10795 {
10796 #ifndef USE_TOOLKIT_SCROLL_BARS
10797 struct scroll_bar *bar
10798 = x_window_to_scroll_bar (event.xmotion.window);
10799
10800 if (bar)
10801 x_scroll_bar_note_movement (bar, &event);
10802 #endif /* USE_TOOLKIT_SCROLL_BARS */
10803
10804 /* If we move outside the frame, then we're
10805 certainly no longer on any text in the frame. */
10806 clear_mouse_face (dpyinfo);
10807 }
10808
10809 /* If the contents of the global variable help_echo
10810 has changed, generate a HELP_EVENT. */
10811 if (!NILP (help_echo)
10812 || !NILP (previous_help_echo))
10813 {
10814 Lisp_Object frame;
10815 int n;
10816
10817 if (f)
10818 XSETFRAME (frame, f);
10819 else
10820 frame = Qnil;
10821
10822 any_help_event_p = 1;
10823 n = gen_help_event (bufp, numchars, help_echo, frame,
10824 help_echo_window, help_echo_object,
10825 help_echo_pos);
10826 bufp += n, count += n, numchars -= n;
10827 }
10828
10829 goto OTHER;
10830 }
10831
10832 case ConfigureNotify:
10833 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10834 if (f)
10835 {
10836 #ifndef USE_X_TOOLKIT
10837 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10838 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10839
10840 /* In the toolkit version, change_frame_size
10841 is called by the code that handles resizing
10842 of the EmacsFrame widget. */
10843
10844 /* Even if the number of character rows and columns has
10845 not changed, the font size may have changed, so we need
10846 to check the pixel dimensions as well. */
10847 if (columns != f->width
10848 || rows != f->height
10849 || event.xconfigure.width != f->output_data.x->pixel_width
10850 || event.xconfigure.height != f->output_data.x->pixel_height)
10851 {
10852 change_frame_size (f, rows, columns, 0, 1, 0);
10853 SET_FRAME_GARBAGED (f);
10854 cancel_mouse_face (f);
10855 }
10856 #endif
10857
10858 f->output_data.x->pixel_width = event.xconfigure.width;
10859 f->output_data.x->pixel_height = event.xconfigure.height;
10860
10861 /* What we have now is the position of Emacs's own window.
10862 Convert that to the position of the window manager window. */
10863 x_real_positions (f, &f->output_data.x->left_pos,
10864 &f->output_data.x->top_pos);
10865
10866 #ifdef HAVE_X_I18N
10867 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10868 xic_set_statusarea (f);
10869 #endif
10870
10871 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10872 {
10873 /* Since the WM decorations come below top_pos now,
10874 we must put them below top_pos in the future. */
10875 f->output_data.x->win_gravity = NorthWestGravity;
10876 x_wm_set_size_hint (f, (long) 0, 0);
10877 }
10878 #ifdef USE_MOTIF
10879 /* Some window managers pass (0,0) as the location of
10880 the window, and the Motif event handler stores it
10881 in the emacs widget, which messes up Motif menus. */
10882 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10883 {
10884 event.xconfigure.x = f->output_data.x->widget->core.x;
10885 event.xconfigure.y = f->output_data.x->widget->core.y;
10886 }
10887 #endif /* USE_MOTIF */
10888 }
10889 goto OTHER;
10890
10891 case ButtonPress:
10892 case ButtonRelease:
10893 {
10894 /* If we decide we want to generate an event to be seen
10895 by the rest of Emacs, we put it here. */
10896 struct input_event emacs_event;
10897 int tool_bar_p = 0;
10898
10899 emacs_event.kind = no_event;
10900 bzero (&compose_status, sizeof (compose_status));
10901
10902 if (dpyinfo->grabbed
10903 && last_mouse_frame
10904 && FRAME_LIVE_P (last_mouse_frame))
10905 f = last_mouse_frame;
10906 else
10907 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10908
10909 if (f)
10910 {
10911 /* Is this in the tool-bar? */
10912 if (WINDOWP (f->tool_bar_window)
10913 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10914 {
10915 Lisp_Object window;
10916 int p, x, y;
10917
10918 x = event.xbutton.x;
10919 y = event.xbutton.y;
10920
10921 /* Set x and y. */
10922 window = window_from_coordinates (f, x, y, &p, 1);
10923 if (EQ (window, f->tool_bar_window))
10924 {
10925 x_handle_tool_bar_click (f, &event.xbutton);
10926 tool_bar_p = 1;
10927 }
10928 }
10929
10930 if (!tool_bar_p)
10931 if (!dpyinfo->x_focus_frame
10932 || f == dpyinfo->x_focus_frame)
10933 construct_mouse_click (&emacs_event, &event, f);
10934 }
10935 else
10936 {
10937 #ifndef USE_TOOLKIT_SCROLL_BARS
10938 struct scroll_bar *bar
10939 = x_window_to_scroll_bar (event.xbutton.window);
10940
10941 if (bar)
10942 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10943 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10944 }
10945
10946 if (event.type == ButtonPress)
10947 {
10948 dpyinfo->grabbed |= (1 << event.xbutton.button);
10949 last_mouse_frame = f;
10950 /* Ignore any mouse motion that happened
10951 before this event; any subsequent mouse-movement
10952 Emacs events should reflect only motion after
10953 the ButtonPress. */
10954 if (f != 0)
10955 f->mouse_moved = 0;
10956
10957 if (!tool_bar_p)
10958 last_tool_bar_item = -1;
10959 }
10960 else
10961 {
10962 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10963 }
10964
10965 if (numchars >= 1 && emacs_event.kind != no_event)
10966 {
10967 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10968 bufp++;
10969 count++;
10970 numchars--;
10971 }
10972
10973 #ifdef USE_X_TOOLKIT
10974 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10975 /* For a down-event in the menu bar,
10976 don't pass it to Xt right now.
10977 Instead, save it away
10978 and we will pass it to Xt from kbd_buffer_get_event.
10979 That way, we can run some Lisp code first. */
10980 if (f && event.type == ButtonPress
10981 /* Verify the event is really within the menu bar
10982 and not just sent to it due to grabbing. */
10983 && event.xbutton.x >= 0
10984 && event.xbutton.x < f->output_data.x->pixel_width
10985 && event.xbutton.y >= 0
10986 && event.xbutton.y < f->output_data.x->menubar_height
10987 && event.xbutton.same_screen)
10988 {
10989 SET_SAVED_BUTTON_EVENT;
10990 XSETFRAME (last_mouse_press_frame, f);
10991 }
10992 else if (event.type == ButtonPress)
10993 {
10994 last_mouse_press_frame = Qnil;
10995 goto OTHER;
10996 }
10997
10998 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10999 but I am trying to be cautious. */
11000 else if (event.type == ButtonRelease)
11001 {
11002 if (!NILP (last_mouse_press_frame))
11003 {
11004 f = XFRAME (last_mouse_press_frame);
11005 if (f->output_data.x)
11006 SET_SAVED_BUTTON_EVENT;
11007 }
11008 else
11009 goto OTHER;
11010 }
11011 #endif /* USE_MOTIF */
11012 else
11013 goto OTHER;
11014 #endif /* USE_X_TOOLKIT */
11015 }
11016 break;
11017
11018 case CirculateNotify:
11019 goto OTHER;
11020
11021 case CirculateRequest:
11022 goto OTHER;
11023
11024 case VisibilityNotify:
11025 goto OTHER;
11026
11027 case MappingNotify:
11028 /* Someone has changed the keyboard mapping - update the
11029 local cache. */
11030 switch (event.xmapping.request)
11031 {
11032 case MappingModifier:
11033 x_find_modifier_meanings (dpyinfo);
11034 /* This is meant to fall through. */
11035 case MappingKeyboard:
11036 XRefreshKeyboardMapping (&event.xmapping);
11037 }
11038 goto OTHER;
11039
11040 default:
11041 OTHER:
11042 #ifdef USE_X_TOOLKIT
11043 BLOCK_INPUT;
11044 XtDispatchEvent (&event);
11045 UNBLOCK_INPUT;
11046 #endif /* USE_X_TOOLKIT */
11047 break;
11048 }
11049 }
11050 }
11051
11052 out:;
11053
11054 /* On some systems, an X bug causes Emacs to get no more events
11055 when the window is destroyed. Detect that. (1994.) */
11056 if (! event_found)
11057 {
11058 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11059 One XNOOP in 100 loops will make Emacs terminate.
11060 B. Bretthauer, 1994 */
11061 x_noop_count++;
11062 if (x_noop_count >= 100)
11063 {
11064 x_noop_count=0;
11065
11066 if (next_noop_dpyinfo == 0)
11067 next_noop_dpyinfo = x_display_list;
11068
11069 XNoOp (next_noop_dpyinfo->display);
11070
11071 /* Each time we get here, cycle through the displays now open. */
11072 next_noop_dpyinfo = next_noop_dpyinfo->next;
11073 }
11074 }
11075
11076 /* If the focus was just given to an auto-raising frame,
11077 raise it now. */
11078 /* ??? This ought to be able to handle more than one such frame. */
11079 if (pending_autoraise_frame)
11080 {
11081 x_raise_frame (pending_autoraise_frame);
11082 pending_autoraise_frame = 0;
11083 }
11084
11085 UNBLOCK_INPUT;
11086 --handling_signal;
11087 return count;
11088 }
11089
11090
11091
11092 \f
11093 /***********************************************************************
11094 Text Cursor
11095 ***********************************************************************/
11096
11097 /* Notice if the text cursor of window W has been overwritten by a
11098 drawing operation that outputs N glyphs starting at START_X and
11099 ending at END_X in the line given by output_cursor.vpos.
11100 Coordinates are area-relative. END_X < 0 means all the rest
11101 of the line after START_X has been written. */
11102
11103 static void
11104 notice_overwritten_cursor (w, start_x, end_x)
11105 struct window *w;
11106 int start_x, end_x;
11107 {
11108 if (updated_area == TEXT_AREA
11109 && w->phys_cursor_on_p
11110 && output_cursor.vpos == w->phys_cursor.vpos
11111 && start_x <= w->phys_cursor.x
11112 && end_x > w->phys_cursor.x)
11113 w->phys_cursor_on_p = 0;
11114 }
11115
11116
11117 /* Set clipping for output in glyph row ROW. W is the window in which
11118 we operate. GC is the graphics context to set clipping in.
11119 WHOLE_LINE_P non-zero means include the areas used for truncation
11120 mark display and alike in the clipping rectangle.
11121
11122 ROW may be a text row or, e.g., a mode line. Text rows must be
11123 clipped to the interior of the window dedicated to text display,
11124 mode lines must be clipped to the whole window. */
11125
11126 static void
11127 x_clip_to_row (w, row, gc, whole_line_p)
11128 struct window *w;
11129 struct glyph_row *row;
11130 GC gc;
11131 int whole_line_p;
11132 {
11133 struct frame *f = XFRAME (WINDOW_FRAME (w));
11134 XRectangle clip_rect;
11135 int window_x, window_y, window_width, window_height;
11136
11137 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11138
11139 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11140 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11141 clip_rect.y = max (clip_rect.y, window_y);
11142 clip_rect.width = window_width;
11143 clip_rect.height = row->visible_height;
11144
11145 /* If clipping to the whole line, including trunc marks, extend
11146 the rectangle to the left and increase its width. */
11147 if (whole_line_p)
11148 {
11149 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11150 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11151 }
11152
11153 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11154 }
11155
11156
11157 /* Draw a hollow box cursor on window W in glyph row ROW. */
11158
11159 static void
11160 x_draw_hollow_cursor (w, row)
11161 struct window *w;
11162 struct glyph_row *row;
11163 {
11164 struct frame *f = XFRAME (WINDOW_FRAME (w));
11165 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11166 Display *dpy = FRAME_X_DISPLAY (f);
11167 int x, y, wd, h;
11168 XGCValues xgcv;
11169 struct glyph *cursor_glyph;
11170 GC gc;
11171
11172 /* Compute frame-relative coordinates from window-relative
11173 coordinates. */
11174 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11175 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11176 + row->ascent - w->phys_cursor_ascent);
11177 h = row->height - 1;
11178
11179 /* Get the glyph the cursor is on. If we can't tell because
11180 the current matrix is invalid or such, give up. */
11181 cursor_glyph = get_phys_cursor_glyph (w);
11182 if (cursor_glyph == NULL)
11183 return;
11184
11185 /* Compute the width of the rectangle to draw. If on a stretch
11186 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11187 rectangle as wide as the glyph, but use a canonical character
11188 width instead. */
11189 wd = cursor_glyph->pixel_width - 1;
11190 if (cursor_glyph->type == STRETCH_GLYPH
11191 && !x_stretch_cursor_p)
11192 wd = min (CANON_X_UNIT (f), wd);
11193
11194 /* The foreground of cursor_gc is typically the same as the normal
11195 background color, which can cause the cursor box to be invisible. */
11196 xgcv.foreground = f->output_data.x->cursor_pixel;
11197 if (dpyinfo->scratch_cursor_gc)
11198 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11199 else
11200 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11201 GCForeground, &xgcv);
11202 gc = dpyinfo->scratch_cursor_gc;
11203
11204 /* Set clipping, draw the rectangle, and reset clipping again. */
11205 x_clip_to_row (w, row, gc, 0);
11206 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11207 XSetClipMask (dpy, gc, None);
11208 }
11209
11210
11211 /* Draw a bar cursor on window W in glyph row ROW.
11212
11213 Implementation note: One would like to draw a bar cursor with an
11214 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11215 Unfortunately, I didn't find a font yet that has this property set.
11216 --gerd. */
11217
11218 static void
11219 x_draw_bar_cursor (w, row, width)
11220 struct window *w;
11221 struct glyph_row *row;
11222 int width;
11223 {
11224 struct frame *f = XFRAME (w->frame);
11225 struct glyph *cursor_glyph;
11226
11227 /* If cursor is out of bounds, don't draw garbage. This can happen
11228 in mini-buffer windows when switching between echo area glyphs
11229 and mini-buffer. */
11230 cursor_glyph = get_phys_cursor_glyph (w);
11231 if (cursor_glyph == NULL)
11232 return;
11233
11234 /* If on an image, draw like a normal cursor. That's usually better
11235 visible than drawing a bar, esp. if the image is large so that
11236 the bar might not be in the window. */
11237 if (cursor_glyph->type == IMAGE_GLYPH)
11238 {
11239 struct glyph_row *row;
11240 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11241 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11242 }
11243 else
11244 {
11245 Display *dpy = FRAME_X_DISPLAY (f);
11246 Window window = FRAME_X_WINDOW (f);
11247 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11248 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11249 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11250 XGCValues xgcv;
11251
11252 /* If the glyph's background equals the color we normally draw
11253 the bar cursor in, the bar cursor in its normal color is
11254 invisible. Use the glyph's foreground color instead in this
11255 case, on the assumption that the glyph's colors are chosen so
11256 that the glyph is legible. */
11257 if (face->background == f->output_data.x->cursor_pixel)
11258 xgcv.background = xgcv.foreground = face->foreground;
11259 else
11260 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11261 xgcv.graphics_exposures = 0;
11262
11263 if (gc)
11264 XChangeGC (dpy, gc, mask, &xgcv);
11265 else
11266 {
11267 gc = XCreateGC (dpy, window, mask, &xgcv);
11268 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11269 }
11270
11271 if (width < 0)
11272 width = f->output_data.x->cursor_width;
11273 width = min (cursor_glyph->pixel_width, width);
11274
11275 x_clip_to_row (w, row, gc, 0);
11276 XFillRectangle (dpy, window, gc,
11277 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11278 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11279 width, row->height);
11280 XSetClipMask (dpy, gc, None);
11281 }
11282 }
11283
11284
11285 /* Clear the cursor of window W to background color, and mark the
11286 cursor as not shown. This is used when the text where the cursor
11287 is is about to be rewritten. */
11288
11289 static void
11290 x_clear_cursor (w)
11291 struct window *w;
11292 {
11293 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11294 x_update_window_cursor (w, 0);
11295 }
11296
11297
11298 /* Draw the cursor glyph of window W in glyph row ROW. See the
11299 comment of x_draw_glyphs for the meaning of HL. */
11300
11301 static void
11302 x_draw_phys_cursor_glyph (w, row, hl)
11303 struct window *w;
11304 struct glyph_row *row;
11305 enum draw_glyphs_face hl;
11306 {
11307 /* If cursor hpos is out of bounds, don't draw garbage. This can
11308 happen in mini-buffer windows when switching between echo area
11309 glyphs and mini-buffer. */
11310 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11311 {
11312 int on_p = w->phys_cursor_on_p;
11313
11314 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11315 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11316 hl, 0);
11317 w->phys_cursor_on_p = on_p;
11318
11319 /* When we erase the cursor, and ROW is overlapped by other
11320 rows, make sure that these overlapping parts of other rows
11321 are redrawn. */
11322 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11323 {
11324 if (row > w->current_matrix->rows
11325 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11326 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11327
11328 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11329 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11330 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11331 }
11332 }
11333 }
11334
11335
11336 /* Erase the image of a cursor of window W from the screen. */
11337
11338 static void
11339 x_erase_phys_cursor (w)
11340 struct window *w;
11341 {
11342 struct frame *f = XFRAME (w->frame);
11343 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11344 int hpos = w->phys_cursor.hpos;
11345 int vpos = w->phys_cursor.vpos;
11346 int mouse_face_here_p = 0;
11347 struct glyph_matrix *active_glyphs = w->current_matrix;
11348 struct glyph_row *cursor_row;
11349 struct glyph *cursor_glyph;
11350 enum draw_glyphs_face hl;
11351
11352 /* No cursor displayed or row invalidated => nothing to do on the
11353 screen. */
11354 if (w->phys_cursor_type == NO_CURSOR)
11355 goto mark_cursor_off;
11356
11357 /* VPOS >= active_glyphs->nrows means that window has been resized.
11358 Don't bother to erase the cursor. */
11359 if (vpos >= active_glyphs->nrows)
11360 goto mark_cursor_off;
11361
11362 /* If row containing cursor is marked invalid, there is nothing we
11363 can do. */
11364 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11365 if (!cursor_row->enabled_p)
11366 goto mark_cursor_off;
11367
11368 /* This can happen when the new row is shorter than the old one.
11369 In this case, either x_draw_glyphs or clear_end_of_line
11370 should have cleared the cursor. Note that we wouldn't be
11371 able to erase the cursor in this case because we don't have a
11372 cursor glyph at hand. */
11373 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11374 goto mark_cursor_off;
11375
11376 /* If the cursor is in the mouse face area, redisplay that when
11377 we clear the cursor. */
11378 if (! NILP (dpyinfo->mouse_face_window)
11379 && w == XWINDOW (dpyinfo->mouse_face_window)
11380 && (vpos > dpyinfo->mouse_face_beg_row
11381 || (vpos == dpyinfo->mouse_face_beg_row
11382 && hpos >= dpyinfo->mouse_face_beg_col))
11383 && (vpos < dpyinfo->mouse_face_end_row
11384 || (vpos == dpyinfo->mouse_face_end_row
11385 && hpos < dpyinfo->mouse_face_end_col))
11386 /* Don't redraw the cursor's spot in mouse face if it is at the
11387 end of a line (on a newline). The cursor appears there, but
11388 mouse highlighting does not. */
11389 && cursor_row->used[TEXT_AREA] > hpos)
11390 mouse_face_here_p = 1;
11391
11392 /* Maybe clear the display under the cursor. */
11393 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11394 {
11395 int x;
11396 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11397
11398 cursor_glyph = get_phys_cursor_glyph (w);
11399 if (cursor_glyph == NULL)
11400 goto mark_cursor_off;
11401
11402 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11403
11404 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11405 x,
11406 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11407 cursor_row->y)),
11408 cursor_glyph->pixel_width,
11409 cursor_row->visible_height,
11410 False);
11411 }
11412
11413 /* Erase the cursor by redrawing the character underneath it. */
11414 if (mouse_face_here_p)
11415 hl = DRAW_MOUSE_FACE;
11416 else
11417 hl = DRAW_NORMAL_TEXT;
11418 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11419
11420 mark_cursor_off:
11421 w->phys_cursor_on_p = 0;
11422 w->phys_cursor_type = NO_CURSOR;
11423 }
11424
11425
11426 /* Non-zero if physical cursor of window W is within mouse face. */
11427
11428 static int
11429 cursor_in_mouse_face_p (w)
11430 struct window *w;
11431 {
11432 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11433 int in_mouse_face = 0;
11434
11435 if (WINDOWP (dpyinfo->mouse_face_window)
11436 && XWINDOW (dpyinfo->mouse_face_window) == w)
11437 {
11438 int hpos = w->phys_cursor.hpos;
11439 int vpos = w->phys_cursor.vpos;
11440
11441 if (vpos >= dpyinfo->mouse_face_beg_row
11442 && vpos <= dpyinfo->mouse_face_end_row
11443 && (vpos > dpyinfo->mouse_face_beg_row
11444 || hpos >= dpyinfo->mouse_face_beg_col)
11445 && (vpos < dpyinfo->mouse_face_end_row
11446 || hpos < dpyinfo->mouse_face_end_col
11447 || dpyinfo->mouse_face_past_end))
11448 in_mouse_face = 1;
11449 }
11450
11451 return in_mouse_face;
11452 }
11453
11454
11455 /* Display or clear cursor of window W. If ON is zero, clear the
11456 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11457 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11458
11459 void
11460 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11461 struct window *w;
11462 int on, hpos, vpos, x, y;
11463 {
11464 struct frame *f = XFRAME (w->frame);
11465 int new_cursor_type;
11466 int new_cursor_width;
11467 struct glyph_matrix *current_glyphs;
11468 struct glyph_row *glyph_row;
11469 struct glyph *glyph;
11470 int cursor_non_selected;
11471
11472 /* This is pointless on invisible frames, and dangerous on garbaged
11473 windows and frames; in the latter case, the frame or window may
11474 be in the midst of changing its size, and x and y may be off the
11475 window. */
11476 if (! FRAME_VISIBLE_P (f)
11477 || FRAME_GARBAGED_P (f)
11478 || vpos >= w->current_matrix->nrows
11479 || hpos >= w->current_matrix->matrix_w)
11480 return;
11481
11482 /* If cursor is off and we want it off, return quickly. */
11483 if (!on && !w->phys_cursor_on_p)
11484 return;
11485
11486 current_glyphs = w->current_matrix;
11487 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11488 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11489
11490 /* If cursor row is not enabled, we don't really know where to
11491 display the cursor. */
11492 if (!glyph_row->enabled_p)
11493 {
11494 w->phys_cursor_on_p = 0;
11495 return;
11496 }
11497
11498 xassert (interrupt_input_blocked);
11499
11500 /* Set new_cursor_type to the cursor we want to be displayed. In a
11501 mini-buffer window, we want the cursor only to appear if we are
11502 reading input from this window. For the selected window, we want
11503 the cursor type given by the frame parameter. If explicitly
11504 marked off, draw no cursor. In all other cases, we want a hollow
11505 box cursor. */
11506 cursor_non_selected
11507 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
11508 w->buffer));
11509 new_cursor_width = -1;
11510 if (cursor_in_echo_area
11511 && FRAME_HAS_MINIBUF_P (f)
11512 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11513 {
11514 if (w == XWINDOW (echo_area_window))
11515 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11516 else if (cursor_non_selected)
11517 new_cursor_type = HOLLOW_BOX_CURSOR;
11518 else
11519 new_cursor_type = NO_CURSOR;
11520 }
11521 else
11522 {
11523 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11524 || w != XWINDOW (f->selected_window))
11525 {
11526 if ((MINI_WINDOW_P (w) && minibuf_level == 0)
11527 || !cursor_non_selected
11528 || NILP (XBUFFER (w->buffer)->cursor_type))
11529 new_cursor_type = NO_CURSOR;
11530 else
11531 new_cursor_type = HOLLOW_BOX_CURSOR;
11532 }
11533 else if (w->cursor_off_p)
11534 new_cursor_type = NO_CURSOR;
11535 else
11536 {
11537 struct buffer *b = XBUFFER (w->buffer);
11538
11539 if (EQ (b->cursor_type, Qt))
11540 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11541 else
11542 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11543 &new_cursor_width);
11544 }
11545 }
11546
11547 /* If cursor is currently being shown and we don't want it to be or
11548 it is in the wrong place, or the cursor type is not what we want,
11549 erase it. */
11550 if (w->phys_cursor_on_p
11551 && (!on
11552 || w->phys_cursor.x != x
11553 || w->phys_cursor.y != y
11554 || new_cursor_type != w->phys_cursor_type))
11555 x_erase_phys_cursor (w);
11556
11557 /* If the cursor is now invisible and we want it to be visible,
11558 display it. */
11559 if (on && !w->phys_cursor_on_p)
11560 {
11561 w->phys_cursor_ascent = glyph_row->ascent;
11562 w->phys_cursor_height = glyph_row->height;
11563
11564 /* Set phys_cursor_.* before x_draw_.* is called because some
11565 of them may need the information. */
11566 w->phys_cursor.x = x;
11567 w->phys_cursor.y = glyph_row->y;
11568 w->phys_cursor.hpos = hpos;
11569 w->phys_cursor.vpos = vpos;
11570 w->phys_cursor_type = new_cursor_type;
11571 w->phys_cursor_on_p = 1;
11572
11573 switch (new_cursor_type)
11574 {
11575 case HOLLOW_BOX_CURSOR:
11576 x_draw_hollow_cursor (w, glyph_row);
11577 break;
11578
11579 case FILLED_BOX_CURSOR:
11580 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11581 break;
11582
11583 case BAR_CURSOR:
11584 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11585 break;
11586
11587 case NO_CURSOR:
11588 break;
11589
11590 default:
11591 abort ();
11592 }
11593
11594 #ifdef HAVE_X_I18N
11595 if (w == XWINDOW (f->selected_window))
11596 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11597 xic_set_preeditarea (w, x, y);
11598 #endif
11599 }
11600
11601 #ifndef XFlush
11602 if (updating_frame != f)
11603 XFlush (FRAME_X_DISPLAY (f));
11604 #endif
11605 }
11606
11607
11608 /* Display the cursor on window W, or clear it. X and Y are window
11609 relative pixel coordinates. HPOS and VPOS are glyph matrix
11610 positions. If W is not the selected window, display a hollow
11611 cursor. ON non-zero means display the cursor at X, Y which
11612 correspond to HPOS, VPOS, otherwise it is cleared. */
11613
11614 void
11615 x_display_cursor (w, on, hpos, vpos, x, y)
11616 struct window *w;
11617 int on, hpos, vpos, x, y;
11618 {
11619 BLOCK_INPUT;
11620 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11621 UNBLOCK_INPUT;
11622 }
11623
11624
11625 /* Display the cursor on window W, or clear it, according to ON_P.
11626 Don't change the cursor's position. */
11627
11628 void
11629 x_update_cursor (f, on_p)
11630 struct frame *f;
11631 {
11632 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11633 }
11634
11635
11636 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11637 in the window tree rooted at W. */
11638
11639 static void
11640 x_update_cursor_in_window_tree (w, on_p)
11641 struct window *w;
11642 int on_p;
11643 {
11644 while (w)
11645 {
11646 if (!NILP (w->hchild))
11647 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11648 else if (!NILP (w->vchild))
11649 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11650 else
11651 x_update_window_cursor (w, on_p);
11652
11653 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11654 }
11655 }
11656
11657
11658 /* Switch the display of W's cursor on or off, according to the value
11659 of ON. */
11660
11661 static void
11662 x_update_window_cursor (w, on)
11663 struct window *w;
11664 int on;
11665 {
11666 /* Don't update cursor in windows whose frame is in the process
11667 of being deleted. */
11668 if (w->current_matrix)
11669 {
11670 BLOCK_INPUT;
11671 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11672 w->phys_cursor.x, w->phys_cursor.y);
11673 UNBLOCK_INPUT;
11674 }
11675 }
11676
11677
11678
11679 \f
11680 /* Icons. */
11681
11682 /* Make the x-window of frame F use the gnu icon bitmap. */
11683
11684 int
11685 x_bitmap_icon (f, file)
11686 struct frame *f;
11687 Lisp_Object file;
11688 {
11689 int bitmap_id;
11690
11691 if (FRAME_X_WINDOW (f) == 0)
11692 return 1;
11693
11694 /* Free up our existing icon bitmap if any. */
11695 if (f->output_data.x->icon_bitmap > 0)
11696 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11697 f->output_data.x->icon_bitmap = 0;
11698
11699 if (STRINGP (file))
11700 bitmap_id = x_create_bitmap_from_file (f, file);
11701 else
11702 {
11703 /* Create the GNU bitmap if necessary. */
11704 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11705 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11706 = x_create_bitmap_from_data (f, gnu_bits,
11707 gnu_width, gnu_height);
11708
11709 /* The first time we create the GNU bitmap,
11710 this increments the ref-count one extra time.
11711 As a result, the GNU bitmap is never freed.
11712 That way, we don't have to worry about allocating it again. */
11713 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11714
11715 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11716 }
11717
11718 x_wm_set_icon_pixmap (f, bitmap_id);
11719 f->output_data.x->icon_bitmap = bitmap_id;
11720
11721 return 0;
11722 }
11723
11724
11725 /* Make the x-window of frame F use a rectangle with text.
11726 Use ICON_NAME as the text. */
11727
11728 int
11729 x_text_icon (f, icon_name)
11730 struct frame *f;
11731 char *icon_name;
11732 {
11733 if (FRAME_X_WINDOW (f) == 0)
11734 return 1;
11735
11736 #ifdef HAVE_X11R4
11737 {
11738 XTextProperty text;
11739 text.value = (unsigned char *) icon_name;
11740 text.encoding = XA_STRING;
11741 text.format = 8;
11742 text.nitems = strlen (icon_name);
11743 #ifdef USE_X_TOOLKIT
11744 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11745 &text);
11746 #else /* not USE_X_TOOLKIT */
11747 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11748 #endif /* not USE_X_TOOLKIT */
11749 }
11750 #else /* not HAVE_X11R4 */
11751 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11752 #endif /* not HAVE_X11R4 */
11753
11754 if (f->output_data.x->icon_bitmap > 0)
11755 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11756 f->output_data.x->icon_bitmap = 0;
11757 x_wm_set_icon_pixmap (f, 0);
11758
11759 return 0;
11760 }
11761 \f
11762 #define X_ERROR_MESSAGE_SIZE 200
11763
11764 /* If non-nil, this should be a string.
11765 It means catch X errors and store the error message in this string. */
11766
11767 static Lisp_Object x_error_message_string;
11768
11769 /* An X error handler which stores the error message in
11770 x_error_message_string. This is called from x_error_handler if
11771 x_catch_errors is in effect. */
11772
11773 static void
11774 x_error_catcher (display, error)
11775 Display *display;
11776 XErrorEvent *error;
11777 {
11778 XGetErrorText (display, error->error_code,
11779 XSTRING (x_error_message_string)->data,
11780 X_ERROR_MESSAGE_SIZE);
11781 }
11782
11783 /* Begin trapping X errors for display DPY. Actually we trap X errors
11784 for all displays, but DPY should be the display you are actually
11785 operating on.
11786
11787 After calling this function, X protocol errors no longer cause
11788 Emacs to exit; instead, they are recorded in the string
11789 stored in x_error_message_string.
11790
11791 Calling x_check_errors signals an Emacs error if an X error has
11792 occurred since the last call to x_catch_errors or x_check_errors.
11793
11794 Calling x_uncatch_errors resumes the normal error handling. */
11795
11796 void x_check_errors ();
11797 static Lisp_Object x_catch_errors_unwind ();
11798
11799 int
11800 x_catch_errors (dpy)
11801 Display *dpy;
11802 {
11803 int count = specpdl_ptr - specpdl;
11804
11805 /* Make sure any errors from previous requests have been dealt with. */
11806 XSync (dpy, False);
11807
11808 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11809
11810 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11811 XSTRING (x_error_message_string)->data[0] = 0;
11812
11813 return count;
11814 }
11815
11816 /* Unbind the binding that we made to check for X errors. */
11817
11818 static Lisp_Object
11819 x_catch_errors_unwind (old_val)
11820 Lisp_Object old_val;
11821 {
11822 x_error_message_string = old_val;
11823 return Qnil;
11824 }
11825
11826 /* If any X protocol errors have arrived since the last call to
11827 x_catch_errors or x_check_errors, signal an Emacs error using
11828 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11829
11830 void
11831 x_check_errors (dpy, format)
11832 Display *dpy;
11833 char *format;
11834 {
11835 /* Make sure to catch any errors incurred so far. */
11836 XSync (dpy, False);
11837
11838 if (XSTRING (x_error_message_string)->data[0])
11839 error (format, XSTRING (x_error_message_string)->data);
11840 }
11841
11842 /* Nonzero if we had any X protocol errors
11843 since we did x_catch_errors on DPY. */
11844
11845 int
11846 x_had_errors_p (dpy)
11847 Display *dpy;
11848 {
11849 /* Make sure to catch any errors incurred so far. */
11850 XSync (dpy, False);
11851
11852 return XSTRING (x_error_message_string)->data[0] != 0;
11853 }
11854
11855 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11856
11857 void
11858 x_clear_errors (dpy)
11859 Display *dpy;
11860 {
11861 XSTRING (x_error_message_string)->data[0] = 0;
11862 }
11863
11864 /* Stop catching X protocol errors and let them make Emacs die.
11865 DPY should be the display that was passed to x_catch_errors.
11866 COUNT should be the value that was returned by
11867 the corresponding call to x_catch_errors. */
11868
11869 void
11870 x_uncatch_errors (dpy, count)
11871 Display *dpy;
11872 int count;
11873 {
11874 unbind_to (count, Qnil);
11875 }
11876
11877 #if 0
11878 static unsigned int x_wire_count;
11879 x_trace_wire ()
11880 {
11881 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11882 }
11883 #endif /* ! 0 */
11884
11885 \f
11886 /* Handle SIGPIPE, which can happen when the connection to a server
11887 simply goes away. SIGPIPE is handled by x_connection_signal.
11888 Don't need to do anything, because the write which caused the
11889 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11890 which will do the appropriate cleanup for us. */
11891
11892 static SIGTYPE
11893 x_connection_signal (signalnum) /* If we don't have an argument, */
11894 int signalnum; /* some compilers complain in signal calls. */
11895 {
11896 #ifdef USG
11897 /* USG systems forget handlers when they are used;
11898 must reestablish each time */
11899 signal (signalnum, x_connection_signal);
11900 #endif /* USG */
11901 }
11902
11903 \f
11904 /************************************************************************
11905 Handling X errors
11906 ************************************************************************/
11907
11908 /* Error message passed to x_connection_closed. */
11909
11910 static char *error_msg;
11911
11912 /* Function installed as fatal_error_signal_hook in
11913 x_connection_closed. Print the X error message, and exit normally,
11914 instead of dumping core when XtCloseDisplay fails. */
11915
11916 static void
11917 x_fatal_error_signal ()
11918 {
11919 fprintf (stderr, "%s\n", error_msg);
11920 exit (70);
11921 }
11922
11923 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11924 the text of an error message that lead to the connection loss. */
11925
11926 static SIGTYPE
11927 x_connection_closed (dpy, error_message)
11928 Display *dpy;
11929 char *error_message;
11930 {
11931 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
11932 Lisp_Object frame, tail;
11933 int count;
11934
11935 error_msg = (char *) alloca (strlen (error_message) + 1);
11936 strcpy (error_msg, error_message);
11937 handling_signal = 0;
11938
11939 /* Prevent being called recursively because of an error condition
11940 below. Otherwise, we might end up with printing ``can't find per
11941 display information'' in the recursive call instead of printing
11942 the original message here. */
11943 count = x_catch_errors (dpy);
11944
11945 /* We have to close the display to inform Xt that it doesn't
11946 exist anymore. If we don't, Xt will continue to wait for
11947 events from the display. As a consequence, a sequence of
11948
11949 M-x make-frame-on-display RET :1 RET
11950 ...kill the new frame, so that we get an IO error...
11951 M-x make-frame-on-display RET :1 RET
11952
11953 will indefinitely wait in Xt for events for display `:1', opened
11954 in the first class to make-frame-on-display.
11955
11956 Closing the display is reported to lead to a bus error on
11957 OpenWindows in certain situations. I suspect that is a bug
11958 in OpenWindows. I don't know how to cicumvent it here. */
11959
11960 #ifdef USE_X_TOOLKIT
11961 /* If DPYINFO is null, this means we didn't open the display
11962 in the first place, so don't try to close it. */
11963 if (dpyinfo)
11964 {
11965 extern void (*fatal_error_signal_hook) P_ ((void));
11966 fatal_error_signal_hook = x_fatal_error_signal;
11967 XtCloseDisplay (dpy);
11968 fatal_error_signal_hook = NULL;
11969 }
11970 #endif
11971
11972 /* Indicate that this display is dead. */
11973 if (dpyinfo)
11974 dpyinfo->display = 0;
11975
11976 /* First delete frames whose mini-buffers are on frames
11977 that are on the dead display. */
11978 FOR_EACH_FRAME (tail, frame)
11979 {
11980 Lisp_Object minibuf_frame;
11981 minibuf_frame
11982 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11983 if (FRAME_X_P (XFRAME (frame))
11984 && FRAME_X_P (XFRAME (minibuf_frame))
11985 && ! EQ (frame, minibuf_frame)
11986 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11987 Fdelete_frame (frame, Qt);
11988 }
11989
11990 /* Now delete all remaining frames on the dead display.
11991 We are now sure none of these is used as the mini-buffer
11992 for another frame that we need to delete. */
11993 FOR_EACH_FRAME (tail, frame)
11994 if (FRAME_X_P (XFRAME (frame))
11995 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11996 {
11997 /* Set this to t so that Fdelete_frame won't get confused
11998 trying to find a replacement. */
11999 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12000 Fdelete_frame (frame, Qt);
12001 }
12002
12003 if (dpyinfo)
12004 x_delete_display (dpyinfo);
12005
12006 x_uncatch_errors (dpy, count);
12007
12008 if (x_display_list == 0)
12009 {
12010 fprintf (stderr, "%s\n", error_msg);
12011 shut_down_emacs (0, 0, Qnil);
12012 exit (70);
12013 }
12014
12015 /* Ordinary stack unwind doesn't deal with these. */
12016 #ifdef SIGIO
12017 sigunblock (sigmask (SIGIO));
12018 #endif
12019 sigunblock (sigmask (SIGALRM));
12020 TOTALLY_UNBLOCK_INPUT;
12021
12022 clear_waiting_for_input ();
12023 error ("%s", error_msg);
12024 }
12025
12026
12027 /* This is the usual handler for X protocol errors.
12028 It kills all frames on the display that we got the error for.
12029 If that was the only one, it prints an error message and kills Emacs. */
12030
12031 static void
12032 x_error_quitter (display, error)
12033 Display *display;
12034 XErrorEvent *error;
12035 {
12036 char buf[256], buf1[356];
12037
12038 /* Note that there is no real way portable across R3/R4 to get the
12039 original error handler. */
12040
12041 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12042 sprintf (buf1, "X protocol error: %s on protocol request %d",
12043 buf, error->request_code);
12044 x_connection_closed (display, buf1);
12045 }
12046
12047
12048 /* This is the first-level handler for X protocol errors.
12049 It calls x_error_quitter or x_error_catcher. */
12050
12051 static int
12052 x_error_handler (display, error)
12053 Display *display;
12054 XErrorEvent *error;
12055 {
12056 if (! NILP (x_error_message_string))
12057 x_error_catcher (display, error);
12058 else
12059 x_error_quitter (display, error);
12060 return 0;
12061 }
12062
12063 /* This is the handler for X IO errors, always.
12064 It kills all frames on the display that we lost touch with.
12065 If that was the only one, it prints an error message and kills Emacs. */
12066
12067 static int
12068 x_io_error_quitter (display)
12069 Display *display;
12070 {
12071 char buf[256];
12072
12073 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12074 x_connection_closed (display, buf);
12075 return 0;
12076 }
12077 \f
12078 /* Changing the font of the frame. */
12079
12080 /* Give frame F the font named FONTNAME as its default font, and
12081 return the full name of that font. FONTNAME may be a wildcard
12082 pattern; in that case, we choose some font that fits the pattern.
12083 The return value shows which font we chose. */
12084
12085 Lisp_Object
12086 x_new_font (f, fontname)
12087 struct frame *f;
12088 register char *fontname;
12089 {
12090 struct font_info *fontp
12091 = FS_LOAD_FONT (f, 0, fontname, -1);
12092
12093 if (!fontp)
12094 return Qnil;
12095
12096 f->output_data.x->font = (XFontStruct *) (fontp->font);
12097 f->output_data.x->baseline_offset = fontp->baseline_offset;
12098 f->output_data.x->fontset = -1;
12099
12100 /* Compute the scroll bar width in character columns. */
12101 if (f->scroll_bar_pixel_width > 0)
12102 {
12103 int wid = FONT_WIDTH (f->output_data.x->font);
12104 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12105 }
12106 else
12107 {
12108 int wid = FONT_WIDTH (f->output_data.x->font);
12109 f->scroll_bar_cols = (14 + wid - 1) / wid;
12110 }
12111
12112 /* Now make the frame display the given font. */
12113 if (FRAME_X_WINDOW (f) != 0)
12114 {
12115 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12116 f->output_data.x->font->fid);
12117 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12118 f->output_data.x->font->fid);
12119 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12120 f->output_data.x->font->fid);
12121
12122 frame_update_line_height (f);
12123
12124 /* Don't change the size of a tip frame; there's no point in
12125 doing it because it's done in Fx_show_tip, and it leads to
12126 problems because the tip frame has no widget. */
12127 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12128 x_set_window_size (f, 0, f->width, f->height);
12129 }
12130 else
12131 /* If we are setting a new frame's font for the first time,
12132 there are no faces yet, so this font's height is the line height. */
12133 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12134
12135 return build_string (fontp->full_name);
12136 }
12137
12138 /* Give frame F the fontset named FONTSETNAME as its default font, and
12139 return the full name of that fontset. FONTSETNAME may be a wildcard
12140 pattern; in that case, we choose some fontset that fits the pattern.
12141 The return value shows which fontset we chose. */
12142
12143 Lisp_Object
12144 x_new_fontset (f, fontsetname)
12145 struct frame *f;
12146 char *fontsetname;
12147 {
12148 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12149 Lisp_Object result;
12150
12151 if (fontset < 0)
12152 return Qnil;
12153
12154 if (f->output_data.x->fontset == fontset)
12155 /* This fontset is already set in frame F. There's nothing more
12156 to do. */
12157 return fontset_name (fontset);
12158
12159 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
12160
12161 if (!STRINGP (result))
12162 /* Can't load ASCII font. */
12163 return Qnil;
12164
12165 /* Since x_new_font doesn't update any fontset information, do it now. */
12166 f->output_data.x->fontset = fontset;
12167
12168 #ifdef HAVE_X_I18N
12169 if (FRAME_XIC (f)
12170 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12171 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
12172 #endif
12173
12174 return build_string (fontsetname);
12175 }
12176
12177 \f
12178 /***********************************************************************
12179 X Input Methods
12180 ***********************************************************************/
12181
12182 #ifdef HAVE_X_I18N
12183
12184 #ifdef HAVE_X11R6
12185
12186 /* XIM destroy callback function, which is called whenever the
12187 connection to input method XIM dies. CLIENT_DATA contains a
12188 pointer to the x_display_info structure corresponding to XIM. */
12189
12190 static void
12191 xim_destroy_callback (xim, client_data, call_data)
12192 XIM xim;
12193 XPointer client_data;
12194 XPointer call_data;
12195 {
12196 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12197 Lisp_Object frame, tail;
12198
12199 BLOCK_INPUT;
12200
12201 /* No need to call XDestroyIC.. */
12202 FOR_EACH_FRAME (tail, frame)
12203 {
12204 struct frame *f = XFRAME (frame);
12205 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12206 {
12207 FRAME_XIC (f) = NULL;
12208 if (FRAME_XIC_FONTSET (f))
12209 {
12210 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12211 FRAME_XIC_FONTSET (f) = NULL;
12212 }
12213 }
12214 }
12215
12216 /* No need to call XCloseIM. */
12217 dpyinfo->xim = NULL;
12218 XFree (dpyinfo->xim_styles);
12219 UNBLOCK_INPUT;
12220 }
12221
12222 #endif /* HAVE_X11R6 */
12223
12224 /* Open the connection to the XIM server on display DPYINFO.
12225 RESOURCE_NAME is the resource name Emacs uses. */
12226
12227 static void
12228 xim_open_dpy (dpyinfo, resource_name)
12229 struct x_display_info *dpyinfo;
12230 char *resource_name;
12231 {
12232 #ifdef USE_XIM
12233 XIM xim;
12234
12235 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12236 dpyinfo->xim = xim;
12237
12238 if (xim)
12239 {
12240 #ifdef HAVE_X11R6
12241 XIMCallback destroy;
12242 #endif
12243
12244 /* Get supported styles and XIM values. */
12245 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12246
12247 #ifdef HAVE_X11R6
12248 destroy.callback = xim_destroy_callback;
12249 destroy.client_data = (XPointer)dpyinfo;
12250 /* This isn't prototyped in OSF 5.0. */
12251 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12252 #endif
12253 }
12254
12255 #else /* not USE_XIM */
12256 dpyinfo->xim = NULL;
12257 #endif /* not USE_XIM */
12258 }
12259
12260
12261 #ifdef HAVE_X11R6_XIM
12262
12263 struct xim_inst_t
12264 {
12265 struct x_display_info *dpyinfo;
12266 char *resource_name;
12267 };
12268
12269 /* XIM instantiate callback function, which is called whenever an XIM
12270 server is available. DISPLAY is teh display of the XIM.
12271 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12272 when the callback was registered. */
12273
12274 static void
12275 xim_instantiate_callback (display, client_data, call_data)
12276 Display *display;
12277 XPointer client_data;
12278 XPointer call_data;
12279 {
12280 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12281 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12282
12283 /* We don't support multiple XIM connections. */
12284 if (dpyinfo->xim)
12285 return;
12286
12287 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12288
12289 /* Create XIC for the existing frames on the same display, as long
12290 as they have no XIC. */
12291 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12292 {
12293 Lisp_Object tail, frame;
12294
12295 BLOCK_INPUT;
12296 FOR_EACH_FRAME (tail, frame)
12297 {
12298 struct frame *f = XFRAME (frame);
12299
12300 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12301 if (FRAME_XIC (f) == NULL)
12302 {
12303 create_frame_xic (f);
12304 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12305 xic_set_statusarea (f);
12306 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12307 {
12308 struct window *w = XWINDOW (f->selected_window);
12309 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12310 }
12311 }
12312 }
12313
12314 UNBLOCK_INPUT;
12315 }
12316 }
12317
12318 #endif /* HAVE_X11R6_XIM */
12319
12320
12321 /* Open a connection to the XIM server on display DPYINFO.
12322 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12323 connection only at the first time. On X11R6, open the connection
12324 in the XIM instantiate callback function. */
12325
12326 static void
12327 xim_initialize (dpyinfo, resource_name)
12328 struct x_display_info *dpyinfo;
12329 char *resource_name;
12330 {
12331 #ifdef USE_XIM
12332 #ifdef HAVE_X11R6_XIM
12333 struct xim_inst_t *xim_inst;
12334 int len;
12335
12336 dpyinfo->xim = NULL;
12337 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12338 xim_inst->dpyinfo = dpyinfo;
12339 len = strlen (resource_name);
12340 xim_inst->resource_name = (char *) xmalloc (len + 1);
12341 bcopy (resource_name, xim_inst->resource_name, len + 1);
12342 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12343 resource_name, EMACS_CLASS,
12344 xim_instantiate_callback,
12345 /* Fixme: This is XPointer in
12346 XFree86 but (XPointer *) on
12347 Tru64, at least. */
12348 (XPointer) xim_inst);
12349 #else /* not HAVE_X11R6_XIM */
12350 dpyinfo->xim = NULL;
12351 xim_open_dpy (dpyinfo, resource_name);
12352 #endif /* not HAVE_X11R6_XIM */
12353
12354 #else /* not USE_XIM */
12355 dpyinfo->xim = NULL;
12356 #endif /* not USE_XIM */
12357 }
12358
12359
12360 /* Close the connection to the XIM server on display DPYINFO. */
12361
12362 static void
12363 xim_close_dpy (dpyinfo)
12364 struct x_display_info *dpyinfo;
12365 {
12366 #ifdef USE_XIM
12367 #ifdef HAVE_X11R6_XIM
12368 if (dpyinfo->display)
12369 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12370 NULL, EMACS_CLASS,
12371 xim_instantiate_callback, NULL);
12372 #endif /* not HAVE_X11R6_XIM */
12373 if (dpyinfo->display)
12374 XCloseIM (dpyinfo->xim);
12375 dpyinfo->xim = NULL;
12376 XFree (dpyinfo->xim_styles);
12377 #endif /* USE_XIM */
12378 }
12379
12380 #endif /* not HAVE_X11R6_XIM */
12381
12382
12383 \f
12384 /* Calculate the absolute position in frame F
12385 from its current recorded position values and gravity. */
12386
12387 void
12388 x_calc_absolute_position (f)
12389 struct frame *f;
12390 {
12391 Window child;
12392 int win_x = 0, win_y = 0;
12393 int flags = f->output_data.x->size_hint_flags;
12394 int this_window;
12395
12396 /* We have nothing to do if the current position
12397 is already for the top-left corner. */
12398 if (! ((flags & XNegative) || (flags & YNegative)))
12399 return;
12400
12401 #ifdef USE_X_TOOLKIT
12402 this_window = XtWindow (f->output_data.x->widget);
12403 #else
12404 this_window = FRAME_X_WINDOW (f);
12405 #endif
12406
12407 /* Find the position of the outside upper-left corner of
12408 the inner window, with respect to the outer window.
12409 But do this only if we will need the results. */
12410 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12411 {
12412 int count;
12413
12414 BLOCK_INPUT;
12415 count = x_catch_errors (FRAME_X_DISPLAY (f));
12416 while (1)
12417 {
12418 x_clear_errors (FRAME_X_DISPLAY (f));
12419 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12420
12421 /* From-window, to-window. */
12422 this_window,
12423 f->output_data.x->parent_desc,
12424
12425 /* From-position, to-position. */
12426 0, 0, &win_x, &win_y,
12427
12428 /* Child of win. */
12429 &child);
12430 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12431 {
12432 Window newroot, newparent = 0xdeadbeef;
12433 Window *newchildren;
12434 unsigned int nchildren;
12435
12436 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12437 &newparent, &newchildren, &nchildren))
12438 break;
12439
12440 XFree ((char *) newchildren);
12441
12442 f->output_data.x->parent_desc = newparent;
12443 }
12444 else
12445 break;
12446 }
12447
12448 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12449 UNBLOCK_INPUT;
12450 }
12451
12452 /* Treat negative positions as relative to the leftmost bottommost
12453 position that fits on the screen. */
12454 if (flags & XNegative)
12455 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12456 - 2 * f->output_data.x->border_width - win_x
12457 - PIXEL_WIDTH (f)
12458 + f->output_data.x->left_pos);
12459
12460 {
12461 int height = PIXEL_HEIGHT (f);
12462
12463 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12464 /* Something is fishy here. When using Motif, starting Emacs with
12465 `-g -0-0', the frame appears too low by a few pixels.
12466
12467 This seems to be so because initially, while Emacs is starting,
12468 the column widget's height and the frame's pixel height are
12469 different. The column widget's height is the right one. In
12470 later invocations, when Emacs is up, the frame's pixel height
12471 is right, though.
12472
12473 It's not obvious where the initial small difference comes from.
12474 2000-12-01, gerd. */
12475
12476 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12477 #endif
12478
12479 if (flags & YNegative)
12480 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12481 - 2 * f->output_data.x->border_width
12482 - win_y
12483 - height
12484 + f->output_data.x->top_pos);
12485 }
12486
12487 /* The left_pos and top_pos
12488 are now relative to the top and left screen edges,
12489 so the flags should correspond. */
12490 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12491 }
12492
12493 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12494 to really change the position, and 0 when calling from
12495 x_make_frame_visible (in that case, XOFF and YOFF are the current
12496 position values). It is -1 when calling from x_set_frame_parameters,
12497 which means, do adjust for borders but don't change the gravity. */
12498
12499 void
12500 x_set_offset (f, xoff, yoff, change_gravity)
12501 struct frame *f;
12502 register int xoff, yoff;
12503 int change_gravity;
12504 {
12505 int modified_top, modified_left;
12506
12507 if (change_gravity > 0)
12508 {
12509 f->output_data.x->top_pos = yoff;
12510 f->output_data.x->left_pos = xoff;
12511 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12512 if (xoff < 0)
12513 f->output_data.x->size_hint_flags |= XNegative;
12514 if (yoff < 0)
12515 f->output_data.x->size_hint_flags |= YNegative;
12516 f->output_data.x->win_gravity = NorthWestGravity;
12517 }
12518 x_calc_absolute_position (f);
12519
12520 BLOCK_INPUT;
12521 x_wm_set_size_hint (f, (long) 0, 0);
12522
12523 modified_left = f->output_data.x->left_pos;
12524 modified_top = f->output_data.x->top_pos;
12525 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12526 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12527 /* It is a mystery why we need to add the border_width here
12528 when the frame is already visible, but experiment says we do. */
12529 if (change_gravity != 0)
12530 {
12531 modified_left += f->output_data.x->border_width;
12532 modified_top += f->output_data.x->border_width;
12533 }
12534 #endif
12535
12536 #ifdef USE_X_TOOLKIT
12537 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12538 modified_left, modified_top);
12539 #else /* not USE_X_TOOLKIT */
12540 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12541 modified_left, modified_top);
12542 #endif /* not USE_X_TOOLKIT */
12543 UNBLOCK_INPUT;
12544 }
12545
12546
12547 /* Change the size of frame F's X window to COLS/ROWS in the case F
12548 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12549 top-left-corner window gravity for this size change and subsequent
12550 size changes. Otherwise we leave the window gravity unchanged. */
12551
12552 static void
12553 x_set_window_size_1 (f, change_gravity, cols, rows)
12554 struct frame *f;
12555 int change_gravity;
12556 int cols, rows;
12557 {
12558 int pixelwidth, pixelheight;
12559
12560 check_frame_size (f, &rows, &cols);
12561 f->output_data.x->vertical_scroll_bar_extra
12562 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12563 ? 0
12564 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12565 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12566 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12567 f->output_data.x->fringes_extra
12568 = FRAME_FRINGE_WIDTH (f);
12569 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12570 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12571
12572 f->output_data.x->win_gravity = NorthWestGravity;
12573 x_wm_set_size_hint (f, (long) 0, 0);
12574
12575 XSync (FRAME_X_DISPLAY (f), False);
12576 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12577 pixelwidth, pixelheight);
12578
12579 /* Now, strictly speaking, we can't be sure that this is accurate,
12580 but the window manager will get around to dealing with the size
12581 change request eventually, and we'll hear how it went when the
12582 ConfigureNotify event gets here.
12583
12584 We could just not bother storing any of this information here,
12585 and let the ConfigureNotify event set everything up, but that
12586 might be kind of confusing to the Lisp code, since size changes
12587 wouldn't be reported in the frame parameters until some random
12588 point in the future when the ConfigureNotify event arrives.
12589
12590 We pass 1 for DELAY since we can't run Lisp code inside of
12591 a BLOCK_INPUT. */
12592 change_frame_size (f, rows, cols, 0, 1, 0);
12593 PIXEL_WIDTH (f) = pixelwidth;
12594 PIXEL_HEIGHT (f) = pixelheight;
12595
12596 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12597 receive in the ConfigureNotify event; if we get what we asked
12598 for, then the event won't cause the screen to become garbaged, so
12599 we have to make sure to do it here. */
12600 SET_FRAME_GARBAGED (f);
12601
12602 XFlush (FRAME_X_DISPLAY (f));
12603 }
12604
12605
12606 /* Call this to change the size of frame F's x-window.
12607 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12608 for this size change and subsequent size changes.
12609 Otherwise we leave the window gravity unchanged. */
12610
12611 void
12612 x_set_window_size (f, change_gravity, cols, rows)
12613 struct frame *f;
12614 int change_gravity;
12615 int cols, rows;
12616 {
12617 BLOCK_INPUT;
12618
12619 #ifdef USE_X_TOOLKIT
12620
12621 if (f->output_data.x->widget != NULL)
12622 {
12623 /* The x and y position of the widget is clobbered by the
12624 call to XtSetValues within EmacsFrameSetCharSize.
12625 This is a real kludge, but I don't understand Xt so I can't
12626 figure out a correct fix. Can anyone else tell me? -- rms. */
12627 int xpos = f->output_data.x->widget->core.x;
12628 int ypos = f->output_data.x->widget->core.y;
12629 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12630 f->output_data.x->widget->core.x = xpos;
12631 f->output_data.x->widget->core.y = ypos;
12632 }
12633 else
12634 x_set_window_size_1 (f, change_gravity, cols, rows);
12635
12636 #else /* not USE_X_TOOLKIT */
12637
12638 x_set_window_size_1 (f, change_gravity, cols, rows);
12639
12640 #endif /* not USE_X_TOOLKIT */
12641
12642 /* If cursor was outside the new size, mark it as off. */
12643 mark_window_cursors_off (XWINDOW (f->root_window));
12644
12645 /* Clear out any recollection of where the mouse highlighting was,
12646 since it might be in a place that's outside the new frame size.
12647 Actually checking whether it is outside is a pain in the neck,
12648 so don't try--just let the highlighting be done afresh with new size. */
12649 cancel_mouse_face (f);
12650
12651 UNBLOCK_INPUT;
12652 }
12653 \f
12654 /* Mouse warping. */
12655
12656 void
12657 x_set_mouse_position (f, x, y)
12658 struct frame *f;
12659 int x, y;
12660 {
12661 int pix_x, pix_y;
12662
12663 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12664 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12665
12666 if (pix_x < 0) pix_x = 0;
12667 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12668
12669 if (pix_y < 0) pix_y = 0;
12670 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12671
12672 BLOCK_INPUT;
12673
12674 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12675 0, 0, 0, 0, pix_x, pix_y);
12676 UNBLOCK_INPUT;
12677 }
12678
12679 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12680
12681 void
12682 x_set_mouse_pixel_position (f, pix_x, pix_y)
12683 struct frame *f;
12684 int pix_x, pix_y;
12685 {
12686 BLOCK_INPUT;
12687
12688 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12689 0, 0, 0, 0, pix_x, pix_y);
12690 UNBLOCK_INPUT;
12691 }
12692 \f
12693 /* focus shifting, raising and lowering. */
12694
12695 void
12696 x_focus_on_frame (f)
12697 struct frame *f;
12698 {
12699 #if 0 /* This proves to be unpleasant. */
12700 x_raise_frame (f);
12701 #endif
12702 #if 0
12703 /* I don't think that the ICCCM allows programs to do things like this
12704 without the interaction of the window manager. Whatever you end up
12705 doing with this code, do it to x_unfocus_frame too. */
12706 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12707 RevertToPointerRoot, CurrentTime);
12708 #endif /* ! 0 */
12709 }
12710
12711 void
12712 x_unfocus_frame (f)
12713 struct frame *f;
12714 {
12715 #if 0
12716 /* Look at the remarks in x_focus_on_frame. */
12717 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
12718 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
12719 RevertToPointerRoot, CurrentTime);
12720 #endif /* ! 0 */
12721 }
12722
12723 /* Raise frame F. */
12724
12725 void
12726 x_raise_frame (f)
12727 struct frame *f;
12728 {
12729 if (f->async_visible)
12730 {
12731 BLOCK_INPUT;
12732 #ifdef USE_X_TOOLKIT
12733 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12734 #else /* not USE_X_TOOLKIT */
12735 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12736 #endif /* not USE_X_TOOLKIT */
12737 XFlush (FRAME_X_DISPLAY (f));
12738 UNBLOCK_INPUT;
12739 }
12740 }
12741
12742 /* Lower frame F. */
12743
12744 void
12745 x_lower_frame (f)
12746 struct frame *f;
12747 {
12748 if (f->async_visible)
12749 {
12750 BLOCK_INPUT;
12751 #ifdef USE_X_TOOLKIT
12752 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12753 #else /* not USE_X_TOOLKIT */
12754 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12755 #endif /* not USE_X_TOOLKIT */
12756 XFlush (FRAME_X_DISPLAY (f));
12757 UNBLOCK_INPUT;
12758 }
12759 }
12760
12761 static void
12762 XTframe_raise_lower (f, raise_flag)
12763 FRAME_PTR f;
12764 int raise_flag;
12765 {
12766 if (raise_flag)
12767 x_raise_frame (f);
12768 else
12769 x_lower_frame (f);
12770 }
12771 \f
12772 /* Change of visibility. */
12773
12774 /* This tries to wait until the frame is really visible.
12775 However, if the window manager asks the user where to position
12776 the frame, this will return before the user finishes doing that.
12777 The frame will not actually be visible at that time,
12778 but it will become visible later when the window manager
12779 finishes with it. */
12780
12781 void
12782 x_make_frame_visible (f)
12783 struct frame *f;
12784 {
12785 Lisp_Object type;
12786 int original_top, original_left;
12787 int retry_count = 2;
12788
12789 retry:
12790
12791 BLOCK_INPUT;
12792
12793 type = x_icon_type (f);
12794 if (!NILP (type))
12795 x_bitmap_icon (f, type);
12796
12797 if (! FRAME_VISIBLE_P (f))
12798 {
12799 /* We test FRAME_GARBAGED_P here to make sure we don't
12800 call x_set_offset a second time
12801 if we get to x_make_frame_visible a second time
12802 before the window gets really visible. */
12803 if (! FRAME_ICONIFIED_P (f)
12804 && ! f->output_data.x->asked_for_visible)
12805 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12806
12807 f->output_data.x->asked_for_visible = 1;
12808
12809 if (! EQ (Vx_no_window_manager, Qt))
12810 x_wm_set_window_state (f, NormalState);
12811 #ifdef USE_X_TOOLKIT
12812 /* This was XtPopup, but that did nothing for an iconified frame. */
12813 XtMapWidget (f->output_data.x->widget);
12814 #else /* not USE_X_TOOLKIT */
12815 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12816 #endif /* not USE_X_TOOLKIT */
12817 #if 0 /* This seems to bring back scroll bars in the wrong places
12818 if the window configuration has changed. They seem
12819 to come back ok without this. */
12820 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12821 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12822 #endif
12823 }
12824
12825 XFlush (FRAME_X_DISPLAY (f));
12826
12827 /* Synchronize to ensure Emacs knows the frame is visible
12828 before we do anything else. We do this loop with input not blocked
12829 so that incoming events are handled. */
12830 {
12831 Lisp_Object frame;
12832 int count;
12833 /* This must be before UNBLOCK_INPUT
12834 since events that arrive in response to the actions above
12835 will set it when they are handled. */
12836 int previously_visible = f->output_data.x->has_been_visible;
12837
12838 original_left = f->output_data.x->left_pos;
12839 original_top = f->output_data.x->top_pos;
12840
12841 /* This must come after we set COUNT. */
12842 UNBLOCK_INPUT;
12843
12844 /* We unblock here so that arriving X events are processed. */
12845
12846 /* Now move the window back to where it was "supposed to be".
12847 But don't do it if the gravity is negative.
12848 When the gravity is negative, this uses a position
12849 that is 3 pixels too low. Perhaps that's really the border width.
12850
12851 Don't do this if the window has never been visible before,
12852 because the window manager may choose the position
12853 and we don't want to override it. */
12854
12855 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12856 && f->output_data.x->win_gravity == NorthWestGravity
12857 && previously_visible)
12858 {
12859 Drawable rootw;
12860 int x, y;
12861 unsigned int width, height, border, depth;
12862
12863 BLOCK_INPUT;
12864
12865 /* On some window managers (such as FVWM) moving an existing
12866 window, even to the same place, causes the window manager
12867 to introduce an offset. This can cause the window to move
12868 to an unexpected location. Check the geometry (a little
12869 slow here) and then verify that the window is in the right
12870 place. If the window is not in the right place, move it
12871 there, and take the potential window manager hit. */
12872 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12873 &rootw, &x, &y, &width, &height, &border, &depth);
12874
12875 if (original_left != x || original_top != y)
12876 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12877 original_left, original_top);
12878
12879 UNBLOCK_INPUT;
12880 }
12881
12882 XSETFRAME (frame, f);
12883
12884 /* Wait until the frame is visible. Process X events until a
12885 MapNotify event has been seen, or until we think we won't get a
12886 MapNotify at all.. */
12887 for (count = input_signal_count + 10;
12888 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12889 {
12890 /* Force processing of queued events. */
12891 x_sync (f);
12892
12893 /* Machines that do polling rather than SIGIO have been
12894 observed to go into a busy-wait here. So we'll fake an
12895 alarm signal to let the handler know that there's something
12896 to be read. We used to raise a real alarm, but it seems
12897 that the handler isn't always enabled here. This is
12898 probably a bug. */
12899 if (input_polling_used ())
12900 {
12901 /* It could be confusing if a real alarm arrives while
12902 processing the fake one. Turn it off and let the
12903 handler reset it. */
12904 extern void poll_for_input_1 P_ ((void));
12905 int old_poll_suppress_count = poll_suppress_count;
12906 poll_suppress_count = 1;
12907 poll_for_input_1 ();
12908 poll_suppress_count = old_poll_suppress_count;
12909 }
12910
12911 /* See if a MapNotify event has been processed. */
12912 FRAME_SAMPLE_VISIBILITY (f);
12913 }
12914
12915 /* 2000-09-28: In
12916
12917 (let ((f (selected-frame)))
12918 (iconify-frame f)
12919 (raise-frame f))
12920
12921 the frame is not raised with various window managers on
12922 FreeBSD, Linux and Solaris. It turns out that, for some
12923 unknown reason, the call to XtMapWidget is completely ignored.
12924 Mapping the widget a second time works. */
12925
12926 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12927 goto retry;
12928 }
12929 }
12930
12931 /* Change from mapped state to withdrawn state. */
12932
12933 /* Make the frame visible (mapped and not iconified). */
12934
12935 void
12936 x_make_frame_invisible (f)
12937 struct frame *f;
12938 {
12939 Window window;
12940
12941 #ifdef USE_X_TOOLKIT
12942 /* Use the frame's outermost window, not the one we normally draw on. */
12943 window = XtWindow (f->output_data.x->widget);
12944 #else /* not USE_X_TOOLKIT */
12945 window = FRAME_X_WINDOW (f);
12946 #endif /* not USE_X_TOOLKIT */
12947
12948 /* Don't keep the highlight on an invisible frame. */
12949 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12950 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12951
12952 #if 0/* This might add unreliability; I don't trust it -- rms. */
12953 if (! f->async_visible && ! f->async_iconified)
12954 return;
12955 #endif
12956
12957 BLOCK_INPUT;
12958
12959 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12960 that the current position of the window is user-specified, rather than
12961 program-specified, so that when the window is mapped again, it will be
12962 placed at the same location, without forcing the user to position it
12963 by hand again (they have already done that once for this window.) */
12964 x_wm_set_size_hint (f, (long) 0, 1);
12965
12966 #ifdef HAVE_X11R4
12967
12968 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12969 DefaultScreen (FRAME_X_DISPLAY (f))))
12970 {
12971 UNBLOCK_INPUT_RESIGNAL;
12972 error ("Can't notify window manager of window withdrawal");
12973 }
12974 #else /* ! defined (HAVE_X11R4) */
12975
12976 /* Tell the window manager what we're going to do. */
12977 if (! EQ (Vx_no_window_manager, Qt))
12978 {
12979 XEvent unmap;
12980
12981 unmap.xunmap.type = UnmapNotify;
12982 unmap.xunmap.window = window;
12983 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12984 unmap.xunmap.from_configure = False;
12985 if (! XSendEvent (FRAME_X_DISPLAY (f),
12986 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12987 False,
12988 SubstructureRedirectMaskSubstructureNotifyMask,
12989 &unmap))
12990 {
12991 UNBLOCK_INPUT_RESIGNAL;
12992 error ("Can't notify window manager of withdrawal");
12993 }
12994 }
12995
12996 /* Unmap the window ourselves. Cheeky! */
12997 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12998 #endif /* ! defined (HAVE_X11R4) */
12999
13000 /* We can't distinguish this from iconification
13001 just by the event that we get from the server.
13002 So we can't win using the usual strategy of letting
13003 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13004 and synchronize with the server to make sure we agree. */
13005 f->visible = 0;
13006 FRAME_ICONIFIED_P (f) = 0;
13007 f->async_visible = 0;
13008 f->async_iconified = 0;
13009
13010 x_sync (f);
13011
13012 UNBLOCK_INPUT;
13013 }
13014
13015 /* Change window state from mapped to iconified. */
13016
13017 void
13018 x_iconify_frame (f)
13019 struct frame *f;
13020 {
13021 int result;
13022 Lisp_Object type;
13023
13024 /* Don't keep the highlight on an invisible frame. */
13025 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13026 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13027
13028 if (f->async_iconified)
13029 return;
13030
13031 BLOCK_INPUT;
13032
13033 FRAME_SAMPLE_VISIBILITY (f);
13034
13035 type = x_icon_type (f);
13036 if (!NILP (type))
13037 x_bitmap_icon (f, type);
13038
13039 #ifdef USE_X_TOOLKIT
13040
13041 if (! FRAME_VISIBLE_P (f))
13042 {
13043 if (! EQ (Vx_no_window_manager, Qt))
13044 x_wm_set_window_state (f, IconicState);
13045 /* This was XtPopup, but that did nothing for an iconified frame. */
13046 XtMapWidget (f->output_data.x->widget);
13047 /* The server won't give us any event to indicate
13048 that an invisible frame was changed to an icon,
13049 so we have to record it here. */
13050 f->iconified = 1;
13051 f->visible = 1;
13052 f->async_iconified = 1;
13053 f->async_visible = 0;
13054 UNBLOCK_INPUT;
13055 return;
13056 }
13057
13058 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13059 XtWindow (f->output_data.x->widget),
13060 DefaultScreen (FRAME_X_DISPLAY (f)));
13061 UNBLOCK_INPUT;
13062
13063 if (!result)
13064 error ("Can't notify window manager of iconification");
13065
13066 f->async_iconified = 1;
13067 f->async_visible = 0;
13068
13069
13070 BLOCK_INPUT;
13071 XFlush (FRAME_X_DISPLAY (f));
13072 UNBLOCK_INPUT;
13073 #else /* not USE_X_TOOLKIT */
13074
13075 /* Make sure the X server knows where the window should be positioned,
13076 in case the user deiconifies with the window manager. */
13077 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13078 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13079
13080 /* Since we don't know which revision of X we're running, we'll use both
13081 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13082
13083 /* X11R4: send a ClientMessage to the window manager using the
13084 WM_CHANGE_STATE type. */
13085 {
13086 XEvent message;
13087
13088 message.xclient.window = FRAME_X_WINDOW (f);
13089 message.xclient.type = ClientMessage;
13090 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13091 message.xclient.format = 32;
13092 message.xclient.data.l[0] = IconicState;
13093
13094 if (! XSendEvent (FRAME_X_DISPLAY (f),
13095 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13096 False,
13097 SubstructureRedirectMask | SubstructureNotifyMask,
13098 &message))
13099 {
13100 UNBLOCK_INPUT_RESIGNAL;
13101 error ("Can't notify window manager of iconification");
13102 }
13103 }
13104
13105 /* X11R3: set the initial_state field of the window manager hints to
13106 IconicState. */
13107 x_wm_set_window_state (f, IconicState);
13108
13109 if (!FRAME_VISIBLE_P (f))
13110 {
13111 /* If the frame was withdrawn, before, we must map it. */
13112 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13113 }
13114
13115 f->async_iconified = 1;
13116 f->async_visible = 0;
13117
13118 XFlush (FRAME_X_DISPLAY (f));
13119 UNBLOCK_INPUT;
13120 #endif /* not USE_X_TOOLKIT */
13121 }
13122
13123 \f
13124 /* Free X resources of frame F. */
13125
13126 void
13127 x_free_frame_resources (f)
13128 struct frame *f;
13129 {
13130 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13131
13132 BLOCK_INPUT;
13133
13134 /* If a display connection is dead, don't try sending more
13135 commands to the X server. */
13136 if (dpyinfo->display)
13137 {
13138 if (f->output_data.x->icon_desc)
13139 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13140
13141 #ifdef HAVE_X_I18N
13142 if (FRAME_XIC (f))
13143 free_frame_xic (f);
13144 #endif
13145
13146 if (FRAME_X_WINDOW (f))
13147 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13148
13149 #ifdef USE_X_TOOLKIT
13150 if (f->output_data.x->widget)
13151 {
13152 XtDestroyWidget (f->output_data.x->widget);
13153 f->output_data.x->widget = NULL;
13154 }
13155 free_frame_menubar (f);
13156 #endif /* USE_X_TOOLKIT */
13157
13158 unload_color (f, f->output_data.x->foreground_pixel);
13159 unload_color (f, f->output_data.x->background_pixel);
13160 unload_color (f, f->output_data.x->cursor_pixel);
13161 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13162 unload_color (f, f->output_data.x->border_pixel);
13163 unload_color (f, f->output_data.x->mouse_pixel);
13164
13165 if (f->output_data.x->scroll_bar_background_pixel != -1)
13166 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13167 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13168 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13169 #ifdef USE_TOOLKIT_SCROLL_BARS
13170 /* Scrollbar shadow colors. */
13171 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13172 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13173 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13174 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13175 #endif /* USE_TOOLKIT_SCROLL_BARS */
13176 if (f->output_data.x->white_relief.allocated_p)
13177 unload_color (f, f->output_data.x->white_relief.pixel);
13178 if (f->output_data.x->black_relief.allocated_p)
13179 unload_color (f, f->output_data.x->black_relief.pixel);
13180
13181 if (FRAME_FACE_CACHE (f))
13182 free_frame_faces (f);
13183
13184 x_free_gcs (f);
13185 XFlush (FRAME_X_DISPLAY (f));
13186 }
13187
13188 if (f->output_data.x->saved_menu_event)
13189 xfree (f->output_data.x->saved_menu_event);
13190
13191 xfree (f->output_data.x);
13192 f->output_data.x = NULL;
13193
13194 if (f == dpyinfo->x_focus_frame)
13195 dpyinfo->x_focus_frame = 0;
13196 if (f == dpyinfo->x_focus_event_frame)
13197 dpyinfo->x_focus_event_frame = 0;
13198 if (f == dpyinfo->x_highlight_frame)
13199 dpyinfo->x_highlight_frame = 0;
13200
13201 if (f == dpyinfo->mouse_face_mouse_frame)
13202 {
13203 dpyinfo->mouse_face_beg_row
13204 = dpyinfo->mouse_face_beg_col = -1;
13205 dpyinfo->mouse_face_end_row
13206 = dpyinfo->mouse_face_end_col = -1;
13207 dpyinfo->mouse_face_window = Qnil;
13208 dpyinfo->mouse_face_deferred_gc = 0;
13209 dpyinfo->mouse_face_mouse_frame = 0;
13210 }
13211
13212 UNBLOCK_INPUT;
13213 }
13214
13215
13216 /* Destroy the X window of frame F. */
13217
13218 void
13219 x_destroy_window (f)
13220 struct frame *f;
13221 {
13222 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13223
13224 /* If a display connection is dead, don't try sending more
13225 commands to the X server. */
13226 if (dpyinfo->display != 0)
13227 x_free_frame_resources (f);
13228
13229 dpyinfo->reference_count--;
13230 }
13231
13232 \f
13233 /* Setting window manager hints. */
13234
13235 /* Set the normal size hints for the window manager, for frame F.
13236 FLAGS is the flags word to use--or 0 meaning preserve the flags
13237 that the window now has.
13238 If USER_POSITION is nonzero, we set the USPosition
13239 flag (this is useful when FLAGS is 0). */
13240
13241 void
13242 x_wm_set_size_hint (f, flags, user_position)
13243 struct frame *f;
13244 long flags;
13245 int user_position;
13246 {
13247 XSizeHints size_hints;
13248
13249 #ifdef USE_X_TOOLKIT
13250 Arg al[2];
13251 int ac = 0;
13252 Dimension widget_width, widget_height;
13253 Window window = XtWindow (f->output_data.x->widget);
13254 #else /* not USE_X_TOOLKIT */
13255 Window window = FRAME_X_WINDOW (f);
13256 #endif /* not USE_X_TOOLKIT */
13257
13258 /* Setting PMaxSize caused various problems. */
13259 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13260
13261 size_hints.x = f->output_data.x->left_pos;
13262 size_hints.y = f->output_data.x->top_pos;
13263
13264 #ifdef USE_X_TOOLKIT
13265 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13266 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13267 XtGetValues (f->output_data.x->widget, al, ac);
13268 size_hints.height = widget_height;
13269 size_hints.width = widget_width;
13270 #else /* not USE_X_TOOLKIT */
13271 size_hints.height = PIXEL_HEIGHT (f);
13272 size_hints.width = PIXEL_WIDTH (f);
13273 #endif /* not USE_X_TOOLKIT */
13274
13275 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13276 size_hints.height_inc = f->output_data.x->line_height;
13277 size_hints.max_width
13278 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13279 size_hints.max_height
13280 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13281
13282 /* Calculate the base and minimum sizes.
13283
13284 (When we use the X toolkit, we don't do it here.
13285 Instead we copy the values that the widgets are using, below.) */
13286 #ifndef USE_X_TOOLKIT
13287 {
13288 int base_width, base_height;
13289 int min_rows = 0, min_cols = 0;
13290
13291 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13292 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13293
13294 check_frame_size (f, &min_rows, &min_cols);
13295
13296 /* The window manager uses the base width hints to calculate the
13297 current number of rows and columns in the frame while
13298 resizing; min_width and min_height aren't useful for this
13299 purpose, since they might not give the dimensions for a
13300 zero-row, zero-column frame.
13301
13302 We use the base_width and base_height members if we have
13303 them; otherwise, we set the min_width and min_height members
13304 to the size for a zero x zero frame. */
13305
13306 #ifdef HAVE_X11R4
13307 size_hints.flags |= PBaseSize;
13308 size_hints.base_width = base_width;
13309 size_hints.base_height = base_height;
13310 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13311 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13312 #else
13313 size_hints.min_width = base_width;
13314 size_hints.min_height = base_height;
13315 #endif
13316 }
13317
13318 /* If we don't need the old flags, we don't need the old hint at all. */
13319 if (flags)
13320 {
13321 size_hints.flags |= flags;
13322 goto no_read;
13323 }
13324 #endif /* not USE_X_TOOLKIT */
13325
13326 {
13327 XSizeHints hints; /* Sometimes I hate X Windows... */
13328 long supplied_return;
13329 int value;
13330
13331 #ifdef HAVE_X11R4
13332 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13333 &supplied_return);
13334 #else
13335 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13336 #endif
13337
13338 #ifdef USE_X_TOOLKIT
13339 size_hints.base_height = hints.base_height;
13340 size_hints.base_width = hints.base_width;
13341 size_hints.min_height = hints.min_height;
13342 size_hints.min_width = hints.min_width;
13343 #endif
13344
13345 if (flags)
13346 size_hints.flags |= flags;
13347 else
13348 {
13349 if (value == 0)
13350 hints.flags = 0;
13351 if (hints.flags & PSize)
13352 size_hints.flags |= PSize;
13353 if (hints.flags & PPosition)
13354 size_hints.flags |= PPosition;
13355 if (hints.flags & USPosition)
13356 size_hints.flags |= USPosition;
13357 if (hints.flags & USSize)
13358 size_hints.flags |= USSize;
13359 }
13360 }
13361
13362 #ifndef USE_X_TOOLKIT
13363 no_read:
13364 #endif
13365
13366 #ifdef PWinGravity
13367 size_hints.win_gravity = f->output_data.x->win_gravity;
13368 size_hints.flags |= PWinGravity;
13369
13370 if (user_position)
13371 {
13372 size_hints.flags &= ~ PPosition;
13373 size_hints.flags |= USPosition;
13374 }
13375 #endif /* PWinGravity */
13376
13377 #ifdef HAVE_X11R4
13378 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13379 #else
13380 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13381 #endif
13382 }
13383
13384 /* Used for IconicState or NormalState */
13385
13386 void
13387 x_wm_set_window_state (f, state)
13388 struct frame *f;
13389 int state;
13390 {
13391 #ifdef USE_X_TOOLKIT
13392 Arg al[1];
13393
13394 XtSetArg (al[0], XtNinitialState, state);
13395 XtSetValues (f->output_data.x->widget, al, 1);
13396 #else /* not USE_X_TOOLKIT */
13397 Window window = FRAME_X_WINDOW (f);
13398
13399 f->output_data.x->wm_hints.flags |= StateHint;
13400 f->output_data.x->wm_hints.initial_state = state;
13401
13402 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13403 #endif /* not USE_X_TOOLKIT */
13404 }
13405
13406 void
13407 x_wm_set_icon_pixmap (f, pixmap_id)
13408 struct frame *f;
13409 int pixmap_id;
13410 {
13411 Pixmap icon_pixmap;
13412
13413 #ifndef USE_X_TOOLKIT
13414 Window window = FRAME_X_WINDOW (f);
13415 #endif
13416
13417 if (pixmap_id > 0)
13418 {
13419 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13420 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13421 }
13422 else
13423 {
13424 /* It seems there is no way to turn off use of an icon pixmap.
13425 The following line does it, only if no icon has yet been created,
13426 for some window managers. But with mwm it crashes.
13427 Some people say it should clear the IconPixmapHint bit in this case,
13428 but that doesn't work, and the X consortium said it isn't the
13429 right thing at all. Since there is no way to win,
13430 best to explicitly give up. */
13431 #if 0
13432 f->output_data.x->wm_hints.icon_pixmap = None;
13433 #else
13434 return;
13435 #endif
13436 }
13437
13438 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13439
13440 {
13441 Arg al[1];
13442 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13443 XtSetValues (f->output_data.x->widget, al, 1);
13444 }
13445
13446 #else /* not USE_X_TOOLKIT */
13447
13448 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13449 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13450
13451 #endif /* not USE_X_TOOLKIT */
13452 }
13453
13454 void
13455 x_wm_set_icon_position (f, icon_x, icon_y)
13456 struct frame *f;
13457 int icon_x, icon_y;
13458 {
13459 #ifdef USE_X_TOOLKIT
13460 Window window = XtWindow (f->output_data.x->widget);
13461 #else
13462 Window window = FRAME_X_WINDOW (f);
13463 #endif
13464
13465 f->output_data.x->wm_hints.flags |= IconPositionHint;
13466 f->output_data.x->wm_hints.icon_x = icon_x;
13467 f->output_data.x->wm_hints.icon_y = icon_y;
13468
13469 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13470 }
13471
13472 \f
13473 /***********************************************************************
13474 Fonts
13475 ***********************************************************************/
13476
13477 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13478
13479 struct font_info *
13480 x_get_font_info (f, font_idx)
13481 FRAME_PTR f;
13482 int font_idx;
13483 {
13484 return (FRAME_X_FONT_TABLE (f) + font_idx);
13485 }
13486
13487
13488 /* Return a list of names of available fonts matching PATTERN on frame F.
13489
13490 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13491 to be listed.
13492
13493 SIZE < 0 means include scalable fonts.
13494
13495 Frame F null means we have not yet created any frame on X, and
13496 consult the first display in x_display_list. MAXNAMES sets a limit
13497 on how many fonts to match. */
13498
13499 Lisp_Object
13500 x_list_fonts (f, pattern, size, maxnames)
13501 struct frame *f;
13502 Lisp_Object pattern;
13503 int size;
13504 int maxnames;
13505 {
13506 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13507 Lisp_Object tem, second_best;
13508 struct x_display_info *dpyinfo
13509 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13510 Display *dpy = dpyinfo->display;
13511 int try_XLoadQueryFont = 0;
13512 int count;
13513 int allow_scalable_fonts_p = 0;
13514
13515 if (size < 0)
13516 {
13517 allow_scalable_fonts_p = 1;
13518 size = 0;
13519 }
13520
13521 patterns = Fassoc (pattern, Valternate_fontname_alist);
13522 if (NILP (patterns))
13523 patterns = Fcons (pattern, Qnil);
13524
13525 if (maxnames == 1 && !size)
13526 /* We can return any single font matching PATTERN. */
13527 try_XLoadQueryFont = 1;
13528
13529 for (; CONSP (patterns); patterns = XCDR (patterns))
13530 {
13531 int num_fonts;
13532 char **names = NULL;
13533
13534 pattern = XCAR (patterns);
13535 /* See if we cached the result for this particular query.
13536 The cache is an alist of the form:
13537 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13538 tem = XCDR (dpyinfo->name_list_element);
13539 key = Fcons (Fcons (pattern, make_number (maxnames)),
13540 allow_scalable_fonts_p ? Qt : Qnil);
13541 list = Fassoc (key, tem);
13542 if (!NILP (list))
13543 {
13544 list = Fcdr_safe (list);
13545 /* We have a cashed list. Don't have to get the list again. */
13546 goto label_cached;
13547 }
13548
13549 /* At first, put PATTERN in the cache. */
13550
13551 BLOCK_INPUT;
13552 count = x_catch_errors (dpy);
13553
13554 if (try_XLoadQueryFont)
13555 {
13556 XFontStruct *font;
13557 unsigned long value;
13558
13559 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13560 if (x_had_errors_p (dpy))
13561 {
13562 /* This error is perhaps due to insufficient memory on X
13563 server. Let's just ignore it. */
13564 font = NULL;
13565 x_clear_errors (dpy);
13566 }
13567
13568 if (font
13569 && XGetFontProperty (font, XA_FONT, &value))
13570 {
13571 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13572 int len = strlen (name);
13573 char *tmp;
13574
13575 /* If DXPC (a Differential X Protocol Compressor)
13576 Ver.3.7 is running, XGetAtomName will return null
13577 string. We must avoid such a name. */
13578 if (len == 0)
13579 try_XLoadQueryFont = 0;
13580 else
13581 {
13582 num_fonts = 1;
13583 names = (char **) alloca (sizeof (char *));
13584 /* Some systems only allow alloca assigned to a
13585 simple var. */
13586 tmp = (char *) alloca (len + 1); names[0] = tmp;
13587 bcopy (name, names[0], len + 1);
13588 XFree (name);
13589 }
13590 }
13591 else
13592 try_XLoadQueryFont = 0;
13593
13594 if (font)
13595 XFreeFont (dpy, font);
13596 }
13597
13598 if (!try_XLoadQueryFont)
13599 {
13600 /* We try at least 10 fonts because XListFonts will return
13601 auto-scaled fonts at the head. */
13602 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13603 &num_fonts);
13604 if (x_had_errors_p (dpy))
13605 {
13606 /* This error is perhaps due to insufficient memory on X
13607 server. Let's just ignore it. */
13608 names = NULL;
13609 x_clear_errors (dpy);
13610 }
13611 }
13612
13613 x_uncatch_errors (dpy, count);
13614 UNBLOCK_INPUT;
13615
13616 if (names)
13617 {
13618 int i;
13619
13620 /* Make a list of all the fonts we got back.
13621 Store that in the font cache for the display. */
13622 for (i = 0; i < num_fonts; i++)
13623 {
13624 int width = 0;
13625 char *p = names[i];
13626 int average_width = -1, dashes = 0;
13627
13628 /* Count the number of dashes in NAMES[I]. If there are
13629 14 dashes, and the field value following 12th dash
13630 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13631 is usually too ugly to be used for editing. Let's
13632 ignore it. */
13633 while (*p)
13634 if (*p++ == '-')
13635 {
13636 dashes++;
13637 if (dashes == 7) /* PIXEL_SIZE field */
13638 width = atoi (p);
13639 else if (dashes == 12) /* AVERAGE_WIDTH field */
13640 average_width = atoi (p);
13641 }
13642
13643 if (allow_scalable_fonts_p
13644 || dashes < 14 || average_width != 0)
13645 {
13646 tem = build_string (names[i]);
13647 if (NILP (Fassoc (tem, list)))
13648 {
13649 if (STRINGP (Vx_pixel_size_width_font_regexp)
13650 && ((fast_c_string_match_ignore_case
13651 (Vx_pixel_size_width_font_regexp, names[i]))
13652 >= 0))
13653 /* We can set the value of PIXEL_SIZE to the
13654 width of this font. */
13655 list = Fcons (Fcons (tem, make_number (width)), list);
13656 else
13657 /* For the moment, width is not known. */
13658 list = Fcons (Fcons (tem, Qnil), list);
13659 }
13660 }
13661 }
13662
13663 if (!try_XLoadQueryFont)
13664 {
13665 BLOCK_INPUT;
13666 XFreeFontNames (names);
13667 UNBLOCK_INPUT;
13668 }
13669 }
13670
13671 /* Now store the result in the cache. */
13672 XSETCDR (dpyinfo->name_list_element,
13673 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
13674
13675 label_cached:
13676 if (NILP (list)) continue; /* Try the remaining alternatives. */
13677
13678 newlist = second_best = Qnil;
13679 /* Make a list of the fonts that have the right width. */
13680 for (; CONSP (list); list = XCDR (list))
13681 {
13682 int found_size;
13683
13684 tem = XCAR (list);
13685
13686 if (!CONSP (tem) || NILP (XCAR (tem)))
13687 continue;
13688 if (!size)
13689 {
13690 newlist = Fcons (XCAR (tem), newlist);
13691 continue;
13692 }
13693
13694 if (!INTEGERP (XCDR (tem)))
13695 {
13696 /* Since we have not yet known the size of this font, we
13697 must try slow function call XLoadQueryFont. */
13698 XFontStruct *thisinfo;
13699
13700 BLOCK_INPUT;
13701 count = x_catch_errors (dpy);
13702 thisinfo = XLoadQueryFont (dpy,
13703 XSTRING (XCAR (tem))->data);
13704 if (x_had_errors_p (dpy))
13705 {
13706 /* This error is perhaps due to insufficient memory on X
13707 server. Let's just ignore it. */
13708 thisinfo = NULL;
13709 x_clear_errors (dpy);
13710 }
13711 x_uncatch_errors (dpy, count);
13712 UNBLOCK_INPUT;
13713
13714 if (thisinfo)
13715 {
13716 XSETCDR (tem,
13717 (thisinfo->min_bounds.width == 0
13718 ? make_number (0)
13719 : make_number (thisinfo->max_bounds.width)));
13720 BLOCK_INPUT;
13721 XFreeFont (dpy, thisinfo);
13722 UNBLOCK_INPUT;
13723 }
13724 else
13725 /* For unknown reason, the previous call of XListFont had
13726 returned a font which can't be opened. Record the size
13727 as 0 not to try to open it again. */
13728 XSETCDR (tem, make_number (0));
13729 }
13730
13731 found_size = XINT (XCDR (tem));
13732 if (found_size == size)
13733 newlist = Fcons (XCAR (tem), newlist);
13734 else if (found_size > 0)
13735 {
13736 if (NILP (second_best))
13737 second_best = tem;
13738 else if (found_size < size)
13739 {
13740 if (XINT (XCDR (second_best)) > size
13741 || XINT (XCDR (second_best)) < found_size)
13742 second_best = tem;
13743 }
13744 else
13745 {
13746 if (XINT (XCDR (second_best)) > size
13747 && XINT (XCDR (second_best)) > found_size)
13748 second_best = tem;
13749 }
13750 }
13751 }
13752 if (!NILP (newlist))
13753 break;
13754 else if (!NILP (second_best))
13755 {
13756 newlist = Fcons (XCAR (second_best), Qnil);
13757 break;
13758 }
13759 }
13760
13761 return newlist;
13762 }
13763
13764
13765 #if GLYPH_DEBUG
13766
13767 /* Check that FONT is valid on frame F. It is if it can be found in F's
13768 font table. */
13769
13770 static void
13771 x_check_font (f, font)
13772 struct frame *f;
13773 XFontStruct *font;
13774 {
13775 int i;
13776 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13777
13778 xassert (font != NULL);
13779
13780 for (i = 0; i < dpyinfo->n_fonts; i++)
13781 if (dpyinfo->font_table[i].name
13782 && font == dpyinfo->font_table[i].font)
13783 break;
13784
13785 xassert (i < dpyinfo->n_fonts);
13786 }
13787
13788 #endif /* GLYPH_DEBUG != 0 */
13789
13790 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13791 Note: There are (broken) X fonts out there with invalid XFontStruct
13792 min_bounds contents. For example, handa@etl.go.jp reports that
13793 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13794 have font->min_bounds.width == 0. */
13795
13796 static INLINE void
13797 x_font_min_bounds (font, w, h)
13798 XFontStruct *font;
13799 int *w, *h;
13800 {
13801 *h = FONT_HEIGHT (font);
13802 *w = font->min_bounds.width;
13803
13804 /* Try to handle the case where FONT->min_bounds has invalid
13805 contents. Since the only font known to have invalid min_bounds
13806 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13807 if (*w <= 0)
13808 *w = font->max_bounds.width;
13809 }
13810
13811
13812 /* Compute the smallest character width and smallest font height over
13813 all fonts available on frame F. Set the members smallest_char_width
13814 and smallest_font_height in F's x_display_info structure to
13815 the values computed. Value is non-zero if smallest_font_height or
13816 smallest_char_width become smaller than they were before. */
13817
13818 static int
13819 x_compute_min_glyph_bounds (f)
13820 struct frame *f;
13821 {
13822 int i;
13823 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13824 XFontStruct *font;
13825 int old_width = dpyinfo->smallest_char_width;
13826 int old_height = dpyinfo->smallest_font_height;
13827
13828 dpyinfo->smallest_font_height = 100000;
13829 dpyinfo->smallest_char_width = 100000;
13830
13831 for (i = 0; i < dpyinfo->n_fonts; ++i)
13832 if (dpyinfo->font_table[i].name)
13833 {
13834 struct font_info *fontp = dpyinfo->font_table + i;
13835 int w, h;
13836
13837 font = (XFontStruct *) fontp->font;
13838 xassert (font != (XFontStruct *) ~0);
13839 x_font_min_bounds (font, &w, &h);
13840
13841 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13842 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13843 }
13844
13845 xassert (dpyinfo->smallest_char_width > 0
13846 && dpyinfo->smallest_font_height > 0);
13847
13848 return (dpyinfo->n_fonts == 1
13849 || dpyinfo->smallest_char_width < old_width
13850 || dpyinfo->smallest_font_height < old_height);
13851 }
13852
13853
13854 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13855 pointer to the structure font_info while allocating it dynamically.
13856 If SIZE is 0, load any size of font.
13857 If loading is failed, return NULL. */
13858
13859 struct font_info *
13860 x_load_font (f, fontname, size)
13861 struct frame *f;
13862 register char *fontname;
13863 int size;
13864 {
13865 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13866 Lisp_Object font_names;
13867 int count;
13868
13869 /* Get a list of all the fonts that match this name. Once we
13870 have a list of matching fonts, we compare them against the fonts
13871 we already have by comparing names. */
13872 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13873
13874 if (!NILP (font_names))
13875 {
13876 Lisp_Object tail;
13877 int i;
13878
13879 for (i = 0; i < dpyinfo->n_fonts; i++)
13880 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13881 if (dpyinfo->font_table[i].name
13882 && (!strcmp (dpyinfo->font_table[i].name,
13883 XSTRING (XCAR (tail))->data)
13884 || !strcmp (dpyinfo->font_table[i].full_name,
13885 XSTRING (XCAR (tail))->data)))
13886 return (dpyinfo->font_table + i);
13887 }
13888
13889 /* Load the font and add it to the table. */
13890 {
13891 char *full_name;
13892 XFontStruct *font;
13893 struct font_info *fontp;
13894 unsigned long value;
13895 int i;
13896
13897 /* If we have found fonts by x_list_font, load one of them. If
13898 not, we still try to load a font by the name given as FONTNAME
13899 because XListFonts (called in x_list_font) of some X server has
13900 a bug of not finding a font even if the font surely exists and
13901 is loadable by XLoadQueryFont. */
13902 if (size > 0 && !NILP (font_names))
13903 fontname = (char *) XSTRING (XCAR (font_names))->data;
13904
13905 BLOCK_INPUT;
13906 count = x_catch_errors (FRAME_X_DISPLAY (f));
13907 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13908 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13909 {
13910 /* This error is perhaps due to insufficient memory on X
13911 server. Let's just ignore it. */
13912 font = NULL;
13913 x_clear_errors (FRAME_X_DISPLAY (f));
13914 }
13915 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13916 UNBLOCK_INPUT;
13917 if (!font)
13918 return NULL;
13919
13920 /* Find a free slot in the font table. */
13921 for (i = 0; i < dpyinfo->n_fonts; ++i)
13922 if (dpyinfo->font_table[i].name == NULL)
13923 break;
13924
13925 /* If no free slot found, maybe enlarge the font table. */
13926 if (i == dpyinfo->n_fonts
13927 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13928 {
13929 int sz;
13930 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13931 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13932 dpyinfo->font_table
13933 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13934 }
13935
13936 fontp = dpyinfo->font_table + i;
13937 if (i == dpyinfo->n_fonts)
13938 ++dpyinfo->n_fonts;
13939
13940 /* Now fill in the slots of *FONTP. */
13941 BLOCK_INPUT;
13942 fontp->font = font;
13943 fontp->font_idx = i;
13944 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13945 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13946
13947 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13948 full_name = 0;
13949 if (XGetFontProperty (font, XA_FONT, &value))
13950 {
13951 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13952 char *p = name;
13953 int dashes = 0;
13954
13955 /* Count the number of dashes in the "full name".
13956 If it is too few, this isn't really the font's full name,
13957 so don't use it.
13958 In X11R4, the fonts did not come with their canonical names
13959 stored in them. */
13960 while (*p)
13961 {
13962 if (*p == '-')
13963 dashes++;
13964 p++;
13965 }
13966
13967 if (dashes >= 13)
13968 {
13969 full_name = (char *) xmalloc (p - name + 1);
13970 bcopy (name, full_name, p - name + 1);
13971 }
13972
13973 XFree (name);
13974 }
13975
13976 if (full_name != 0)
13977 fontp->full_name = full_name;
13978 else
13979 fontp->full_name = fontp->name;
13980
13981 fontp->size = font->max_bounds.width;
13982 fontp->height = FONT_HEIGHT (font);
13983
13984 if (NILP (font_names))
13985 {
13986 /* We come here because of a bug of XListFonts mentioned at
13987 the head of this block. Let's store this information in
13988 the cache for x_list_fonts. */
13989 Lisp_Object lispy_name = build_string (fontname);
13990 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13991 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13992 Qnil);
13993
13994 XSETCDR (dpyinfo->name_list_element,
13995 Fcons (Fcons (key,
13996 Fcons (Fcons (lispy_full_name,
13997 make_number (fontp->size)),
13998 Qnil)),
13999 XCDR (dpyinfo->name_list_element)));
14000 if (full_name)
14001 {
14002 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14003 Qnil);
14004 XSETCDR (dpyinfo->name_list_element,
14005 Fcons (Fcons (key,
14006 Fcons (Fcons (lispy_full_name,
14007 make_number (fontp->size)),
14008 Qnil)),
14009 XCDR (dpyinfo->name_list_element)));
14010 }
14011 }
14012
14013 /* The slot `encoding' specifies how to map a character
14014 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14015 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14016 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14017 2:0xA020..0xFF7F). For the moment, we don't know which charset
14018 uses this font. So, we set information in fontp->encoding[1]
14019 which is never used by any charset. If mapping can't be
14020 decided, set FONT_ENCODING_NOT_DECIDED. */
14021 fontp->encoding[1]
14022 = (font->max_byte1 == 0
14023 /* 1-byte font */
14024 ? (font->min_char_or_byte2 < 0x80
14025 ? (font->max_char_or_byte2 < 0x80
14026 ? 0 /* 0x20..0x7F */
14027 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14028 : 1) /* 0xA0..0xFF */
14029 /* 2-byte font */
14030 : (font->min_byte1 < 0x80
14031 ? (font->max_byte1 < 0x80
14032 ? (font->min_char_or_byte2 < 0x80
14033 ? (font->max_char_or_byte2 < 0x80
14034 ? 0 /* 0x2020..0x7F7F */
14035 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14036 : 3) /* 0x20A0..0x7FFF */
14037 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14038 : (font->min_char_or_byte2 < 0x80
14039 ? (font->max_char_or_byte2 < 0x80
14040 ? 2 /* 0xA020..0xFF7F */
14041 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14042 : 1))); /* 0xA0A0..0xFFFF */
14043
14044 fontp->baseline_offset
14045 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14046 ? (long) value : 0);
14047 fontp->relative_compose
14048 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14049 ? (long) value : 0);
14050 fontp->default_ascent
14051 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14052 ? (long) value : 0);
14053
14054 /* Set global flag fonts_changed_p to non-zero if the font loaded
14055 has a character with a smaller width than any other character
14056 before, or if the font loaded has a smalle>r height than any
14057 other font loaded before. If this happens, it will make a
14058 glyph matrix reallocation necessary. */
14059 fonts_changed_p = x_compute_min_glyph_bounds (f);
14060 UNBLOCK_INPUT;
14061 return fontp;
14062 }
14063 }
14064
14065
14066 /* Return a pointer to struct font_info of a font named FONTNAME for
14067 frame F. If no such font is loaded, return NULL. */
14068
14069 struct font_info *
14070 x_query_font (f, fontname)
14071 struct frame *f;
14072 register char *fontname;
14073 {
14074 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14075 int i;
14076
14077 for (i = 0; i < dpyinfo->n_fonts; i++)
14078 if (dpyinfo->font_table[i].name
14079 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14080 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14081 return (dpyinfo->font_table + i);
14082 return NULL;
14083 }
14084
14085
14086 /* Find a CCL program for a font specified by FONTP, and set the member
14087 `encoder' of the structure. */
14088
14089 void
14090 x_find_ccl_program (fontp)
14091 struct font_info *fontp;
14092 {
14093 Lisp_Object list, elt;
14094
14095 elt = Qnil;
14096 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14097 {
14098 elt = XCAR (list);
14099 if (CONSP (elt)
14100 && STRINGP (XCAR (elt))
14101 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14102 >= 0)
14103 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14104 >= 0)))
14105 break;
14106 }
14107
14108 if (! NILP (list))
14109 {
14110 struct ccl_program *ccl
14111 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14112
14113 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14114 xfree (ccl);
14115 else
14116 fontp->font_encoder = ccl;
14117 }
14118 }
14119
14120
14121 \f
14122 /***********************************************************************
14123 Initialization
14124 ***********************************************************************/
14125
14126 #ifdef USE_X_TOOLKIT
14127 static XrmOptionDescRec emacs_options[] = {
14128 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14129 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14130
14131 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14132 XrmoptionSepArg, NULL},
14133 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14134
14135 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14136 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14137 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14138 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14139 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14140 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14141 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14142 };
14143 #endif /* USE_X_TOOLKIT */
14144
14145 static int x_initialized;
14146
14147 #ifdef MULTI_KBOARD
14148 /* Test whether two display-name strings agree up to the dot that separates
14149 the screen number from the server number. */
14150 static int
14151 same_x_server (name1, name2)
14152 char *name1, *name2;
14153 {
14154 int seen_colon = 0;
14155 unsigned char *system_name = XSTRING (Vsystem_name)->data;
14156 int system_name_length = strlen (system_name);
14157 int length_until_period = 0;
14158
14159 while (system_name[length_until_period] != 0
14160 && system_name[length_until_period] != '.')
14161 length_until_period++;
14162
14163 /* Treat `unix' like an empty host name. */
14164 if (! strncmp (name1, "unix:", 5))
14165 name1 += 4;
14166 if (! strncmp (name2, "unix:", 5))
14167 name2 += 4;
14168 /* Treat this host's name like an empty host name. */
14169 if (! strncmp (name1, system_name, system_name_length)
14170 && name1[system_name_length] == ':')
14171 name1 += system_name_length;
14172 if (! strncmp (name2, system_name, system_name_length)
14173 && name2[system_name_length] == ':')
14174 name2 += system_name_length;
14175 /* Treat this host's domainless name like an empty host name. */
14176 if (! strncmp (name1, system_name, length_until_period)
14177 && name1[length_until_period] == ':')
14178 name1 += length_until_period;
14179 if (! strncmp (name2, system_name, length_until_period)
14180 && name2[length_until_period] == ':')
14181 name2 += length_until_period;
14182
14183 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14184 {
14185 if (*name1 == ':')
14186 seen_colon++;
14187 if (seen_colon && *name1 == '.')
14188 return 1;
14189 }
14190 return (seen_colon
14191 && (*name1 == '.' || *name1 == '\0')
14192 && (*name2 == '.' || *name2 == '\0'));
14193 }
14194 #endif
14195
14196 struct x_display_info *
14197 x_term_init (display_name, xrm_option, resource_name)
14198 Lisp_Object display_name;
14199 char *xrm_option;
14200 char *resource_name;
14201 {
14202 int connection;
14203 Display *dpy;
14204 struct x_display_info *dpyinfo;
14205 XrmDatabase xrdb;
14206
14207 BLOCK_INPUT;
14208
14209 if (!x_initialized)
14210 {
14211 x_initialize ();
14212 x_initialized = 1;
14213 }
14214
14215 #ifdef USE_X_TOOLKIT
14216 /* weiner@footloose.sps.mot.com reports that this causes
14217 errors with X11R5:
14218 X protocol error: BadAtom (invalid Atom parameter)
14219 on protocol request 18skiloaf.
14220 So let's not use it until R6. */
14221 #ifdef HAVE_X11XTR6
14222 XtSetLanguageProc (NULL, NULL, NULL);
14223 #endif
14224
14225 {
14226 int argc = 0;
14227 char *argv[3];
14228
14229 argv[0] = "";
14230 argc = 1;
14231 if (xrm_option)
14232 {
14233 argv[argc++] = "-xrm";
14234 argv[argc++] = xrm_option;
14235 }
14236 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
14237 resource_name, EMACS_CLASS,
14238 emacs_options, XtNumber (emacs_options),
14239 &argc, argv);
14240
14241 #ifdef HAVE_X11XTR6
14242 /* I think this is to compensate for XtSetLanguageProc. */
14243 fixup_locale ();
14244 #endif
14245 }
14246
14247 #else /* not USE_X_TOOLKIT */
14248 #ifdef HAVE_X11R5
14249 XSetLocaleModifiers ("");
14250 #endif
14251 dpy = XOpenDisplay (XSTRING (display_name)->data);
14252 #endif /* not USE_X_TOOLKIT */
14253
14254 /* Detect failure. */
14255 if (dpy == 0)
14256 {
14257 UNBLOCK_INPUT;
14258 return 0;
14259 }
14260
14261 /* We have definitely succeeded. Record the new connection. */
14262
14263 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14264 bzero (dpyinfo, sizeof *dpyinfo);
14265
14266 #ifdef MULTI_KBOARD
14267 {
14268 struct x_display_info *share;
14269 Lisp_Object tail;
14270
14271 for (share = x_display_list, tail = x_display_name_list; share;
14272 share = share->next, tail = XCDR (tail))
14273 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
14274 XSTRING (display_name)->data))
14275 break;
14276 if (share)
14277 dpyinfo->kboard = share->kboard;
14278 else
14279 {
14280 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14281 init_kboard (dpyinfo->kboard);
14282 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14283 {
14284 char *vendor = ServerVendor (dpy);
14285 UNBLOCK_INPUT;
14286 dpyinfo->kboard->Vsystem_key_alist
14287 = call1 (Qvendor_specific_keysyms,
14288 build_string (vendor ? vendor : ""));
14289 BLOCK_INPUT;
14290 }
14291
14292 dpyinfo->kboard->next_kboard = all_kboards;
14293 all_kboards = dpyinfo->kboard;
14294 /* Don't let the initial kboard remain current longer than necessary.
14295 That would cause problems if a file loaded on startup tries to
14296 prompt in the mini-buffer. */
14297 if (current_kboard == initial_kboard)
14298 current_kboard = dpyinfo->kboard;
14299 }
14300 dpyinfo->kboard->reference_count++;
14301 }
14302 #endif
14303
14304 /* Put this display on the chain. */
14305 dpyinfo->next = x_display_list;
14306 x_display_list = dpyinfo;
14307
14308 /* Put it on x_display_name_list as well, to keep them parallel. */
14309 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14310 x_display_name_list);
14311 dpyinfo->name_list_element = XCAR (x_display_name_list);
14312
14313 dpyinfo->display = dpy;
14314
14315 #if 0
14316 XSetAfterFunction (x_current_display, x_trace_wire);
14317 #endif /* ! 0 */
14318
14319 dpyinfo->x_id_name
14320 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
14321 + STRING_BYTES (XSTRING (Vsystem_name))
14322 + 2);
14323 sprintf (dpyinfo->x_id_name, "%s@%s",
14324 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
14325
14326 /* Figure out which modifier bits mean what. */
14327 x_find_modifier_meanings (dpyinfo);
14328
14329 /* Get the scroll bar cursor. */
14330 dpyinfo->vertical_scroll_bar_cursor
14331 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14332
14333 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14334 resource_name, EMACS_CLASS);
14335 #ifdef HAVE_XRMSETDATABASE
14336 XrmSetDatabase (dpyinfo->display, xrdb);
14337 #else
14338 dpyinfo->display->db = xrdb;
14339 #endif
14340 /* Put the rdb where we can find it in a way that works on
14341 all versions. */
14342 dpyinfo->xrdb = xrdb;
14343
14344 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14345 DefaultScreen (dpyinfo->display));
14346 select_visual (dpyinfo);
14347 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14348 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14349 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14350 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14351 dpyinfo->grabbed = 0;
14352 dpyinfo->reference_count = 0;
14353 dpyinfo->icon_bitmap_id = -1;
14354 dpyinfo->font_table = NULL;
14355 dpyinfo->n_fonts = 0;
14356 dpyinfo->font_table_size = 0;
14357 dpyinfo->bitmaps = 0;
14358 dpyinfo->bitmaps_size = 0;
14359 dpyinfo->bitmaps_last = 0;
14360 dpyinfo->scratch_cursor_gc = 0;
14361 dpyinfo->mouse_face_mouse_frame = 0;
14362 dpyinfo->mouse_face_deferred_gc = 0;
14363 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14364 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14365 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14366 dpyinfo->mouse_face_window = Qnil;
14367 dpyinfo->mouse_face_overlay = Qnil;
14368 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14369 dpyinfo->mouse_face_defer = 0;
14370 dpyinfo->x_focus_frame = 0;
14371 dpyinfo->x_focus_event_frame = 0;
14372 dpyinfo->x_highlight_frame = 0;
14373 dpyinfo->image_cache = make_image_cache ();
14374
14375 /* See if a private colormap is requested. */
14376 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14377 {
14378 if (dpyinfo->visual->class == PseudoColor)
14379 {
14380 Lisp_Object value;
14381 value = display_x_get_resource (dpyinfo,
14382 build_string ("privateColormap"),
14383 build_string ("PrivateColormap"),
14384 Qnil, Qnil);
14385 if (STRINGP (value)
14386 && (!strcmp (XSTRING (value)->data, "true")
14387 || !strcmp (XSTRING (value)->data, "on")))
14388 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14389 }
14390 }
14391 else
14392 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14393 dpyinfo->visual, AllocNone);
14394
14395 {
14396 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14397 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14398 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14399 dpyinfo->resy = pixels * 25.4 / mm;
14400 pixels = DisplayWidth (dpyinfo->display, screen_number);
14401 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14402 dpyinfo->resx = pixels * 25.4 / mm;
14403 }
14404
14405 dpyinfo->Xatom_wm_protocols
14406 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14407 dpyinfo->Xatom_wm_take_focus
14408 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14409 dpyinfo->Xatom_wm_save_yourself
14410 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14411 dpyinfo->Xatom_wm_delete_window
14412 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14413 dpyinfo->Xatom_wm_change_state
14414 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14415 dpyinfo->Xatom_wm_configure_denied
14416 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14417 dpyinfo->Xatom_wm_window_moved
14418 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14419 dpyinfo->Xatom_editres
14420 = XInternAtom (dpyinfo->display, "Editres", False);
14421 dpyinfo->Xatom_CLIPBOARD
14422 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14423 dpyinfo->Xatom_TIMESTAMP
14424 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14425 dpyinfo->Xatom_TEXT
14426 = XInternAtom (dpyinfo->display, "TEXT", False);
14427 dpyinfo->Xatom_COMPOUND_TEXT
14428 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14429 dpyinfo->Xatom_DELETE
14430 = XInternAtom (dpyinfo->display, "DELETE", False);
14431 dpyinfo->Xatom_MULTIPLE
14432 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14433 dpyinfo->Xatom_INCR
14434 = XInternAtom (dpyinfo->display, "INCR", False);
14435 dpyinfo->Xatom_EMACS_TMP
14436 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14437 dpyinfo->Xatom_TARGETS
14438 = XInternAtom (dpyinfo->display, "TARGETS", False);
14439 dpyinfo->Xatom_NULL
14440 = XInternAtom (dpyinfo->display, "NULL", False);
14441 dpyinfo->Xatom_ATOM_PAIR
14442 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14443 /* For properties of font. */
14444 dpyinfo->Xatom_PIXEL_SIZE
14445 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14446 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14447 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14448 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14449 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14450 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14451 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14452
14453 /* Ghostscript support. */
14454 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14455 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14456
14457 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14458 False);
14459
14460 dpyinfo->cut_buffers_initialized = 0;
14461
14462 connection = ConnectionNumber (dpyinfo->display);
14463 dpyinfo->connection = connection;
14464
14465 {
14466 char null_bits[1];
14467
14468 null_bits[0] = 0x00;
14469
14470 dpyinfo->null_pixel
14471 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14472 null_bits, 1, 1, (long) 0, (long) 0,
14473 1);
14474 }
14475
14476 {
14477 extern int gray_bitmap_width, gray_bitmap_height;
14478 extern char *gray_bitmap_bits;
14479 dpyinfo->gray
14480 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14481 gray_bitmap_bits,
14482 gray_bitmap_width, gray_bitmap_height,
14483 (unsigned long) 1, (unsigned long) 0, 1);
14484 }
14485
14486 #ifdef HAVE_X_I18N
14487 xim_initialize (dpyinfo, resource_name);
14488 #endif
14489
14490 #ifdef subprocesses
14491 /* This is only needed for distinguishing keyboard and process input. */
14492 if (connection != 0)
14493 add_keyboard_wait_descriptor (connection);
14494 #endif
14495
14496 #ifndef F_SETOWN_BUG
14497 #ifdef F_SETOWN
14498 #ifdef F_SETOWN_SOCK_NEG
14499 /* stdin is a socket here */
14500 fcntl (connection, F_SETOWN, -getpid ());
14501 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14502 fcntl (connection, F_SETOWN, getpid ());
14503 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14504 #endif /* ! defined (F_SETOWN) */
14505 #endif /* F_SETOWN_BUG */
14506
14507 #ifdef SIGIO
14508 if (interrupt_input)
14509 init_sigio (connection);
14510 #endif /* ! defined (SIGIO) */
14511
14512 #ifdef USE_LUCID
14513 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14514 /* Make sure that we have a valid font for dialog boxes
14515 so that Xt does not crash. */
14516 {
14517 Display *dpy = dpyinfo->display;
14518 XrmValue d, fr, to;
14519 Font font;
14520 int count;
14521
14522 d.addr = (XPointer)&dpy;
14523 d.size = sizeof (Display *);
14524 fr.addr = XtDefaultFont;
14525 fr.size = sizeof (XtDefaultFont);
14526 to.size = sizeof (Font *);
14527 to.addr = (XPointer)&font;
14528 count = x_catch_errors (dpy);
14529 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14530 abort ();
14531 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14532 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14533 x_uncatch_errors (dpy, count);
14534 }
14535 #endif
14536 #endif
14537
14538 /* See if we should run in synchronous mode. This is useful
14539 for debugging X code. */
14540 {
14541 Lisp_Object value;
14542 value = display_x_get_resource (dpyinfo,
14543 build_string ("synchronous"),
14544 build_string ("Synchronous"),
14545 Qnil, Qnil);
14546 if (STRINGP (value)
14547 && (!strcmp (XSTRING (value)->data, "true")
14548 || !strcmp (XSTRING (value)->data, "on")))
14549 XSynchronize (dpyinfo->display, True);
14550 }
14551
14552 UNBLOCK_INPUT;
14553
14554 return dpyinfo;
14555 }
14556 \f
14557 /* Get rid of display DPYINFO, assuming all frames are already gone,
14558 and without sending any more commands to the X server. */
14559
14560 void
14561 x_delete_display (dpyinfo)
14562 struct x_display_info *dpyinfo;
14563 {
14564 delete_keyboard_wait_descriptor (dpyinfo->connection);
14565
14566 /* Discard this display from x_display_name_list and x_display_list.
14567 We can't use Fdelq because that can quit. */
14568 if (! NILP (x_display_name_list)
14569 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14570 x_display_name_list = XCDR (x_display_name_list);
14571 else
14572 {
14573 Lisp_Object tail;
14574
14575 tail = x_display_name_list;
14576 while (CONSP (tail) && CONSP (XCDR (tail)))
14577 {
14578 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14579 {
14580 XSETCDR (tail, XCDR (XCDR (tail)));
14581 break;
14582 }
14583 tail = XCDR (tail);
14584 }
14585 }
14586
14587 if (next_noop_dpyinfo == dpyinfo)
14588 next_noop_dpyinfo = dpyinfo->next;
14589
14590 if (x_display_list == dpyinfo)
14591 x_display_list = dpyinfo->next;
14592 else
14593 {
14594 struct x_display_info *tail;
14595
14596 for (tail = x_display_list; tail; tail = tail->next)
14597 if (tail->next == dpyinfo)
14598 tail->next = tail->next->next;
14599 }
14600
14601 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14602 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14603 XrmDestroyDatabase (dpyinfo->xrdb);
14604 #endif
14605 #endif
14606 #ifdef MULTI_KBOARD
14607 if (--dpyinfo->kboard->reference_count == 0)
14608 delete_kboard (dpyinfo->kboard);
14609 #endif
14610 #ifdef HAVE_X_I18N
14611 if (dpyinfo->xim)
14612 xim_close_dpy (dpyinfo);
14613 #endif
14614
14615 xfree (dpyinfo->font_table);
14616 xfree (dpyinfo->x_id_name);
14617 xfree (dpyinfo->color_cells);
14618 xfree (dpyinfo);
14619 }
14620
14621 \f
14622 /* Set up use of X before we make the first connection. */
14623
14624 static struct redisplay_interface x_redisplay_interface =
14625 {
14626 x_produce_glyphs,
14627 x_write_glyphs,
14628 x_insert_glyphs,
14629 x_clear_end_of_line,
14630 x_scroll_run,
14631 x_after_update_window_line,
14632 x_update_window_begin,
14633 x_update_window_end,
14634 XTcursor_to,
14635 x_flush,
14636 x_clear_mouse_face,
14637 x_get_glyph_overhangs,
14638 x_fix_overlapping_area
14639 };
14640
14641 void
14642 x_initialize ()
14643 {
14644 rif = &x_redisplay_interface;
14645
14646 clear_frame_hook = x_clear_frame;
14647 ins_del_lines_hook = x_ins_del_lines;
14648 delete_glyphs_hook = x_delete_glyphs;
14649 ring_bell_hook = XTring_bell;
14650 reset_terminal_modes_hook = XTreset_terminal_modes;
14651 set_terminal_modes_hook = XTset_terminal_modes;
14652 update_begin_hook = x_update_begin;
14653 update_end_hook = x_update_end;
14654 set_terminal_window_hook = XTset_terminal_window;
14655 read_socket_hook = XTread_socket;
14656 frame_up_to_date_hook = XTframe_up_to_date;
14657 mouse_position_hook = XTmouse_position;
14658 frame_rehighlight_hook = XTframe_rehighlight;
14659 frame_raise_lower_hook = XTframe_raise_lower;
14660 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14661 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14662 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14663 judge_scroll_bars_hook = XTjudge_scroll_bars;
14664 estimate_mode_line_height_hook = x_estimate_mode_line_height;
14665
14666 scroll_region_ok = 1; /* we'll scroll partial frames */
14667 char_ins_del_ok = 1;
14668 line_ins_del_ok = 1; /* we'll just blt 'em */
14669 fast_clear_end_of_line = 1; /* X does this well */
14670 memory_below_frame = 0; /* we don't remember what scrolls
14671 off the bottom */
14672 baud_rate = 19200;
14673
14674 x_noop_count = 0;
14675 last_tool_bar_item = -1;
14676 any_help_event_p = 0;
14677
14678 /* Try to use interrupt input; if we can't, then start polling. */
14679 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14680
14681 #ifdef USE_X_TOOLKIT
14682 XtToolkitInitialize ();
14683
14684 Xt_app_con = XtCreateApplicationContext ();
14685
14686 /* Register a converter from strings to pixels, which uses
14687 Emacs' color allocation infrastructure. */
14688 XtAppSetTypeConverter (Xt_app_con,
14689 XtRString, XtRPixel, cvt_string_to_pixel,
14690 cvt_string_to_pixel_args,
14691 XtNumber (cvt_string_to_pixel_args),
14692 XtCacheByDisplay, cvt_pixel_dtor);
14693
14694 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
14695
14696 /* Install an asynchronous timer that processes Xt timeout events
14697 every 0.1s. This is necessary because some widget sets use
14698 timeouts internally, for example the LessTif menu bar, or the
14699 Xaw3d scroll bar. When Xt timouts aren't processed, these
14700 widgets don't behave normally. */
14701 {
14702 EMACS_TIME interval;
14703 EMACS_SET_SECS_USECS (interval, 0, 100000);
14704 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14705 }
14706 #endif
14707
14708 #ifdef USE_TOOLKIT_SCROLL_BARS
14709 xaw3d_arrow_scroll = False;
14710 xaw3d_pick_top = True;
14711 #endif
14712
14713 /* Note that there is no real way portable across R3/R4 to get the
14714 original error handler. */
14715 XSetErrorHandler (x_error_handler);
14716 XSetIOErrorHandler (x_io_error_quitter);
14717
14718 /* Disable Window Change signals; they are handled by X events. */
14719 #ifdef SIGWINCH
14720 signal (SIGWINCH, SIG_DFL);
14721 #endif /* ! defined (SIGWINCH) */
14722
14723 signal (SIGPIPE, x_connection_signal);
14724 }
14725
14726
14727 void
14728 syms_of_xterm ()
14729 {
14730 staticpro (&x_error_message_string);
14731 x_error_message_string = Qnil;
14732
14733 staticpro (&x_display_name_list);
14734 x_display_name_list = Qnil;
14735
14736 staticpro (&last_mouse_scroll_bar);
14737 last_mouse_scroll_bar = Qnil;
14738
14739 staticpro (&Qvendor_specific_keysyms);
14740 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
14741
14742 staticpro (&last_mouse_press_frame);
14743 last_mouse_press_frame = Qnil;
14744
14745 help_echo = Qnil;
14746 staticpro (&help_echo);
14747 help_echo_object = Qnil;
14748 staticpro (&help_echo_object);
14749 help_echo_window = Qnil;
14750 staticpro (&help_echo_window);
14751 previous_help_echo = Qnil;
14752 staticpro (&previous_help_echo);
14753 help_echo_pos = -1;
14754
14755 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14756 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
14757 For example, if a block cursor is over a tab, it will be drawn as
14758 wide as that tab on the display. */);
14759 x_stretch_cursor_p = 0;
14760
14761 DEFVAR_BOOL ("x-use-underline-position-properties",
14762 &x_use_underline_position_properties,
14763 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
14764 Nil means ignore them. If you encounter fonts with bogus
14765 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
14766 to 4.1, set this to nil. */);
14767 x_use_underline_position_properties = 1;
14768
14769 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14770 doc: /* What X toolkit scroll bars Emacs uses.
14771 A value of nil means Emacs doesn't use X toolkit scroll bars.
14772 Otherwise, value is a symbol describing the X toolkit. */);
14773 #ifdef USE_TOOLKIT_SCROLL_BARS
14774 #ifdef USE_MOTIF
14775 Vx_toolkit_scroll_bars = intern ("motif");
14776 #elif defined HAVE_XAW3D
14777 Vx_toolkit_scroll_bars = intern ("xaw3d");
14778 #else
14779 Vx_toolkit_scroll_bars = intern ("xaw");
14780 #endif
14781 #else
14782 Vx_toolkit_scroll_bars = Qnil;
14783 #endif
14784
14785 staticpro (&last_mouse_motion_frame);
14786 last_mouse_motion_frame = Qnil;
14787 }
14788
14789 #endif /* HAVE_X_WINDOWS */