(echo-area-clear-hook): Undo Oct 29 change.
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
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 /* Bitmaps for truncated lines. */
159
160 enum bitmap_type
161 {
162 NO_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_bitmap P_ ((struct window *, struct glyph_row *,
467 enum 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_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_FLAGS_AREA_WIDTH (f);
663 y1 -= 1;
664
665 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
666 f->output_data.x->normal_gc, x1, y0, x1, y1);
667 }
668 }
669
670
671 /* End update of window W (which is equal to updated_window).
672
673 Draw vertical borders between horizontally adjacent windows, and
674 display W's cursor if CURSOR_ON_P is non-zero.
675
676 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
677 glyphs in mouse-face were overwritten. In that case we have to
678 make sure that the mouse-highlight is properly redrawn.
679
680 W may be a menu bar pseudo-window in case we don't have X toolkit
681 support. Such windows don't have a cursor, so don't display it
682 here. */
683
684 static void
685 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
686 struct window *w;
687 int cursor_on_p, mouse_face_overwritten_p;
688 {
689 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 areas where they would be displayed
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_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 areas to the left or right 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_bitmap (w, row, which)
823 struct window *w;
824 struct glyph_row *row;
825 enum 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_FLAGS_AREA_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_FLAGS_AREA_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_FLAGS_AREA_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_FLAGS_AREA_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_FLAGS_AREA_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_FLAGS_AREA_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, BITMAP_AREA_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 flags bitmaps for glyph row ROW on window W. Call this
916 function with input blocked. */
917
918 static void
919 x_draw_row_bitmaps (w, row)
920 struct window *w;
921 struct glyph_row *row;
922 {
923 struct frame *f = XFRAME (w->frame);
924 enum 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, BITMAP_AREA_FACE_ID);
936 PREPARE_FACE_FOR_DISPLAY (f, face);
937
938 /* Decide which bitmap to draw at the left side. */
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_BITMAP;
949
950 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
951 the flags area. */
952 if (bitmap == NO_BITMAP
953 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
954 || row->height > FRAME_FLAGS_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 bitmap areas 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_FLAGS_AREA_WIDTH (f)
978 + border),
979 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
980 row->y)),
981 FRAME_X_LEFT_FLAGS_AREA_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_BITMAP)
989 x_draw_bitmap (w, row, bitmap);
990
991 /* Decide which bitmap to draw at the right side. */
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_BITMAP;
998
999 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
1000 the flags area. */
1001 if (bitmap == NO_BITMAP
1002 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
1003 || row->height > FRAME_FLAGS_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 bitmap areas 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_FLAGS_AREA_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_BITMAP)
1031 x_draw_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_FLAGS_AREA_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 flag areas. */
5068 struct frame *f = XFRAME (w->frame);
5069 /* int width = FRAME_FLAGS_AREA_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 flags areas to the
5736 left and right of W. */
5737 window_box (w, -1, &x, &y, &width, &height);
5738 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5739 x -= FRAME_X_LEFT_FLAGS_AREA_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_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 bitmap areas 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_FLAGS_AREA_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 (event.xcrossing.focus)
10673 {
10674 /* Avoid nasty pop/raise loops. */
10675 if (f && (!(f->auto_raise)
10676 || !(f->auto_lower)
10677 || (event.xcrossing.time - enter_timestamp) > 500))
10678 {
10679 x_new_focus_frame (dpyinfo, f);
10680 enter_timestamp = event.xcrossing.time;
10681 }
10682 }
10683 else if (f == dpyinfo->x_focus_frame)
10684 x_new_focus_frame (dpyinfo, 0);
10685
10686 /* EnterNotify counts as mouse movement,
10687 so update things that depend on mouse position. */
10688 if (f && !f->output_data.x->hourglass_p)
10689 note_mouse_movement (f, &event.xmotion);
10690 goto OTHER;
10691 }
10692
10693 case FocusIn:
10694 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10695 if (event.xfocus.detail != NotifyPointer)
10696 dpyinfo->x_focus_event_frame = f;
10697 if (f)
10698 {
10699 x_new_focus_frame (dpyinfo, f);
10700
10701 /* Don't stop displaying the initial startup message
10702 for a switch-frame event we don't need. */
10703 if (GC_NILP (Vterminal_frame)
10704 && GC_CONSP (Vframe_list)
10705 && !GC_NILP (XCDR (Vframe_list)))
10706 {
10707 bufp->kind = FOCUS_IN_EVENT;
10708 XSETFRAME (bufp->frame_or_window, f);
10709 bufp->arg = Qnil;
10710 ++bufp, ++count, --numchars;
10711 }
10712 }
10713
10714 #ifdef HAVE_X_I18N
10715 if (f && FRAME_XIC (f))
10716 XSetICFocus (FRAME_XIC (f));
10717 #endif
10718
10719 goto OTHER;
10720
10721 case LeaveNotify:
10722 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10723 if (f)
10724 {
10725 if (f == dpyinfo->mouse_face_mouse_frame)
10726 {
10727 /* If we move outside the frame, then we're
10728 certainly no longer on any text in the frame. */
10729 clear_mouse_face (dpyinfo);
10730 dpyinfo->mouse_face_mouse_frame = 0;
10731 }
10732
10733 /* Generate a nil HELP_EVENT to cancel a help-echo.
10734 Do it only if there's something to cancel.
10735 Otherwise, the startup message is cleared when
10736 the mouse leaves the frame. */
10737 if (any_help_event_p)
10738 {
10739 Lisp_Object frame;
10740 int n;
10741
10742 XSETFRAME (frame, f);
10743 help_echo = Qnil;
10744 n = gen_help_event (bufp, numchars,
10745 Qnil, frame, Qnil, Qnil, 0);
10746 bufp += n, count += n, numchars -= n;
10747 }
10748
10749 if (event.xcrossing.focus)
10750 x_mouse_leave (dpyinfo);
10751 else
10752 {
10753 if (f == dpyinfo->x_focus_event_frame)
10754 dpyinfo->x_focus_event_frame = 0;
10755 if (f == dpyinfo->x_focus_frame)
10756 x_new_focus_frame (dpyinfo, 0);
10757 }
10758 }
10759 goto OTHER;
10760
10761 case FocusOut:
10762 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10763 if (event.xfocus.detail != NotifyPointer
10764 && f == dpyinfo->x_focus_event_frame)
10765 dpyinfo->x_focus_event_frame = 0;
10766 if (f && f == dpyinfo->x_focus_frame)
10767 x_new_focus_frame (dpyinfo, 0);
10768
10769 #ifdef HAVE_X_I18N
10770 if (f && FRAME_XIC (f))
10771 XUnsetICFocus (FRAME_XIC (f));
10772 #endif
10773
10774 goto OTHER;
10775
10776 case MotionNotify:
10777 {
10778 previous_help_echo = help_echo;
10779 help_echo = help_echo_object = help_echo_window = Qnil;
10780 help_echo_pos = -1;
10781
10782 if (dpyinfo->grabbed && last_mouse_frame
10783 && FRAME_LIVE_P (last_mouse_frame))
10784 f = last_mouse_frame;
10785 else
10786 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10787
10788 if (f)
10789 note_mouse_movement (f, &event.xmotion);
10790 else
10791 {
10792 #ifndef USE_TOOLKIT_SCROLL_BARS
10793 struct scroll_bar *bar
10794 = x_window_to_scroll_bar (event.xmotion.window);
10795
10796 if (bar)
10797 x_scroll_bar_note_movement (bar, &event);
10798 #endif /* USE_TOOLKIT_SCROLL_BARS */
10799
10800 /* If we move outside the frame, then we're
10801 certainly no longer on any text in the frame. */
10802 clear_mouse_face (dpyinfo);
10803 }
10804
10805 /* If the contents of the global variable help_echo
10806 has changed, generate a HELP_EVENT. */
10807 if (!NILP (help_echo)
10808 || !NILP (previous_help_echo))
10809 {
10810 Lisp_Object frame;
10811 int n;
10812
10813 if (f)
10814 XSETFRAME (frame, f);
10815 else
10816 frame = Qnil;
10817
10818 any_help_event_p = 1;
10819 n = gen_help_event (bufp, numchars, help_echo, frame,
10820 help_echo_window, help_echo_object,
10821 help_echo_pos);
10822 bufp += n, count += n, numchars -= n;
10823 }
10824
10825 goto OTHER;
10826 }
10827
10828 case ConfigureNotify:
10829 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10830 if (f)
10831 {
10832 #ifndef USE_X_TOOLKIT
10833 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10834 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10835
10836 /* In the toolkit version, change_frame_size
10837 is called by the code that handles resizing
10838 of the EmacsFrame widget. */
10839
10840 /* Even if the number of character rows and columns has
10841 not changed, the font size may have changed, so we need
10842 to check the pixel dimensions as well. */
10843 if (columns != f->width
10844 || rows != f->height
10845 || event.xconfigure.width != f->output_data.x->pixel_width
10846 || event.xconfigure.height != f->output_data.x->pixel_height)
10847 {
10848 change_frame_size (f, rows, columns, 0, 1, 0);
10849 SET_FRAME_GARBAGED (f);
10850 cancel_mouse_face (f);
10851 }
10852 #endif
10853
10854 f->output_data.x->pixel_width = event.xconfigure.width;
10855 f->output_data.x->pixel_height = event.xconfigure.height;
10856
10857 /* What we have now is the position of Emacs's own window.
10858 Convert that to the position of the window manager window. */
10859 x_real_positions (f, &f->output_data.x->left_pos,
10860 &f->output_data.x->top_pos);
10861
10862 #ifdef HAVE_X_I18N
10863 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10864 xic_set_statusarea (f);
10865 #endif
10866
10867 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10868 {
10869 /* Since the WM decorations come below top_pos now,
10870 we must put them below top_pos in the future. */
10871 f->output_data.x->win_gravity = NorthWestGravity;
10872 x_wm_set_size_hint (f, (long) 0, 0);
10873 }
10874 #ifdef USE_MOTIF
10875 /* Some window managers pass (0,0) as the location of
10876 the window, and the Motif event handler stores it
10877 in the emacs widget, which messes up Motif menus. */
10878 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10879 {
10880 event.xconfigure.x = f->output_data.x->widget->core.x;
10881 event.xconfigure.y = f->output_data.x->widget->core.y;
10882 }
10883 #endif /* USE_MOTIF */
10884 }
10885 goto OTHER;
10886
10887 case ButtonPress:
10888 case ButtonRelease:
10889 {
10890 /* If we decide we want to generate an event to be seen
10891 by the rest of Emacs, we put it here. */
10892 struct input_event emacs_event;
10893 int tool_bar_p = 0;
10894
10895 emacs_event.kind = no_event;
10896 bzero (&compose_status, sizeof (compose_status));
10897
10898 if (dpyinfo->grabbed
10899 && last_mouse_frame
10900 && FRAME_LIVE_P (last_mouse_frame))
10901 f = last_mouse_frame;
10902 else
10903 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10904
10905 if (f)
10906 {
10907 /* Is this in the tool-bar? */
10908 if (WINDOWP (f->tool_bar_window)
10909 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10910 {
10911 Lisp_Object window;
10912 int p, x, y;
10913
10914 x = event.xbutton.x;
10915 y = event.xbutton.y;
10916
10917 /* Set x and y. */
10918 window = window_from_coordinates (f, x, y, &p, 1);
10919 if (EQ (window, f->tool_bar_window))
10920 {
10921 x_handle_tool_bar_click (f, &event.xbutton);
10922 tool_bar_p = 1;
10923 }
10924 }
10925
10926 if (!tool_bar_p)
10927 if (!dpyinfo->x_focus_frame
10928 || f == dpyinfo->x_focus_frame)
10929 construct_mouse_click (&emacs_event, &event, f);
10930 }
10931 else
10932 {
10933 #ifndef USE_TOOLKIT_SCROLL_BARS
10934 struct scroll_bar *bar
10935 = x_window_to_scroll_bar (event.xbutton.window);
10936
10937 if (bar)
10938 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10939 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10940 }
10941
10942 if (event.type == ButtonPress)
10943 {
10944 dpyinfo->grabbed |= (1 << event.xbutton.button);
10945 last_mouse_frame = f;
10946 /* Ignore any mouse motion that happened
10947 before this event; any subsequent mouse-movement
10948 Emacs events should reflect only motion after
10949 the ButtonPress. */
10950 if (f != 0)
10951 f->mouse_moved = 0;
10952
10953 if (!tool_bar_p)
10954 last_tool_bar_item = -1;
10955 }
10956 else
10957 {
10958 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10959 }
10960
10961 if (numchars >= 1 && emacs_event.kind != no_event)
10962 {
10963 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10964 bufp++;
10965 count++;
10966 numchars--;
10967 }
10968
10969 #ifdef USE_X_TOOLKIT
10970 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10971 /* For a down-event in the menu bar,
10972 don't pass it to Xt right now.
10973 Instead, save it away
10974 and we will pass it to Xt from kbd_buffer_get_event.
10975 That way, we can run some Lisp code first. */
10976 if (f && event.type == ButtonPress
10977 /* Verify the event is really within the menu bar
10978 and not just sent to it due to grabbing. */
10979 && event.xbutton.x >= 0
10980 && event.xbutton.x < f->output_data.x->pixel_width
10981 && event.xbutton.y >= 0
10982 && event.xbutton.y < f->output_data.x->menubar_height
10983 && event.xbutton.same_screen)
10984 {
10985 SET_SAVED_BUTTON_EVENT;
10986 XSETFRAME (last_mouse_press_frame, f);
10987 }
10988 else if (event.type == ButtonPress)
10989 {
10990 last_mouse_press_frame = Qnil;
10991 goto OTHER;
10992 }
10993
10994 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10995 but I am trying to be cautious. */
10996 else if (event.type == ButtonRelease)
10997 {
10998 if (!NILP (last_mouse_press_frame))
10999 {
11000 f = XFRAME (last_mouse_press_frame);
11001 if (f->output_data.x)
11002 SET_SAVED_BUTTON_EVENT;
11003 }
11004 else
11005 goto OTHER;
11006 }
11007 #endif /* USE_MOTIF */
11008 else
11009 goto OTHER;
11010 #endif /* USE_X_TOOLKIT */
11011 }
11012 break;
11013
11014 case CirculateNotify:
11015 goto OTHER;
11016
11017 case CirculateRequest:
11018 goto OTHER;
11019
11020 case VisibilityNotify:
11021 goto OTHER;
11022
11023 case MappingNotify:
11024 /* Someone has changed the keyboard mapping - update the
11025 local cache. */
11026 switch (event.xmapping.request)
11027 {
11028 case MappingModifier:
11029 x_find_modifier_meanings (dpyinfo);
11030 /* This is meant to fall through. */
11031 case MappingKeyboard:
11032 XRefreshKeyboardMapping (&event.xmapping);
11033 }
11034 goto OTHER;
11035
11036 default:
11037 OTHER:
11038 #ifdef USE_X_TOOLKIT
11039 BLOCK_INPUT;
11040 XtDispatchEvent (&event);
11041 UNBLOCK_INPUT;
11042 #endif /* USE_X_TOOLKIT */
11043 break;
11044 }
11045 }
11046 }
11047
11048 out:;
11049
11050 /* On some systems, an X bug causes Emacs to get no more events
11051 when the window is destroyed. Detect that. (1994.) */
11052 if (! event_found)
11053 {
11054 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11055 One XNOOP in 100 loops will make Emacs terminate.
11056 B. Bretthauer, 1994 */
11057 x_noop_count++;
11058 if (x_noop_count >= 100)
11059 {
11060 x_noop_count=0;
11061
11062 if (next_noop_dpyinfo == 0)
11063 next_noop_dpyinfo = x_display_list;
11064
11065 XNoOp (next_noop_dpyinfo->display);
11066
11067 /* Each time we get here, cycle through the displays now open. */
11068 next_noop_dpyinfo = next_noop_dpyinfo->next;
11069 }
11070 }
11071
11072 /* If the focus was just given to an auto-raising frame,
11073 raise it now. */
11074 /* ??? This ought to be able to handle more than one such frame. */
11075 if (pending_autoraise_frame)
11076 {
11077 x_raise_frame (pending_autoraise_frame);
11078 pending_autoraise_frame = 0;
11079 }
11080
11081 UNBLOCK_INPUT;
11082 --handling_signal;
11083 return count;
11084 }
11085
11086
11087
11088 \f
11089 /***********************************************************************
11090 Text Cursor
11091 ***********************************************************************/
11092
11093 /* Notice if the text cursor of window W has been overwritten by a
11094 drawing operation that outputs N glyphs starting at START_X and
11095 ending at END_X in the line given by output_cursor.vpos.
11096 Coordinates are area-relative. END_X < 0 means all the rest
11097 of the line after START_X has been written. */
11098
11099 static void
11100 notice_overwritten_cursor (w, start_x, end_x)
11101 struct window *w;
11102 int start_x, end_x;
11103 {
11104 if (updated_area == TEXT_AREA
11105 && w->phys_cursor_on_p
11106 && output_cursor.vpos == w->phys_cursor.vpos
11107 && start_x <= w->phys_cursor.x
11108 && end_x > w->phys_cursor.x)
11109 w->phys_cursor_on_p = 0;
11110 }
11111
11112
11113 /* Set clipping for output in glyph row ROW. W is the window in which
11114 we operate. GC is the graphics context to set clipping in.
11115 WHOLE_LINE_P non-zero means include the areas used for truncation
11116 mark display and alike in the clipping rectangle.
11117
11118 ROW may be a text row or, e.g., a mode line. Text rows must be
11119 clipped to the interior of the window dedicated to text display,
11120 mode lines must be clipped to the whole window. */
11121
11122 static void
11123 x_clip_to_row (w, row, gc, whole_line_p)
11124 struct window *w;
11125 struct glyph_row *row;
11126 GC gc;
11127 int whole_line_p;
11128 {
11129 struct frame *f = XFRAME (WINDOW_FRAME (w));
11130 XRectangle clip_rect;
11131 int window_x, window_y, window_width, window_height;
11132
11133 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11134
11135 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11136 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11137 clip_rect.y = max (clip_rect.y, window_y);
11138 clip_rect.width = window_width;
11139 clip_rect.height = row->visible_height;
11140
11141 /* If clipping to the whole line, including trunc marks, extend
11142 the rectangle to the left and increase its width. */
11143 if (whole_line_p)
11144 {
11145 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
11146 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
11147 }
11148
11149 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11150 }
11151
11152
11153 /* Draw a hollow box cursor on window W in glyph row ROW. */
11154
11155 static void
11156 x_draw_hollow_cursor (w, row)
11157 struct window *w;
11158 struct glyph_row *row;
11159 {
11160 struct frame *f = XFRAME (WINDOW_FRAME (w));
11161 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11162 Display *dpy = FRAME_X_DISPLAY (f);
11163 int x, y, wd, h;
11164 XGCValues xgcv;
11165 struct glyph *cursor_glyph;
11166 GC gc;
11167
11168 /* Compute frame-relative coordinates from window-relative
11169 coordinates. */
11170 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11171 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11172 + row->ascent - w->phys_cursor_ascent);
11173 h = row->height - 1;
11174
11175 /* Get the glyph the cursor is on. If we can't tell because
11176 the current matrix is invalid or such, give up. */
11177 cursor_glyph = get_phys_cursor_glyph (w);
11178 if (cursor_glyph == NULL)
11179 return;
11180
11181 /* Compute the width of the rectangle to draw. If on a stretch
11182 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11183 rectangle as wide as the glyph, but use a canonical character
11184 width instead. */
11185 wd = cursor_glyph->pixel_width - 1;
11186 if (cursor_glyph->type == STRETCH_GLYPH
11187 && !x_stretch_cursor_p)
11188 wd = min (CANON_X_UNIT (f), wd);
11189
11190 /* The foreground of cursor_gc is typically the same as the normal
11191 background color, which can cause the cursor box to be invisible. */
11192 xgcv.foreground = f->output_data.x->cursor_pixel;
11193 if (dpyinfo->scratch_cursor_gc)
11194 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11195 else
11196 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11197 GCForeground, &xgcv);
11198 gc = dpyinfo->scratch_cursor_gc;
11199
11200 /* Set clipping, draw the rectangle, and reset clipping again. */
11201 x_clip_to_row (w, row, gc, 0);
11202 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11203 XSetClipMask (dpy, gc, None);
11204 }
11205
11206
11207 /* Draw a bar cursor on window W in glyph row ROW.
11208
11209 Implementation note: One would like to draw a bar cursor with an
11210 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11211 Unfortunately, I didn't find a font yet that has this property set.
11212 --gerd. */
11213
11214 static void
11215 x_draw_bar_cursor (w, row, width)
11216 struct window *w;
11217 struct glyph_row *row;
11218 int width;
11219 {
11220 struct frame *f = XFRAME (w->frame);
11221 struct glyph *cursor_glyph;
11222 GC gc;
11223 int x;
11224 unsigned long mask;
11225 XGCValues xgcv;
11226 Display *dpy;
11227 Window window;
11228
11229 /* If cursor is out of bounds, don't draw garbage. This can happen
11230 in mini-buffer windows when switching between echo area glyphs
11231 and mini-buffer. */
11232 cursor_glyph = get_phys_cursor_glyph (w);
11233 if (cursor_glyph == NULL)
11234 return;
11235
11236 /* If on an image, draw like a normal cursor. That's usually better
11237 visible than drawing a bar, esp. if the image is large so that
11238 the bar might not be in the window. */
11239 if (cursor_glyph->type == IMAGE_GLYPH)
11240 {
11241 struct glyph_row *row;
11242 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11243 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11244 }
11245 else
11246 {
11247 xgcv.background = f->output_data.x->cursor_pixel;
11248 xgcv.foreground = f->output_data.x->cursor_pixel;
11249 xgcv.graphics_exposures = 0;
11250 mask = GCForeground | GCBackground | GCGraphicsExposures;
11251 dpy = FRAME_X_DISPLAY (f);
11252 window = FRAME_X_WINDOW (f);
11253 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11254
11255 if (gc)
11256 XChangeGC (dpy, gc, mask, &xgcv);
11257 else
11258 {
11259 gc = XCreateGC (dpy, window, mask, &xgcv);
11260 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11261 }
11262
11263 if (width < 0)
11264 width = f->output_data.x->cursor_width;
11265
11266 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11267 x_clip_to_row (w, row, gc, 0);
11268 XFillRectangle (dpy, window, gc,
11269 x,
11270 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11271 min (cursor_glyph->pixel_width, width),
11272 row->height);
11273 XSetClipMask (dpy, gc, None);
11274 }
11275 }
11276
11277
11278 /* Clear the cursor of window W to background color, and mark the
11279 cursor as not shown. This is used when the text where the cursor
11280 is is about to be rewritten. */
11281
11282 static void
11283 x_clear_cursor (w)
11284 struct window *w;
11285 {
11286 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11287 x_update_window_cursor (w, 0);
11288 }
11289
11290
11291 /* Draw the cursor glyph of window W in glyph row ROW. See the
11292 comment of x_draw_glyphs for the meaning of HL. */
11293
11294 static void
11295 x_draw_phys_cursor_glyph (w, row, hl)
11296 struct window *w;
11297 struct glyph_row *row;
11298 enum draw_glyphs_face hl;
11299 {
11300 /* If cursor hpos is out of bounds, don't draw garbage. This can
11301 happen in mini-buffer windows when switching between echo area
11302 glyphs and mini-buffer. */
11303 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11304 {
11305 int on_p = w->phys_cursor_on_p;
11306
11307 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11308 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11309 hl, 0);
11310 w->phys_cursor_on_p = on_p;
11311
11312 /* When we erase the cursor, and ROW is overlapped by other
11313 rows, make sure that these overlapping parts of other rows
11314 are redrawn. */
11315 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11316 {
11317 if (row > w->current_matrix->rows
11318 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11319 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11320
11321 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11322 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11323 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11324 }
11325 }
11326 }
11327
11328
11329 /* Erase the image of a cursor of window W from the screen. */
11330
11331 static void
11332 x_erase_phys_cursor (w)
11333 struct window *w;
11334 {
11335 struct frame *f = XFRAME (w->frame);
11336 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11337 int hpos = w->phys_cursor.hpos;
11338 int vpos = w->phys_cursor.vpos;
11339 int mouse_face_here_p = 0;
11340 struct glyph_matrix *active_glyphs = w->current_matrix;
11341 struct glyph_row *cursor_row;
11342 struct glyph *cursor_glyph;
11343 enum draw_glyphs_face hl;
11344
11345 /* No cursor displayed or row invalidated => nothing to do on the
11346 screen. */
11347 if (w->phys_cursor_type == NO_CURSOR)
11348 goto mark_cursor_off;
11349
11350 /* VPOS >= active_glyphs->nrows means that window has been resized.
11351 Don't bother to erase the cursor. */
11352 if (vpos >= active_glyphs->nrows)
11353 goto mark_cursor_off;
11354
11355 /* If row containing cursor is marked invalid, there is nothing we
11356 can do. */
11357 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11358 if (!cursor_row->enabled_p)
11359 goto mark_cursor_off;
11360
11361 /* This can happen when the new row is shorter than the old one.
11362 In this case, either x_draw_glyphs or clear_end_of_line
11363 should have cleared the cursor. Note that we wouldn't be
11364 able to erase the cursor in this case because we don't have a
11365 cursor glyph at hand. */
11366 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11367 goto mark_cursor_off;
11368
11369 /* If the cursor is in the mouse face area, redisplay that when
11370 we clear the cursor. */
11371 if (! NILP (dpyinfo->mouse_face_window)
11372 && w == XWINDOW (dpyinfo->mouse_face_window)
11373 && (vpos > dpyinfo->mouse_face_beg_row
11374 || (vpos == dpyinfo->mouse_face_beg_row
11375 && hpos >= dpyinfo->mouse_face_beg_col))
11376 && (vpos < dpyinfo->mouse_face_end_row
11377 || (vpos == dpyinfo->mouse_face_end_row
11378 && hpos < dpyinfo->mouse_face_end_col))
11379 /* Don't redraw the cursor's spot in mouse face if it is at the
11380 end of a line (on a newline). The cursor appears there, but
11381 mouse highlighting does not. */
11382 && cursor_row->used[TEXT_AREA] > hpos)
11383 mouse_face_here_p = 1;
11384
11385 /* Maybe clear the display under the cursor. */
11386 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11387 {
11388 int x;
11389 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11390
11391 cursor_glyph = get_phys_cursor_glyph (w);
11392 if (cursor_glyph == NULL)
11393 goto mark_cursor_off;
11394
11395 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11396
11397 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11398 x,
11399 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11400 cursor_row->y)),
11401 cursor_glyph->pixel_width,
11402 cursor_row->visible_height,
11403 False);
11404 }
11405
11406 /* Erase the cursor by redrawing the character underneath it. */
11407 if (mouse_face_here_p)
11408 hl = DRAW_MOUSE_FACE;
11409 else
11410 hl = DRAW_NORMAL_TEXT;
11411 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11412
11413 mark_cursor_off:
11414 w->phys_cursor_on_p = 0;
11415 w->phys_cursor_type = NO_CURSOR;
11416 }
11417
11418
11419 /* Non-zero if physical cursor of window W is within mouse face. */
11420
11421 static int
11422 cursor_in_mouse_face_p (w)
11423 struct window *w;
11424 {
11425 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11426 int in_mouse_face = 0;
11427
11428 if (WINDOWP (dpyinfo->mouse_face_window)
11429 && XWINDOW (dpyinfo->mouse_face_window) == w)
11430 {
11431 int hpos = w->phys_cursor.hpos;
11432 int vpos = w->phys_cursor.vpos;
11433
11434 if (vpos >= dpyinfo->mouse_face_beg_row
11435 && vpos <= dpyinfo->mouse_face_end_row
11436 && (vpos > dpyinfo->mouse_face_beg_row
11437 || hpos >= dpyinfo->mouse_face_beg_col)
11438 && (vpos < dpyinfo->mouse_face_end_row
11439 || hpos < dpyinfo->mouse_face_end_col
11440 || dpyinfo->mouse_face_past_end))
11441 in_mouse_face = 1;
11442 }
11443
11444 return in_mouse_face;
11445 }
11446
11447
11448 /* Display or clear cursor of window W. If ON is zero, clear the
11449 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11450 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11451
11452 void
11453 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11454 struct window *w;
11455 int on, hpos, vpos, x, y;
11456 {
11457 struct frame *f = XFRAME (w->frame);
11458 int new_cursor_type;
11459 int new_cursor_width;
11460 struct glyph_matrix *current_glyphs;
11461 struct glyph_row *glyph_row;
11462 struct glyph *glyph;
11463 int cursor_non_selected;
11464
11465 /* This is pointless on invisible frames, and dangerous on garbaged
11466 windows and frames; in the latter case, the frame or window may
11467 be in the midst of changing its size, and x and y may be off the
11468 window. */
11469 if (! FRAME_VISIBLE_P (f)
11470 || FRAME_GARBAGED_P (f)
11471 || vpos >= w->current_matrix->nrows
11472 || hpos >= w->current_matrix->matrix_w)
11473 return;
11474
11475 /* If cursor is off and we want it off, return quickly. */
11476 if (!on && !w->phys_cursor_on_p)
11477 return;
11478
11479 current_glyphs = w->current_matrix;
11480 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11481 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11482
11483 /* If cursor row is not enabled, we don't really know where to
11484 display the cursor. */
11485 if (!glyph_row->enabled_p)
11486 {
11487 w->phys_cursor_on_p = 0;
11488 return;
11489 }
11490
11491 xassert (interrupt_input_blocked);
11492
11493 /* Set new_cursor_type to the cursor we want to be displayed. In a
11494 mini-buffer window, we want the cursor only to appear if we are
11495 reading input from this window. For the selected window, we want
11496 the cursor type given by the frame parameter. If explicitly
11497 marked off, draw no cursor. In all other cases, we want a hollow
11498 box cursor. */
11499 cursor_non_selected
11500 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
11501 w->buffer));
11502 new_cursor_width = -1;
11503 if (cursor_in_echo_area
11504 && FRAME_HAS_MINIBUF_P (f)
11505 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
11506 {
11507 if (w == XWINDOW (echo_area_window))
11508 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11509 else if (cursor_non_selected)
11510 new_cursor_type = HOLLOW_BOX_CURSOR;
11511 else
11512 new_cursor_type = NO_CURSOR;
11513 }
11514 else
11515 {
11516 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11517 || w != XWINDOW (f->selected_window))
11518 {
11519 if (MINI_WINDOW_P (w)
11520 || !cursor_non_selected
11521 || NILP (XBUFFER (w->buffer)->cursor_type))
11522 new_cursor_type = NO_CURSOR;
11523 else
11524 new_cursor_type = HOLLOW_BOX_CURSOR;
11525 }
11526 else if (w->cursor_off_p)
11527 new_cursor_type = NO_CURSOR;
11528 else
11529 {
11530 struct buffer *b = XBUFFER (w->buffer);
11531
11532 if (EQ (b->cursor_type, Qt))
11533 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11534 else
11535 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11536 &new_cursor_width);
11537 }
11538 }
11539
11540 /* If cursor is currently being shown and we don't want it to be or
11541 it is in the wrong place, or the cursor type is not what we want,
11542 erase it. */
11543 if (w->phys_cursor_on_p
11544 && (!on
11545 || w->phys_cursor.x != x
11546 || w->phys_cursor.y != y
11547 || new_cursor_type != w->phys_cursor_type))
11548 x_erase_phys_cursor (w);
11549
11550 /* If the cursor is now invisible and we want it to be visible,
11551 display it. */
11552 if (on && !w->phys_cursor_on_p)
11553 {
11554 w->phys_cursor_ascent = glyph_row->ascent;
11555 w->phys_cursor_height = glyph_row->height;
11556
11557 /* Set phys_cursor_.* before x_draw_.* is called because some
11558 of them may need the information. */
11559 w->phys_cursor.x = x;
11560 w->phys_cursor.y = glyph_row->y;
11561 w->phys_cursor.hpos = hpos;
11562 w->phys_cursor.vpos = vpos;
11563 w->phys_cursor_type = new_cursor_type;
11564 w->phys_cursor_on_p = 1;
11565
11566 switch (new_cursor_type)
11567 {
11568 case HOLLOW_BOX_CURSOR:
11569 x_draw_hollow_cursor (w, glyph_row);
11570 break;
11571
11572 case FILLED_BOX_CURSOR:
11573 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11574 break;
11575
11576 case BAR_CURSOR:
11577 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
11578 break;
11579
11580 case NO_CURSOR:
11581 break;
11582
11583 default:
11584 abort ();
11585 }
11586
11587 #ifdef HAVE_X_I18N
11588 if (w == XWINDOW (f->selected_window))
11589 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11590 xic_set_preeditarea (w, x, y);
11591 #endif
11592 }
11593
11594 #ifndef XFlush
11595 if (updating_frame != f)
11596 XFlush (FRAME_X_DISPLAY (f));
11597 #endif
11598 }
11599
11600
11601 /* Display the cursor on window W, or clear it. X and Y are window
11602 relative pixel coordinates. HPOS and VPOS are glyph matrix
11603 positions. If W is not the selected window, display a hollow
11604 cursor. ON non-zero means display the cursor at X, Y which
11605 correspond to HPOS, VPOS, otherwise it is cleared. */
11606
11607 void
11608 x_display_cursor (w, on, hpos, vpos, x, y)
11609 struct window *w;
11610 int on, hpos, vpos, x, y;
11611 {
11612 BLOCK_INPUT;
11613 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11614 UNBLOCK_INPUT;
11615 }
11616
11617
11618 /* Display the cursor on window W, or clear it, according to ON_P.
11619 Don't change the cursor's position. */
11620
11621 void
11622 x_update_cursor (f, on_p)
11623 struct frame *f;
11624 {
11625 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11626 }
11627
11628
11629 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
11630 in the window tree rooted at W. */
11631
11632 static void
11633 x_update_cursor_in_window_tree (w, on_p)
11634 struct window *w;
11635 int on_p;
11636 {
11637 while (w)
11638 {
11639 if (!NILP (w->hchild))
11640 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11641 else if (!NILP (w->vchild))
11642 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11643 else
11644 x_update_window_cursor (w, on_p);
11645
11646 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11647 }
11648 }
11649
11650
11651 /* Switch the display of W's cursor on or off, according to the value
11652 of ON. */
11653
11654 static void
11655 x_update_window_cursor (w, on)
11656 struct window *w;
11657 int on;
11658 {
11659 /* Don't update cursor in windows whose frame is in the process
11660 of being deleted. */
11661 if (w->current_matrix)
11662 {
11663 BLOCK_INPUT;
11664 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11665 w->phys_cursor.x, w->phys_cursor.y);
11666 UNBLOCK_INPUT;
11667 }
11668 }
11669
11670
11671
11672 \f
11673 /* Icons. */
11674
11675 /* Make the x-window of frame F use the gnu icon bitmap. */
11676
11677 int
11678 x_bitmap_icon (f, file)
11679 struct frame *f;
11680 Lisp_Object file;
11681 {
11682 int bitmap_id;
11683
11684 if (FRAME_X_WINDOW (f) == 0)
11685 return 1;
11686
11687 /* Free up our existing icon bitmap if any. */
11688 if (f->output_data.x->icon_bitmap > 0)
11689 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11690 f->output_data.x->icon_bitmap = 0;
11691
11692 if (STRINGP (file))
11693 bitmap_id = x_create_bitmap_from_file (f, file);
11694 else
11695 {
11696 /* Create the GNU bitmap if necessary. */
11697 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11698 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11699 = x_create_bitmap_from_data (f, gnu_bits,
11700 gnu_width, gnu_height);
11701
11702 /* The first time we create the GNU bitmap,
11703 this increments the ref-count one extra time.
11704 As a result, the GNU bitmap is never freed.
11705 That way, we don't have to worry about allocating it again. */
11706 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11707
11708 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11709 }
11710
11711 x_wm_set_icon_pixmap (f, bitmap_id);
11712 f->output_data.x->icon_bitmap = bitmap_id;
11713
11714 return 0;
11715 }
11716
11717
11718 /* Make the x-window of frame F use a rectangle with text.
11719 Use ICON_NAME as the text. */
11720
11721 int
11722 x_text_icon (f, icon_name)
11723 struct frame *f;
11724 char *icon_name;
11725 {
11726 if (FRAME_X_WINDOW (f) == 0)
11727 return 1;
11728
11729 #ifdef HAVE_X11R4
11730 {
11731 XTextProperty text;
11732 text.value = (unsigned char *) icon_name;
11733 text.encoding = XA_STRING;
11734 text.format = 8;
11735 text.nitems = strlen (icon_name);
11736 #ifdef USE_X_TOOLKIT
11737 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11738 &text);
11739 #else /* not USE_X_TOOLKIT */
11740 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11741 #endif /* not USE_X_TOOLKIT */
11742 }
11743 #else /* not HAVE_X11R4 */
11744 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11745 #endif /* not HAVE_X11R4 */
11746
11747 if (f->output_data.x->icon_bitmap > 0)
11748 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11749 f->output_data.x->icon_bitmap = 0;
11750 x_wm_set_icon_pixmap (f, 0);
11751
11752 return 0;
11753 }
11754 \f
11755 #define X_ERROR_MESSAGE_SIZE 200
11756
11757 /* If non-nil, this should be a string.
11758 It means catch X errors and store the error message in this string. */
11759
11760 static Lisp_Object x_error_message_string;
11761
11762 /* An X error handler which stores the error message in
11763 x_error_message_string. This is called from x_error_handler if
11764 x_catch_errors is in effect. */
11765
11766 static void
11767 x_error_catcher (display, error)
11768 Display *display;
11769 XErrorEvent *error;
11770 {
11771 XGetErrorText (display, error->error_code,
11772 XSTRING (x_error_message_string)->data,
11773 X_ERROR_MESSAGE_SIZE);
11774 }
11775
11776 /* Begin trapping X errors for display DPY. Actually we trap X errors
11777 for all displays, but DPY should be the display you are actually
11778 operating on.
11779
11780 After calling this function, X protocol errors no longer cause
11781 Emacs to exit; instead, they are recorded in the string
11782 stored in x_error_message_string.
11783
11784 Calling x_check_errors signals an Emacs error if an X error has
11785 occurred since the last call to x_catch_errors or x_check_errors.
11786
11787 Calling x_uncatch_errors resumes the normal error handling. */
11788
11789 void x_check_errors ();
11790 static Lisp_Object x_catch_errors_unwind ();
11791
11792 int
11793 x_catch_errors (dpy)
11794 Display *dpy;
11795 {
11796 int count = specpdl_ptr - specpdl;
11797
11798 /* Make sure any errors from previous requests have been dealt with. */
11799 XSync (dpy, False);
11800
11801 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11802
11803 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11804 XSTRING (x_error_message_string)->data[0] = 0;
11805
11806 return count;
11807 }
11808
11809 /* Unbind the binding that we made to check for X errors. */
11810
11811 static Lisp_Object
11812 x_catch_errors_unwind (old_val)
11813 Lisp_Object old_val;
11814 {
11815 x_error_message_string = old_val;
11816 return Qnil;
11817 }
11818
11819 /* If any X protocol errors have arrived since the last call to
11820 x_catch_errors or x_check_errors, signal an Emacs error using
11821 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11822
11823 void
11824 x_check_errors (dpy, format)
11825 Display *dpy;
11826 char *format;
11827 {
11828 /* Make sure to catch any errors incurred so far. */
11829 XSync (dpy, False);
11830
11831 if (XSTRING (x_error_message_string)->data[0])
11832 error (format, XSTRING (x_error_message_string)->data);
11833 }
11834
11835 /* Nonzero if we had any X protocol errors
11836 since we did x_catch_errors on DPY. */
11837
11838 int
11839 x_had_errors_p (dpy)
11840 Display *dpy;
11841 {
11842 /* Make sure to catch any errors incurred so far. */
11843 XSync (dpy, False);
11844
11845 return XSTRING (x_error_message_string)->data[0] != 0;
11846 }
11847
11848 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11849
11850 void
11851 x_clear_errors (dpy)
11852 Display *dpy;
11853 {
11854 XSTRING (x_error_message_string)->data[0] = 0;
11855 }
11856
11857 /* Stop catching X protocol errors and let them make Emacs die.
11858 DPY should be the display that was passed to x_catch_errors.
11859 COUNT should be the value that was returned by
11860 the corresponding call to x_catch_errors. */
11861
11862 void
11863 x_uncatch_errors (dpy, count)
11864 Display *dpy;
11865 int count;
11866 {
11867 unbind_to (count, Qnil);
11868 }
11869
11870 #if 0
11871 static unsigned int x_wire_count;
11872 x_trace_wire ()
11873 {
11874 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11875 }
11876 #endif /* ! 0 */
11877
11878 \f
11879 /* Handle SIGPIPE, which can happen when the connection to a server
11880 simply goes away. SIGPIPE is handled by x_connection_signal.
11881 Don't need to do anything, because the write which caused the
11882 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11883 which will do the appropriate cleanup for us. */
11884
11885 static SIGTYPE
11886 x_connection_signal (signalnum) /* If we don't have an argument, */
11887 int signalnum; /* some compilers complain in signal calls. */
11888 {
11889 #ifdef USG
11890 /* USG systems forget handlers when they are used;
11891 must reestablish each time */
11892 signal (signalnum, x_connection_signal);
11893 #endif /* USG */
11894 }
11895
11896 \f
11897 /************************************************************************
11898 Handling X errors
11899 ************************************************************************/
11900
11901 /* Error message passed to x_connection_closed. */
11902
11903 static char *error_msg;
11904
11905 /* Function installed as fatal_error_signal_hook in
11906 x_connection_closed. Print the X error message, and exit normally,
11907 instead of dumping core when XtCloseDisplay fails. */
11908
11909 static void
11910 x_fatal_error_signal ()
11911 {
11912 fprintf (stderr, "%s\n", error_msg);
11913 exit (70);
11914 }
11915
11916 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11917 the text of an error message that lead to the connection loss. */
11918
11919 static SIGTYPE
11920 x_connection_closed (dpy, error_message)
11921 Display *dpy;
11922 char *error_message;
11923 {
11924 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
11925 Lisp_Object frame, tail;
11926 int count;
11927
11928 error_msg = (char *) alloca (strlen (error_message) + 1);
11929 strcpy (error_msg, error_message);
11930 handling_signal = 0;
11931
11932 /* Prevent being called recursively because of an error condition
11933 below. Otherwise, we might end up with printing ``can't find per
11934 display information'' in the recursive call instead of printing
11935 the original message here. */
11936 count = x_catch_errors (dpy);
11937
11938 /* We have to close the display to inform Xt that it doesn't
11939 exist anymore. If we don't, Xt will continue to wait for
11940 events from the display. As a consequence, a sequence of
11941
11942 M-x make-frame-on-display RET :1 RET
11943 ...kill the new frame, so that we get an IO error...
11944 M-x make-frame-on-display RET :1 RET
11945
11946 will indefinitely wait in Xt for events for display `:1', opened
11947 in the first class to make-frame-on-display.
11948
11949 Closing the display is reported to lead to a bus error on
11950 OpenWindows in certain situations. I suspect that is a bug
11951 in OpenWindows. I don't know how to cicumvent it here. */
11952
11953 #ifdef USE_X_TOOLKIT
11954 /* If DPYINFO is null, this means we didn't open the display
11955 in the first place, so don't try to close it. */
11956 if (dpyinfo)
11957 {
11958 extern void (*fatal_error_signal_hook) P_ ((void));
11959 fatal_error_signal_hook = x_fatal_error_signal;
11960 XtCloseDisplay (dpy);
11961 fatal_error_signal_hook = NULL;
11962 }
11963 #endif
11964
11965 /* Indicate that this display is dead. */
11966 if (dpyinfo)
11967 dpyinfo->display = 0;
11968
11969 /* First delete frames whose mini-buffers are on frames
11970 that are on the dead display. */
11971 FOR_EACH_FRAME (tail, frame)
11972 {
11973 Lisp_Object minibuf_frame;
11974 minibuf_frame
11975 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11976 if (FRAME_X_P (XFRAME (frame))
11977 && FRAME_X_P (XFRAME (minibuf_frame))
11978 && ! EQ (frame, minibuf_frame)
11979 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11980 Fdelete_frame (frame, Qt);
11981 }
11982
11983 /* Now delete all remaining frames on the dead display.
11984 We are now sure none of these is used as the mini-buffer
11985 for another frame that we need to delete. */
11986 FOR_EACH_FRAME (tail, frame)
11987 if (FRAME_X_P (XFRAME (frame))
11988 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11989 {
11990 /* Set this to t so that Fdelete_frame won't get confused
11991 trying to find a replacement. */
11992 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11993 Fdelete_frame (frame, Qt);
11994 }
11995
11996 if (dpyinfo)
11997 x_delete_display (dpyinfo);
11998
11999 x_uncatch_errors (dpy, count);
12000
12001 if (x_display_list == 0)
12002 {
12003 fprintf (stderr, "%s\n", error_msg);
12004 shut_down_emacs (0, 0, Qnil);
12005 exit (70);
12006 }
12007
12008 /* Ordinary stack unwind doesn't deal with these. */
12009 #ifdef SIGIO
12010 sigunblock (sigmask (SIGIO));
12011 #endif
12012 sigunblock (sigmask (SIGALRM));
12013 TOTALLY_UNBLOCK_INPUT;
12014
12015 clear_waiting_for_input ();
12016 error ("%s", error_msg);
12017 }
12018
12019
12020 /* This is the usual handler for X protocol errors.
12021 It kills all frames on the display that we got the error for.
12022 If that was the only one, it prints an error message and kills Emacs. */
12023
12024 static void
12025 x_error_quitter (display, error)
12026 Display *display;
12027 XErrorEvent *error;
12028 {
12029 char buf[256], buf1[356];
12030
12031 /* Note that there is no real way portable across R3/R4 to get the
12032 original error handler. */
12033
12034 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12035 sprintf (buf1, "X protocol error: %s on protocol request %d",
12036 buf, error->request_code);
12037 x_connection_closed (display, buf1);
12038 }
12039
12040
12041 /* This is the first-level handler for X protocol errors.
12042 It calls x_error_quitter or x_error_catcher. */
12043
12044 static int
12045 x_error_handler (display, error)
12046 Display *display;
12047 XErrorEvent *error;
12048 {
12049 if (! NILP (x_error_message_string))
12050 x_error_catcher (display, error);
12051 else
12052 x_error_quitter (display, error);
12053 return 0;
12054 }
12055
12056 /* This is the handler for X IO errors, always.
12057 It kills all frames on the display that we lost touch with.
12058 If that was the only one, it prints an error message and kills Emacs. */
12059
12060 static int
12061 x_io_error_quitter (display)
12062 Display *display;
12063 {
12064 char buf[256];
12065
12066 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12067 x_connection_closed (display, buf);
12068 return 0;
12069 }
12070 \f
12071 /* Changing the font of the frame. */
12072
12073 /* Give frame F the font named FONTNAME as its default font, and
12074 return the full name of that font. FONTNAME may be a wildcard
12075 pattern; in that case, we choose some font that fits the pattern.
12076 The return value shows which font we chose. */
12077
12078 Lisp_Object
12079 x_new_font (f, fontname)
12080 struct frame *f;
12081 register char *fontname;
12082 {
12083 struct font_info *fontp
12084 = FS_LOAD_FONT (f, 0, fontname, -1);
12085
12086 if (!fontp)
12087 return Qnil;
12088
12089 f->output_data.x->font = (XFontStruct *) (fontp->font);
12090 f->output_data.x->baseline_offset = fontp->baseline_offset;
12091 f->output_data.x->fontset = -1;
12092
12093 /* Compute the scroll bar width in character columns. */
12094 if (f->scroll_bar_pixel_width > 0)
12095 {
12096 int wid = FONT_WIDTH (f->output_data.x->font);
12097 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12098 }
12099 else
12100 {
12101 int wid = FONT_WIDTH (f->output_data.x->font);
12102 f->scroll_bar_cols = (14 + wid - 1) / wid;
12103 }
12104
12105 /* Now make the frame display the given font. */
12106 if (FRAME_X_WINDOW (f) != 0)
12107 {
12108 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12109 f->output_data.x->font->fid);
12110 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12111 f->output_data.x->font->fid);
12112 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12113 f->output_data.x->font->fid);
12114
12115 frame_update_line_height (f);
12116
12117 /* Don't change the size of a tip frame; there's no point in
12118 doing it because it's done in Fx_show_tip, and it leads to
12119 problems because the tip frame has no widget. */
12120 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12121 x_set_window_size (f, 0, f->width, f->height);
12122 }
12123 else
12124 /* If we are setting a new frame's font for the first time,
12125 there are no faces yet, so this font's height is the line height. */
12126 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12127
12128 return build_string (fontp->full_name);
12129 }
12130
12131 /* Give frame F the fontset named FONTSETNAME as its default font, and
12132 return the full name of that fontset. FONTSETNAME may be a wildcard
12133 pattern; in that case, we choose some fontset that fits the pattern.
12134 The return value shows which fontset we chose. */
12135
12136 Lisp_Object
12137 x_new_fontset (f, fontsetname)
12138 struct frame *f;
12139 char *fontsetname;
12140 {
12141 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12142 Lisp_Object result;
12143
12144 if (fontset < 0)
12145 return Qnil;
12146
12147 if (f->output_data.x->fontset == fontset)
12148 /* This fontset is already set in frame F. There's nothing more
12149 to do. */
12150 return fontset_name (fontset);
12151
12152 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
12153
12154 if (!STRINGP (result))
12155 /* Can't load ASCII font. */
12156 return Qnil;
12157
12158 /* Since x_new_font doesn't update any fontset information, do it now. */
12159 f->output_data.x->fontset = fontset;
12160
12161 #ifdef HAVE_X_I18N
12162 if (FRAME_XIC (f)
12163 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12164 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
12165 #endif
12166
12167 return build_string (fontsetname);
12168 }
12169
12170 \f
12171 /***********************************************************************
12172 X Input Methods
12173 ***********************************************************************/
12174
12175 #ifdef HAVE_X_I18N
12176
12177 #ifdef HAVE_X11R6
12178
12179 /* XIM destroy callback function, which is called whenever the
12180 connection to input method XIM dies. CLIENT_DATA contains a
12181 pointer to the x_display_info structure corresponding to XIM. */
12182
12183 static void
12184 xim_destroy_callback (xim, client_data, call_data)
12185 XIM xim;
12186 XPointer client_data;
12187 XPointer call_data;
12188 {
12189 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12190 Lisp_Object frame, tail;
12191
12192 BLOCK_INPUT;
12193
12194 /* No need to call XDestroyIC.. */
12195 FOR_EACH_FRAME (tail, frame)
12196 {
12197 struct frame *f = XFRAME (frame);
12198 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12199 {
12200 FRAME_XIC (f) = NULL;
12201 if (FRAME_XIC_FONTSET (f))
12202 {
12203 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12204 FRAME_XIC_FONTSET (f) = NULL;
12205 }
12206 }
12207 }
12208
12209 /* No need to call XCloseIM. */
12210 dpyinfo->xim = NULL;
12211 XFree (dpyinfo->xim_styles);
12212 UNBLOCK_INPUT;
12213 }
12214
12215 #endif /* HAVE_X11R6 */
12216
12217 /* Open the connection to the XIM server on display DPYINFO.
12218 RESOURCE_NAME is the resource name Emacs uses. */
12219
12220 static void
12221 xim_open_dpy (dpyinfo, resource_name)
12222 struct x_display_info *dpyinfo;
12223 char *resource_name;
12224 {
12225 #ifdef USE_XIM
12226 XIM xim;
12227
12228 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12229 dpyinfo->xim = xim;
12230
12231 if (xim)
12232 {
12233 #ifdef HAVE_X11R6
12234 XIMCallback destroy;
12235 #endif
12236
12237 /* Get supported styles and XIM values. */
12238 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12239
12240 #ifdef HAVE_X11R6
12241 destroy.callback = xim_destroy_callback;
12242 destroy.client_data = (XPointer)dpyinfo;
12243 /* This isn't prototyped in OSF 5.0. */
12244 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12245 #endif
12246 }
12247
12248 #else /* not USE_XIM */
12249 dpyinfo->xim = NULL;
12250 #endif /* not USE_XIM */
12251 }
12252
12253
12254 #ifdef HAVE_X11R6_XIM
12255
12256 struct xim_inst_t
12257 {
12258 struct x_display_info *dpyinfo;
12259 char *resource_name;
12260 };
12261
12262 /* XIM instantiate callback function, which is called whenever an XIM
12263 server is available. DISPLAY is teh display of the XIM.
12264 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12265 when the callback was registered. */
12266
12267 static void
12268 xim_instantiate_callback (display, client_data, call_data)
12269 Display *display;
12270 XPointer client_data;
12271 XPointer call_data;
12272 {
12273 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12274 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12275
12276 /* We don't support multiple XIM connections. */
12277 if (dpyinfo->xim)
12278 return;
12279
12280 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12281
12282 /* Create XIC for the existing frames on the same display, as long
12283 as they have no XIC. */
12284 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12285 {
12286 Lisp_Object tail, frame;
12287
12288 BLOCK_INPUT;
12289 FOR_EACH_FRAME (tail, frame)
12290 {
12291 struct frame *f = XFRAME (frame);
12292
12293 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12294 if (FRAME_XIC (f) == NULL)
12295 {
12296 create_frame_xic (f);
12297 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12298 xic_set_statusarea (f);
12299 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12300 {
12301 struct window *w = XWINDOW (f->selected_window);
12302 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12303 }
12304 }
12305 }
12306
12307 UNBLOCK_INPUT;
12308 }
12309 }
12310
12311 #endif /* HAVE_X11R6_XIM */
12312
12313
12314 /* Open a connection to the XIM server on display DPYINFO.
12315 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12316 connection only at the first time. On X11R6, open the connection
12317 in the XIM instantiate callback function. */
12318
12319 static void
12320 xim_initialize (dpyinfo, resource_name)
12321 struct x_display_info *dpyinfo;
12322 char *resource_name;
12323 {
12324 #ifdef USE_XIM
12325 #ifdef HAVE_X11R6_XIM
12326 struct xim_inst_t *xim_inst;
12327 int len;
12328
12329 dpyinfo->xim = NULL;
12330 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12331 xim_inst->dpyinfo = dpyinfo;
12332 len = strlen (resource_name);
12333 xim_inst->resource_name = (char *) xmalloc (len + 1);
12334 bcopy (resource_name, xim_inst->resource_name, len + 1);
12335 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12336 resource_name, EMACS_CLASS,
12337 xim_instantiate_callback,
12338 /* Fixme: This is XPointer in
12339 XFree86 but (XPointer *) on
12340 Tru64, at least. */
12341 (XPointer) xim_inst);
12342 #else /* not HAVE_X11R6_XIM */
12343 dpyinfo->xim = NULL;
12344 xim_open_dpy (dpyinfo, resource_name);
12345 #endif /* not HAVE_X11R6_XIM */
12346
12347 #else /* not USE_XIM */
12348 dpyinfo->xim = NULL;
12349 #endif /* not USE_XIM */
12350 }
12351
12352
12353 /* Close the connection to the XIM server on display DPYINFO. */
12354
12355 static void
12356 xim_close_dpy (dpyinfo)
12357 struct x_display_info *dpyinfo;
12358 {
12359 #ifdef USE_XIM
12360 #ifdef HAVE_X11R6_XIM
12361 if (dpyinfo->display)
12362 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12363 NULL, EMACS_CLASS,
12364 xim_instantiate_callback, NULL);
12365 #endif /* not HAVE_X11R6_XIM */
12366 if (dpyinfo->display)
12367 XCloseIM (dpyinfo->xim);
12368 dpyinfo->xim = NULL;
12369 XFree (dpyinfo->xim_styles);
12370 #endif /* USE_XIM */
12371 }
12372
12373 #endif /* not HAVE_X11R6_XIM */
12374
12375
12376 \f
12377 /* Calculate the absolute position in frame F
12378 from its current recorded position values and gravity. */
12379
12380 void
12381 x_calc_absolute_position (f)
12382 struct frame *f;
12383 {
12384 Window child;
12385 int win_x = 0, win_y = 0;
12386 int flags = f->output_data.x->size_hint_flags;
12387 int this_window;
12388
12389 /* We have nothing to do if the current position
12390 is already for the top-left corner. */
12391 if (! ((flags & XNegative) || (flags & YNegative)))
12392 return;
12393
12394 #ifdef USE_X_TOOLKIT
12395 this_window = XtWindow (f->output_data.x->widget);
12396 #else
12397 this_window = FRAME_X_WINDOW (f);
12398 #endif
12399
12400 /* Find the position of the outside upper-left corner of
12401 the inner window, with respect to the outer window.
12402 But do this only if we will need the results. */
12403 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12404 {
12405 int count;
12406
12407 BLOCK_INPUT;
12408 count = x_catch_errors (FRAME_X_DISPLAY (f));
12409 while (1)
12410 {
12411 x_clear_errors (FRAME_X_DISPLAY (f));
12412 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12413
12414 /* From-window, to-window. */
12415 this_window,
12416 f->output_data.x->parent_desc,
12417
12418 /* From-position, to-position. */
12419 0, 0, &win_x, &win_y,
12420
12421 /* Child of win. */
12422 &child);
12423 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12424 {
12425 Window newroot, newparent = 0xdeadbeef;
12426 Window *newchildren;
12427 unsigned int nchildren;
12428
12429 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12430 &newparent, &newchildren, &nchildren))
12431 break;
12432
12433 XFree ((char *) newchildren);
12434
12435 f->output_data.x->parent_desc = newparent;
12436 }
12437 else
12438 break;
12439 }
12440
12441 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12442 UNBLOCK_INPUT;
12443 }
12444
12445 /* Treat negative positions as relative to the leftmost bottommost
12446 position that fits on the screen. */
12447 if (flags & XNegative)
12448 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12449 - 2 * f->output_data.x->border_width - win_x
12450 - PIXEL_WIDTH (f)
12451 + f->output_data.x->left_pos);
12452
12453 {
12454 int height = PIXEL_HEIGHT (f);
12455
12456 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12457 /* Something is fishy here. When using Motif, starting Emacs with
12458 `-g -0-0', the frame appears too low by a few pixels.
12459
12460 This seems to be so because initially, while Emacs is starting,
12461 the column widget's height and the frame's pixel height are
12462 different. The column widget's height is the right one. In
12463 later invocations, when Emacs is up, the frame's pixel height
12464 is right, though.
12465
12466 It's not obvious where the initial small difference comes from.
12467 2000-12-01, gerd. */
12468
12469 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12470 #endif
12471
12472 if (flags & YNegative)
12473 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12474 - 2 * f->output_data.x->border_width
12475 - win_y
12476 - height
12477 + f->output_data.x->top_pos);
12478 }
12479
12480 /* The left_pos and top_pos
12481 are now relative to the top and left screen edges,
12482 so the flags should correspond. */
12483 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12484 }
12485
12486 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12487 to really change the position, and 0 when calling from
12488 x_make_frame_visible (in that case, XOFF and YOFF are the current
12489 position values). It is -1 when calling from x_set_frame_parameters,
12490 which means, do adjust for borders but don't change the gravity. */
12491
12492 void
12493 x_set_offset (f, xoff, yoff, change_gravity)
12494 struct frame *f;
12495 register int xoff, yoff;
12496 int change_gravity;
12497 {
12498 int modified_top, modified_left;
12499
12500 if (change_gravity > 0)
12501 {
12502 f->output_data.x->top_pos = yoff;
12503 f->output_data.x->left_pos = xoff;
12504 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12505 if (xoff < 0)
12506 f->output_data.x->size_hint_flags |= XNegative;
12507 if (yoff < 0)
12508 f->output_data.x->size_hint_flags |= YNegative;
12509 f->output_data.x->win_gravity = NorthWestGravity;
12510 }
12511 x_calc_absolute_position (f);
12512
12513 BLOCK_INPUT;
12514 x_wm_set_size_hint (f, (long) 0, 0);
12515
12516 modified_left = f->output_data.x->left_pos;
12517 modified_top = f->output_data.x->top_pos;
12518 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12519 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12520 /* It is a mystery why we need to add the border_width here
12521 when the frame is already visible, but experiment says we do. */
12522 if (change_gravity != 0)
12523 {
12524 modified_left += f->output_data.x->border_width;
12525 modified_top += f->output_data.x->border_width;
12526 }
12527 #endif
12528
12529 #ifdef USE_X_TOOLKIT
12530 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12531 modified_left, modified_top);
12532 #else /* not USE_X_TOOLKIT */
12533 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12534 modified_left, modified_top);
12535 #endif /* not USE_X_TOOLKIT */
12536 UNBLOCK_INPUT;
12537 }
12538
12539
12540 /* Change the size of frame F's X window to COLS/ROWS in the case F
12541 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12542 top-left-corner window gravity for this size change and subsequent
12543 size changes. Otherwise we leave the window gravity unchanged. */
12544
12545 static void
12546 x_set_window_size_1 (f, change_gravity, cols, rows)
12547 struct frame *f;
12548 int change_gravity;
12549 int cols, rows;
12550 {
12551 int pixelwidth, pixelheight;
12552
12553 check_frame_size (f, &rows, &cols);
12554 f->output_data.x->vertical_scroll_bar_extra
12555 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12556 ? 0
12557 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
12558 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
12559 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
12560 f->output_data.x->flags_areas_extra
12561 = FRAME_FLAGS_AREA_WIDTH (f);
12562 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12563 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
12564
12565 f->output_data.x->win_gravity = NorthWestGravity;
12566 x_wm_set_size_hint (f, (long) 0, 0);
12567
12568 XSync (FRAME_X_DISPLAY (f), False);
12569 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12570 pixelwidth, pixelheight);
12571
12572 /* Now, strictly speaking, we can't be sure that this is accurate,
12573 but the window manager will get around to dealing with the size
12574 change request eventually, and we'll hear how it went when the
12575 ConfigureNotify event gets here.
12576
12577 We could just not bother storing any of this information here,
12578 and let the ConfigureNotify event set everything up, but that
12579 might be kind of confusing to the Lisp code, since size changes
12580 wouldn't be reported in the frame parameters until some random
12581 point in the future when the ConfigureNotify event arrives.
12582
12583 We pass 1 for DELAY since we can't run Lisp code inside of
12584 a BLOCK_INPUT. */
12585 change_frame_size (f, rows, cols, 0, 1, 0);
12586 PIXEL_WIDTH (f) = pixelwidth;
12587 PIXEL_HEIGHT (f) = pixelheight;
12588
12589 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12590 receive in the ConfigureNotify event; if we get what we asked
12591 for, then the event won't cause the screen to become garbaged, so
12592 we have to make sure to do it here. */
12593 SET_FRAME_GARBAGED (f);
12594
12595 XFlush (FRAME_X_DISPLAY (f));
12596 }
12597
12598
12599 /* Call this to change the size of frame F's x-window.
12600 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12601 for this size change and subsequent size changes.
12602 Otherwise we leave the window gravity unchanged. */
12603
12604 void
12605 x_set_window_size (f, change_gravity, cols, rows)
12606 struct frame *f;
12607 int change_gravity;
12608 int cols, rows;
12609 {
12610 BLOCK_INPUT;
12611
12612 #ifdef USE_X_TOOLKIT
12613
12614 if (f->output_data.x->widget != NULL)
12615 {
12616 /* The x and y position of the widget is clobbered by the
12617 call to XtSetValues within EmacsFrameSetCharSize.
12618 This is a real kludge, but I don't understand Xt so I can't
12619 figure out a correct fix. Can anyone else tell me? -- rms. */
12620 int xpos = f->output_data.x->widget->core.x;
12621 int ypos = f->output_data.x->widget->core.y;
12622 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12623 f->output_data.x->widget->core.x = xpos;
12624 f->output_data.x->widget->core.y = ypos;
12625 }
12626 else
12627 x_set_window_size_1 (f, change_gravity, cols, rows);
12628
12629 #else /* not USE_X_TOOLKIT */
12630
12631 x_set_window_size_1 (f, change_gravity, cols, rows);
12632
12633 #endif /* not USE_X_TOOLKIT */
12634
12635 /* If cursor was outside the new size, mark it as off. */
12636 mark_window_cursors_off (XWINDOW (f->root_window));
12637
12638 /* Clear out any recollection of where the mouse highlighting was,
12639 since it might be in a place that's outside the new frame size.
12640 Actually checking whether it is outside is a pain in the neck,
12641 so don't try--just let the highlighting be done afresh with new size. */
12642 cancel_mouse_face (f);
12643
12644 UNBLOCK_INPUT;
12645 }
12646 \f
12647 /* Mouse warping. */
12648
12649 void
12650 x_set_mouse_position (f, x, y)
12651 struct frame *f;
12652 int x, y;
12653 {
12654 int pix_x, pix_y;
12655
12656 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12657 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
12658
12659 if (pix_x < 0) pix_x = 0;
12660 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12661
12662 if (pix_y < 0) pix_y = 0;
12663 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
12664
12665 BLOCK_INPUT;
12666
12667 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12668 0, 0, 0, 0, pix_x, pix_y);
12669 UNBLOCK_INPUT;
12670 }
12671
12672 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12673
12674 void
12675 x_set_mouse_pixel_position (f, pix_x, pix_y)
12676 struct frame *f;
12677 int pix_x, pix_y;
12678 {
12679 BLOCK_INPUT;
12680
12681 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12682 0, 0, 0, 0, pix_x, pix_y);
12683 UNBLOCK_INPUT;
12684 }
12685 \f
12686 /* focus shifting, raising and lowering. */
12687
12688 void
12689 x_focus_on_frame (f)
12690 struct frame *f;
12691 {
12692 #if 0 /* This proves to be unpleasant. */
12693 x_raise_frame (f);
12694 #endif
12695 #if 0
12696 /* I don't think that the ICCCM allows programs to do things like this
12697 without the interaction of the window manager. Whatever you end up
12698 doing with this code, do it to x_unfocus_frame too. */
12699 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12700 RevertToPointerRoot, CurrentTime);
12701 #endif /* ! 0 */
12702 }
12703
12704 void
12705 x_unfocus_frame (f)
12706 struct frame *f;
12707 {
12708 #if 0
12709 /* Look at the remarks in x_focus_on_frame. */
12710 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
12711 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
12712 RevertToPointerRoot, CurrentTime);
12713 #endif /* ! 0 */
12714 }
12715
12716 /* Raise frame F. */
12717
12718 void
12719 x_raise_frame (f)
12720 struct frame *f;
12721 {
12722 if (f->async_visible)
12723 {
12724 BLOCK_INPUT;
12725 #ifdef USE_X_TOOLKIT
12726 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12727 #else /* not USE_X_TOOLKIT */
12728 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12729 #endif /* not USE_X_TOOLKIT */
12730 XFlush (FRAME_X_DISPLAY (f));
12731 UNBLOCK_INPUT;
12732 }
12733 }
12734
12735 /* Lower frame F. */
12736
12737 void
12738 x_lower_frame (f)
12739 struct frame *f;
12740 {
12741 if (f->async_visible)
12742 {
12743 BLOCK_INPUT;
12744 #ifdef USE_X_TOOLKIT
12745 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12746 #else /* not USE_X_TOOLKIT */
12747 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12748 #endif /* not USE_X_TOOLKIT */
12749 XFlush (FRAME_X_DISPLAY (f));
12750 UNBLOCK_INPUT;
12751 }
12752 }
12753
12754 static void
12755 XTframe_raise_lower (f, raise_flag)
12756 FRAME_PTR f;
12757 int raise_flag;
12758 {
12759 if (raise_flag)
12760 x_raise_frame (f);
12761 else
12762 x_lower_frame (f);
12763 }
12764 \f
12765 /* Change of visibility. */
12766
12767 /* This tries to wait until the frame is really visible.
12768 However, if the window manager asks the user where to position
12769 the frame, this will return before the user finishes doing that.
12770 The frame will not actually be visible at that time,
12771 but it will become visible later when the window manager
12772 finishes with it. */
12773
12774 void
12775 x_make_frame_visible (f)
12776 struct frame *f;
12777 {
12778 Lisp_Object type;
12779 int original_top, original_left;
12780 int retry_count = 2;
12781
12782 retry:
12783
12784 BLOCK_INPUT;
12785
12786 type = x_icon_type (f);
12787 if (!NILP (type))
12788 x_bitmap_icon (f, type);
12789
12790 if (! FRAME_VISIBLE_P (f))
12791 {
12792 /* We test FRAME_GARBAGED_P here to make sure we don't
12793 call x_set_offset a second time
12794 if we get to x_make_frame_visible a second time
12795 before the window gets really visible. */
12796 if (! FRAME_ICONIFIED_P (f)
12797 && ! f->output_data.x->asked_for_visible)
12798 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12799
12800 f->output_data.x->asked_for_visible = 1;
12801
12802 if (! EQ (Vx_no_window_manager, Qt))
12803 x_wm_set_window_state (f, NormalState);
12804 #ifdef USE_X_TOOLKIT
12805 /* This was XtPopup, but that did nothing for an iconified frame. */
12806 XtMapWidget (f->output_data.x->widget);
12807 #else /* not USE_X_TOOLKIT */
12808 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12809 #endif /* not USE_X_TOOLKIT */
12810 #if 0 /* This seems to bring back scroll bars in the wrong places
12811 if the window configuration has changed. They seem
12812 to come back ok without this. */
12813 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12814 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12815 #endif
12816 }
12817
12818 XFlush (FRAME_X_DISPLAY (f));
12819
12820 /* Synchronize to ensure Emacs knows the frame is visible
12821 before we do anything else. We do this loop with input not blocked
12822 so that incoming events are handled. */
12823 {
12824 Lisp_Object frame;
12825 int count;
12826 /* This must be before UNBLOCK_INPUT
12827 since events that arrive in response to the actions above
12828 will set it when they are handled. */
12829 int previously_visible = f->output_data.x->has_been_visible;
12830
12831 original_left = f->output_data.x->left_pos;
12832 original_top = f->output_data.x->top_pos;
12833
12834 /* This must come after we set COUNT. */
12835 UNBLOCK_INPUT;
12836
12837 /* We unblock here so that arriving X events are processed. */
12838
12839 /* Now move the window back to where it was "supposed to be".
12840 But don't do it if the gravity is negative.
12841 When the gravity is negative, this uses a position
12842 that is 3 pixels too low. Perhaps that's really the border width.
12843
12844 Don't do this if the window has never been visible before,
12845 because the window manager may choose the position
12846 and we don't want to override it. */
12847
12848 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12849 && f->output_data.x->win_gravity == NorthWestGravity
12850 && previously_visible)
12851 {
12852 Drawable rootw;
12853 int x, y;
12854 unsigned int width, height, border, depth;
12855
12856 BLOCK_INPUT;
12857
12858 /* On some window managers (such as FVWM) moving an existing
12859 window, even to the same place, causes the window manager
12860 to introduce an offset. This can cause the window to move
12861 to an unexpected location. Check the geometry (a little
12862 slow here) and then verify that the window is in the right
12863 place. If the window is not in the right place, move it
12864 there, and take the potential window manager hit. */
12865 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12866 &rootw, &x, &y, &width, &height, &border, &depth);
12867
12868 if (original_left != x || original_top != y)
12869 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12870 original_left, original_top);
12871
12872 UNBLOCK_INPUT;
12873 }
12874
12875 XSETFRAME (frame, f);
12876
12877 /* Wait until the frame is visible. Process X events until a
12878 MapNotify event has been seen, or until we think we won't get a
12879 MapNotify at all.. */
12880 for (count = input_signal_count + 10;
12881 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12882 {
12883 /* Force processing of queued events. */
12884 x_sync (f);
12885
12886 /* Machines that do polling rather than SIGIO have been
12887 observed to go into a busy-wait here. So we'll fake an
12888 alarm signal to let the handler know that there's something
12889 to be read. We used to raise a real alarm, but it seems
12890 that the handler isn't always enabled here. This is
12891 probably a bug. */
12892 if (input_polling_used ())
12893 {
12894 /* It could be confusing if a real alarm arrives while
12895 processing the fake one. Turn it off and let the
12896 handler reset it. */
12897 extern void poll_for_input_1 P_ ((void));
12898 int old_poll_suppress_count = poll_suppress_count;
12899 poll_suppress_count = 1;
12900 poll_for_input_1 ();
12901 poll_suppress_count = old_poll_suppress_count;
12902 }
12903
12904 /* See if a MapNotify event has been processed. */
12905 FRAME_SAMPLE_VISIBILITY (f);
12906 }
12907
12908 /* 2000-09-28: In
12909
12910 (let ((f (selected-frame)))
12911 (iconify-frame f)
12912 (raise-frame f))
12913
12914 the frame is not raised with various window managers on
12915 FreeBSD, Linux and Solaris. It turns out that, for some
12916 unknown reason, the call to XtMapWidget is completely ignored.
12917 Mapping the widget a second time works. */
12918
12919 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12920 goto retry;
12921 }
12922 }
12923
12924 /* Change from mapped state to withdrawn state. */
12925
12926 /* Make the frame visible (mapped and not iconified). */
12927
12928 void
12929 x_make_frame_invisible (f)
12930 struct frame *f;
12931 {
12932 Window window;
12933
12934 #ifdef USE_X_TOOLKIT
12935 /* Use the frame's outermost window, not the one we normally draw on. */
12936 window = XtWindow (f->output_data.x->widget);
12937 #else /* not USE_X_TOOLKIT */
12938 window = FRAME_X_WINDOW (f);
12939 #endif /* not USE_X_TOOLKIT */
12940
12941 /* Don't keep the highlight on an invisible frame. */
12942 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12943 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12944
12945 #if 0/* This might add unreliability; I don't trust it -- rms. */
12946 if (! f->async_visible && ! f->async_iconified)
12947 return;
12948 #endif
12949
12950 BLOCK_INPUT;
12951
12952 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12953 that the current position of the window is user-specified, rather than
12954 program-specified, so that when the window is mapped again, it will be
12955 placed at the same location, without forcing the user to position it
12956 by hand again (they have already done that once for this window.) */
12957 x_wm_set_size_hint (f, (long) 0, 1);
12958
12959 #ifdef HAVE_X11R4
12960
12961 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12962 DefaultScreen (FRAME_X_DISPLAY (f))))
12963 {
12964 UNBLOCK_INPUT_RESIGNAL;
12965 error ("Can't notify window manager of window withdrawal");
12966 }
12967 #else /* ! defined (HAVE_X11R4) */
12968
12969 /* Tell the window manager what we're going to do. */
12970 if (! EQ (Vx_no_window_manager, Qt))
12971 {
12972 XEvent unmap;
12973
12974 unmap.xunmap.type = UnmapNotify;
12975 unmap.xunmap.window = window;
12976 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12977 unmap.xunmap.from_configure = False;
12978 if (! XSendEvent (FRAME_X_DISPLAY (f),
12979 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12980 False,
12981 SubstructureRedirectMaskSubstructureNotifyMask,
12982 &unmap))
12983 {
12984 UNBLOCK_INPUT_RESIGNAL;
12985 error ("Can't notify window manager of withdrawal");
12986 }
12987 }
12988
12989 /* Unmap the window ourselves. Cheeky! */
12990 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12991 #endif /* ! defined (HAVE_X11R4) */
12992
12993 /* We can't distinguish this from iconification
12994 just by the event that we get from the server.
12995 So we can't win using the usual strategy of letting
12996 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12997 and synchronize with the server to make sure we agree. */
12998 f->visible = 0;
12999 FRAME_ICONIFIED_P (f) = 0;
13000 f->async_visible = 0;
13001 f->async_iconified = 0;
13002
13003 x_sync (f);
13004
13005 UNBLOCK_INPUT;
13006 }
13007
13008 /* Change window state from mapped to iconified. */
13009
13010 void
13011 x_iconify_frame (f)
13012 struct frame *f;
13013 {
13014 int result;
13015 Lisp_Object type;
13016
13017 /* Don't keep the highlight on an invisible frame. */
13018 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13019 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13020
13021 if (f->async_iconified)
13022 return;
13023
13024 BLOCK_INPUT;
13025
13026 FRAME_SAMPLE_VISIBILITY (f);
13027
13028 type = x_icon_type (f);
13029 if (!NILP (type))
13030 x_bitmap_icon (f, type);
13031
13032 #ifdef USE_X_TOOLKIT
13033
13034 if (! FRAME_VISIBLE_P (f))
13035 {
13036 if (! EQ (Vx_no_window_manager, Qt))
13037 x_wm_set_window_state (f, IconicState);
13038 /* This was XtPopup, but that did nothing for an iconified frame. */
13039 XtMapWidget (f->output_data.x->widget);
13040 /* The server won't give us any event to indicate
13041 that an invisible frame was changed to an icon,
13042 so we have to record it here. */
13043 f->iconified = 1;
13044 f->visible = 1;
13045 f->async_iconified = 1;
13046 f->async_visible = 0;
13047 UNBLOCK_INPUT;
13048 return;
13049 }
13050
13051 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13052 XtWindow (f->output_data.x->widget),
13053 DefaultScreen (FRAME_X_DISPLAY (f)));
13054 UNBLOCK_INPUT;
13055
13056 if (!result)
13057 error ("Can't notify window manager of iconification");
13058
13059 f->async_iconified = 1;
13060 f->async_visible = 0;
13061
13062
13063 BLOCK_INPUT;
13064 XFlush (FRAME_X_DISPLAY (f));
13065 UNBLOCK_INPUT;
13066 #else /* not USE_X_TOOLKIT */
13067
13068 /* Make sure the X server knows where the window should be positioned,
13069 in case the user deiconifies with the window manager. */
13070 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13071 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13072
13073 /* Since we don't know which revision of X we're running, we'll use both
13074 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13075
13076 /* X11R4: send a ClientMessage to the window manager using the
13077 WM_CHANGE_STATE type. */
13078 {
13079 XEvent message;
13080
13081 message.xclient.window = FRAME_X_WINDOW (f);
13082 message.xclient.type = ClientMessage;
13083 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13084 message.xclient.format = 32;
13085 message.xclient.data.l[0] = IconicState;
13086
13087 if (! XSendEvent (FRAME_X_DISPLAY (f),
13088 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13089 False,
13090 SubstructureRedirectMask | SubstructureNotifyMask,
13091 &message))
13092 {
13093 UNBLOCK_INPUT_RESIGNAL;
13094 error ("Can't notify window manager of iconification");
13095 }
13096 }
13097
13098 /* X11R3: set the initial_state field of the window manager hints to
13099 IconicState. */
13100 x_wm_set_window_state (f, IconicState);
13101
13102 if (!FRAME_VISIBLE_P (f))
13103 {
13104 /* If the frame was withdrawn, before, we must map it. */
13105 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13106 }
13107
13108 f->async_iconified = 1;
13109 f->async_visible = 0;
13110
13111 XFlush (FRAME_X_DISPLAY (f));
13112 UNBLOCK_INPUT;
13113 #endif /* not USE_X_TOOLKIT */
13114 }
13115
13116 \f
13117 /* Free X resources of frame F. */
13118
13119 void
13120 x_free_frame_resources (f)
13121 struct frame *f;
13122 {
13123 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13124
13125 BLOCK_INPUT;
13126
13127 /* If a display connection is dead, don't try sending more
13128 commands to the X server. */
13129 if (dpyinfo->display)
13130 {
13131 if (f->output_data.x->icon_desc)
13132 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13133
13134 #ifdef HAVE_X_I18N
13135 if (FRAME_XIC (f))
13136 free_frame_xic (f);
13137 #endif
13138
13139 if (FRAME_X_WINDOW (f))
13140 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13141
13142 #ifdef USE_X_TOOLKIT
13143 if (f->output_data.x->widget)
13144 {
13145 XtDestroyWidget (f->output_data.x->widget);
13146 f->output_data.x->widget = NULL;
13147 }
13148 free_frame_menubar (f);
13149 #endif /* USE_X_TOOLKIT */
13150
13151 unload_color (f, f->output_data.x->foreground_pixel);
13152 unload_color (f, f->output_data.x->background_pixel);
13153 unload_color (f, f->output_data.x->cursor_pixel);
13154 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13155 unload_color (f, f->output_data.x->border_pixel);
13156 unload_color (f, f->output_data.x->mouse_pixel);
13157
13158 if (f->output_data.x->scroll_bar_background_pixel != -1)
13159 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13160 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13161 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13162 #ifdef USE_TOOLKIT_SCROLL_BARS
13163 /* Scrollbar shadow colors. */
13164 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13165 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13166 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13167 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13168 #endif /* USE_TOOLKIT_SCROLL_BARS */
13169 if (f->output_data.x->white_relief.allocated_p)
13170 unload_color (f, f->output_data.x->white_relief.pixel);
13171 if (f->output_data.x->black_relief.allocated_p)
13172 unload_color (f, f->output_data.x->black_relief.pixel);
13173
13174 if (FRAME_FACE_CACHE (f))
13175 free_frame_faces (f);
13176
13177 x_free_gcs (f);
13178 XFlush (FRAME_X_DISPLAY (f));
13179 }
13180
13181 if (f->output_data.x->saved_menu_event)
13182 xfree (f->output_data.x->saved_menu_event);
13183
13184 xfree (f->output_data.x);
13185 f->output_data.x = NULL;
13186
13187 if (f == dpyinfo->x_focus_frame)
13188 dpyinfo->x_focus_frame = 0;
13189 if (f == dpyinfo->x_focus_event_frame)
13190 dpyinfo->x_focus_event_frame = 0;
13191 if (f == dpyinfo->x_highlight_frame)
13192 dpyinfo->x_highlight_frame = 0;
13193
13194 if (f == dpyinfo->mouse_face_mouse_frame)
13195 {
13196 dpyinfo->mouse_face_beg_row
13197 = dpyinfo->mouse_face_beg_col = -1;
13198 dpyinfo->mouse_face_end_row
13199 = dpyinfo->mouse_face_end_col = -1;
13200 dpyinfo->mouse_face_window = Qnil;
13201 dpyinfo->mouse_face_deferred_gc = 0;
13202 dpyinfo->mouse_face_mouse_frame = 0;
13203 }
13204
13205 UNBLOCK_INPUT;
13206 }
13207
13208
13209 /* Destroy the X window of frame F. */
13210
13211 void
13212 x_destroy_window (f)
13213 struct frame *f;
13214 {
13215 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13216
13217 /* If a display connection is dead, don't try sending more
13218 commands to the X server. */
13219 if (dpyinfo->display != 0)
13220 x_free_frame_resources (f);
13221
13222 dpyinfo->reference_count--;
13223 }
13224
13225 \f
13226 /* Setting window manager hints. */
13227
13228 /* Set the normal size hints for the window manager, for frame F.
13229 FLAGS is the flags word to use--or 0 meaning preserve the flags
13230 that the window now has.
13231 If USER_POSITION is nonzero, we set the USPosition
13232 flag (this is useful when FLAGS is 0). */
13233
13234 void
13235 x_wm_set_size_hint (f, flags, user_position)
13236 struct frame *f;
13237 long flags;
13238 int user_position;
13239 {
13240 XSizeHints size_hints;
13241
13242 #ifdef USE_X_TOOLKIT
13243 Arg al[2];
13244 int ac = 0;
13245 Dimension widget_width, widget_height;
13246 Window window = XtWindow (f->output_data.x->widget);
13247 #else /* not USE_X_TOOLKIT */
13248 Window window = FRAME_X_WINDOW (f);
13249 #endif /* not USE_X_TOOLKIT */
13250
13251 /* Setting PMaxSize caused various problems. */
13252 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13253
13254 size_hints.x = f->output_data.x->left_pos;
13255 size_hints.y = f->output_data.x->top_pos;
13256
13257 #ifdef USE_X_TOOLKIT
13258 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13259 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13260 XtGetValues (f->output_data.x->widget, al, ac);
13261 size_hints.height = widget_height;
13262 size_hints.width = widget_width;
13263 #else /* not USE_X_TOOLKIT */
13264 size_hints.height = PIXEL_HEIGHT (f);
13265 size_hints.width = PIXEL_WIDTH (f);
13266 #endif /* not USE_X_TOOLKIT */
13267
13268 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13269 size_hints.height_inc = f->output_data.x->line_height;
13270 size_hints.max_width
13271 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13272 size_hints.max_height
13273 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13274
13275 /* Calculate the base and minimum sizes.
13276
13277 (When we use the X toolkit, we don't do it here.
13278 Instead we copy the values that the widgets are using, below.) */
13279 #ifndef USE_X_TOOLKIT
13280 {
13281 int base_width, base_height;
13282 int min_rows = 0, min_cols = 0;
13283
13284 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13285 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13286
13287 check_frame_size (f, &min_rows, &min_cols);
13288
13289 /* The window manager uses the base width hints to calculate the
13290 current number of rows and columns in the frame while
13291 resizing; min_width and min_height aren't useful for this
13292 purpose, since they might not give the dimensions for a
13293 zero-row, zero-column frame.
13294
13295 We use the base_width and base_height members if we have
13296 them; otherwise, we set the min_width and min_height members
13297 to the size for a zero x zero frame. */
13298
13299 #ifdef HAVE_X11R4
13300 size_hints.flags |= PBaseSize;
13301 size_hints.base_width = base_width;
13302 size_hints.base_height = base_height;
13303 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13304 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13305 #else
13306 size_hints.min_width = base_width;
13307 size_hints.min_height = base_height;
13308 #endif
13309 }
13310
13311 /* If we don't need the old flags, we don't need the old hint at all. */
13312 if (flags)
13313 {
13314 size_hints.flags |= flags;
13315 goto no_read;
13316 }
13317 #endif /* not USE_X_TOOLKIT */
13318
13319 {
13320 XSizeHints hints; /* Sometimes I hate X Windows... */
13321 long supplied_return;
13322 int value;
13323
13324 #ifdef HAVE_X11R4
13325 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13326 &supplied_return);
13327 #else
13328 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13329 #endif
13330
13331 #ifdef USE_X_TOOLKIT
13332 size_hints.base_height = hints.base_height;
13333 size_hints.base_width = hints.base_width;
13334 size_hints.min_height = hints.min_height;
13335 size_hints.min_width = hints.min_width;
13336 #endif
13337
13338 if (flags)
13339 size_hints.flags |= flags;
13340 else
13341 {
13342 if (value == 0)
13343 hints.flags = 0;
13344 if (hints.flags & PSize)
13345 size_hints.flags |= PSize;
13346 if (hints.flags & PPosition)
13347 size_hints.flags |= PPosition;
13348 if (hints.flags & USPosition)
13349 size_hints.flags |= USPosition;
13350 if (hints.flags & USSize)
13351 size_hints.flags |= USSize;
13352 }
13353 }
13354
13355 #ifndef USE_X_TOOLKIT
13356 no_read:
13357 #endif
13358
13359 #ifdef PWinGravity
13360 size_hints.win_gravity = f->output_data.x->win_gravity;
13361 size_hints.flags |= PWinGravity;
13362
13363 if (user_position)
13364 {
13365 size_hints.flags &= ~ PPosition;
13366 size_hints.flags |= USPosition;
13367 }
13368 #endif /* PWinGravity */
13369
13370 #ifdef HAVE_X11R4
13371 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13372 #else
13373 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13374 #endif
13375 }
13376
13377 /* Used for IconicState or NormalState */
13378
13379 void
13380 x_wm_set_window_state (f, state)
13381 struct frame *f;
13382 int state;
13383 {
13384 #ifdef USE_X_TOOLKIT
13385 Arg al[1];
13386
13387 XtSetArg (al[0], XtNinitialState, state);
13388 XtSetValues (f->output_data.x->widget, al, 1);
13389 #else /* not USE_X_TOOLKIT */
13390 Window window = FRAME_X_WINDOW (f);
13391
13392 f->output_data.x->wm_hints.flags |= StateHint;
13393 f->output_data.x->wm_hints.initial_state = state;
13394
13395 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13396 #endif /* not USE_X_TOOLKIT */
13397 }
13398
13399 void
13400 x_wm_set_icon_pixmap (f, pixmap_id)
13401 struct frame *f;
13402 int pixmap_id;
13403 {
13404 Pixmap icon_pixmap;
13405
13406 #ifndef USE_X_TOOLKIT
13407 Window window = FRAME_X_WINDOW (f);
13408 #endif
13409
13410 if (pixmap_id > 0)
13411 {
13412 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
13413 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
13414 }
13415 else
13416 {
13417 /* It seems there is no way to turn off use of an icon pixmap.
13418 The following line does it, only if no icon has yet been created,
13419 for some window managers. But with mwm it crashes.
13420 Some people say it should clear the IconPixmapHint bit in this case,
13421 but that doesn't work, and the X consortium said it isn't the
13422 right thing at all. Since there is no way to win,
13423 best to explicitly give up. */
13424 #if 0
13425 f->output_data.x->wm_hints.icon_pixmap = None;
13426 #else
13427 return;
13428 #endif
13429 }
13430
13431 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13432
13433 {
13434 Arg al[1];
13435 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13436 XtSetValues (f->output_data.x->widget, al, 1);
13437 }
13438
13439 #else /* not USE_X_TOOLKIT */
13440
13441 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13442 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13443
13444 #endif /* not USE_X_TOOLKIT */
13445 }
13446
13447 void
13448 x_wm_set_icon_position (f, icon_x, icon_y)
13449 struct frame *f;
13450 int icon_x, icon_y;
13451 {
13452 #ifdef USE_X_TOOLKIT
13453 Window window = XtWindow (f->output_data.x->widget);
13454 #else
13455 Window window = FRAME_X_WINDOW (f);
13456 #endif
13457
13458 f->output_data.x->wm_hints.flags |= IconPositionHint;
13459 f->output_data.x->wm_hints.icon_x = icon_x;
13460 f->output_data.x->wm_hints.icon_y = icon_y;
13461
13462 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13463 }
13464
13465 \f
13466 /***********************************************************************
13467 Fonts
13468 ***********************************************************************/
13469
13470 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
13471
13472 struct font_info *
13473 x_get_font_info (f, font_idx)
13474 FRAME_PTR f;
13475 int font_idx;
13476 {
13477 return (FRAME_X_FONT_TABLE (f) + font_idx);
13478 }
13479
13480
13481 /* Return a list of names of available fonts matching PATTERN on frame F.
13482
13483 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13484 to be listed.
13485
13486 SIZE < 0 means include scalable fonts.
13487
13488 Frame F null means we have not yet created any frame on X, and
13489 consult the first display in x_display_list. MAXNAMES sets a limit
13490 on how many fonts to match. */
13491
13492 Lisp_Object
13493 x_list_fonts (f, pattern, size, maxnames)
13494 struct frame *f;
13495 Lisp_Object pattern;
13496 int size;
13497 int maxnames;
13498 {
13499 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13500 Lisp_Object tem, second_best;
13501 struct x_display_info *dpyinfo
13502 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13503 Display *dpy = dpyinfo->display;
13504 int try_XLoadQueryFont = 0;
13505 int count;
13506 int allow_scalable_fonts_p = 0;
13507
13508 if (size < 0)
13509 {
13510 allow_scalable_fonts_p = 1;
13511 size = 0;
13512 }
13513
13514 patterns = Fassoc (pattern, Valternate_fontname_alist);
13515 if (NILP (patterns))
13516 patterns = Fcons (pattern, Qnil);
13517
13518 if (maxnames == 1 && !size)
13519 /* We can return any single font matching PATTERN. */
13520 try_XLoadQueryFont = 1;
13521
13522 for (; CONSP (patterns); patterns = XCDR (patterns))
13523 {
13524 int num_fonts;
13525 char **names = NULL;
13526
13527 pattern = XCAR (patterns);
13528 /* See if we cached the result for this particular query.
13529 The cache is an alist of the form:
13530 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13531 tem = XCDR (dpyinfo->name_list_element);
13532 key = Fcons (Fcons (pattern, make_number (maxnames)),
13533 allow_scalable_fonts_p ? Qt : Qnil);
13534 list = Fassoc (key, tem);
13535 if (!NILP (list))
13536 {
13537 list = Fcdr_safe (list);
13538 /* We have a cashed list. Don't have to get the list again. */
13539 goto label_cached;
13540 }
13541
13542 /* At first, put PATTERN in the cache. */
13543
13544 BLOCK_INPUT;
13545 count = x_catch_errors (dpy);
13546
13547 if (try_XLoadQueryFont)
13548 {
13549 XFontStruct *font;
13550 unsigned long value;
13551
13552 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
13553 if (x_had_errors_p (dpy))
13554 {
13555 /* This error is perhaps due to insufficient memory on X
13556 server. Let's just ignore it. */
13557 font = NULL;
13558 x_clear_errors (dpy);
13559 }
13560
13561 if (font
13562 && XGetFontProperty (font, XA_FONT, &value))
13563 {
13564 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13565 int len = strlen (name);
13566 char *tmp;
13567
13568 /* If DXPC (a Differential X Protocol Compressor)
13569 Ver.3.7 is running, XGetAtomName will return null
13570 string. We must avoid such a name. */
13571 if (len == 0)
13572 try_XLoadQueryFont = 0;
13573 else
13574 {
13575 num_fonts = 1;
13576 names = (char **) alloca (sizeof (char *));
13577 /* Some systems only allow alloca assigned to a
13578 simple var. */
13579 tmp = (char *) alloca (len + 1); names[0] = tmp;
13580 bcopy (name, names[0], len + 1);
13581 XFree (name);
13582 }
13583 }
13584 else
13585 try_XLoadQueryFont = 0;
13586
13587 if (font)
13588 XFreeFont (dpy, font);
13589 }
13590
13591 if (!try_XLoadQueryFont)
13592 {
13593 /* We try at least 10 fonts because XListFonts will return
13594 auto-scaled fonts at the head. */
13595 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13596 &num_fonts);
13597 if (x_had_errors_p (dpy))
13598 {
13599 /* This error is perhaps due to insufficient memory on X
13600 server. Let's just ignore it. */
13601 names = NULL;
13602 x_clear_errors (dpy);
13603 }
13604 }
13605
13606 x_uncatch_errors (dpy, count);
13607 UNBLOCK_INPUT;
13608
13609 if (names)
13610 {
13611 int i;
13612
13613 /* Make a list of all the fonts we got back.
13614 Store that in the font cache for the display. */
13615 for (i = 0; i < num_fonts; i++)
13616 {
13617 int width = 0;
13618 char *p = names[i];
13619 int average_width = -1, dashes = 0;
13620
13621 /* Count the number of dashes in NAMES[I]. If there are
13622 14 dashes, and the field value following 12th dash
13623 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13624 is usually too ugly to be used for editing. Let's
13625 ignore it. */
13626 while (*p)
13627 if (*p++ == '-')
13628 {
13629 dashes++;
13630 if (dashes == 7) /* PIXEL_SIZE field */
13631 width = atoi (p);
13632 else if (dashes == 12) /* AVERAGE_WIDTH field */
13633 average_width = atoi (p);
13634 }
13635
13636 if (allow_scalable_fonts_p
13637 || dashes < 14 || average_width != 0)
13638 {
13639 tem = build_string (names[i]);
13640 if (NILP (Fassoc (tem, list)))
13641 {
13642 if (STRINGP (Vx_pixel_size_width_font_regexp)
13643 && ((fast_c_string_match_ignore_case
13644 (Vx_pixel_size_width_font_regexp, names[i]))
13645 >= 0))
13646 /* We can set the value of PIXEL_SIZE to the
13647 width of this font. */
13648 list = Fcons (Fcons (tem, make_number (width)), list);
13649 else
13650 /* For the moment, width is not known. */
13651 list = Fcons (Fcons (tem, Qnil), list);
13652 }
13653 }
13654 }
13655
13656 if (!try_XLoadQueryFont)
13657 {
13658 BLOCK_INPUT;
13659 XFreeFontNames (names);
13660 UNBLOCK_INPUT;
13661 }
13662 }
13663
13664 /* Now store the result in the cache. */
13665 XSETCDR (dpyinfo->name_list_element,
13666 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
13667
13668 label_cached:
13669 if (NILP (list)) continue; /* Try the remaining alternatives. */
13670
13671 newlist = second_best = Qnil;
13672 /* Make a list of the fonts that have the right width. */
13673 for (; CONSP (list); list = XCDR (list))
13674 {
13675 int found_size;
13676
13677 tem = XCAR (list);
13678
13679 if (!CONSP (tem) || NILP (XCAR (tem)))
13680 continue;
13681 if (!size)
13682 {
13683 newlist = Fcons (XCAR (tem), newlist);
13684 continue;
13685 }
13686
13687 if (!INTEGERP (XCDR (tem)))
13688 {
13689 /* Since we have not yet known the size of this font, we
13690 must try slow function call XLoadQueryFont. */
13691 XFontStruct *thisinfo;
13692
13693 BLOCK_INPUT;
13694 count = x_catch_errors (dpy);
13695 thisinfo = XLoadQueryFont (dpy,
13696 XSTRING (XCAR (tem))->data);
13697 if (x_had_errors_p (dpy))
13698 {
13699 /* This error is perhaps due to insufficient memory on X
13700 server. Let's just ignore it. */
13701 thisinfo = NULL;
13702 x_clear_errors (dpy);
13703 }
13704 x_uncatch_errors (dpy, count);
13705 UNBLOCK_INPUT;
13706
13707 if (thisinfo)
13708 {
13709 XSETCDR (tem,
13710 (thisinfo->min_bounds.width == 0
13711 ? make_number (0)
13712 : make_number (thisinfo->max_bounds.width)));
13713 BLOCK_INPUT;
13714 XFreeFont (dpy, thisinfo);
13715 UNBLOCK_INPUT;
13716 }
13717 else
13718 /* For unknown reason, the previous call of XListFont had
13719 returned a font which can't be opened. Record the size
13720 as 0 not to try to open it again. */
13721 XSETCDR (tem, make_number (0));
13722 }
13723
13724 found_size = XINT (XCDR (tem));
13725 if (found_size == size)
13726 newlist = Fcons (XCAR (tem), newlist);
13727 else if (found_size > 0)
13728 {
13729 if (NILP (second_best))
13730 second_best = tem;
13731 else if (found_size < size)
13732 {
13733 if (XINT (XCDR (second_best)) > size
13734 || XINT (XCDR (second_best)) < found_size)
13735 second_best = tem;
13736 }
13737 else
13738 {
13739 if (XINT (XCDR (second_best)) > size
13740 && XINT (XCDR (second_best)) > found_size)
13741 second_best = tem;
13742 }
13743 }
13744 }
13745 if (!NILP (newlist))
13746 break;
13747 else if (!NILP (second_best))
13748 {
13749 newlist = Fcons (XCAR (second_best), Qnil);
13750 break;
13751 }
13752 }
13753
13754 return newlist;
13755 }
13756
13757
13758 #if GLYPH_DEBUG
13759
13760 /* Check that FONT is valid on frame F. It is if it can be found in F's
13761 font table. */
13762
13763 static void
13764 x_check_font (f, font)
13765 struct frame *f;
13766 XFontStruct *font;
13767 {
13768 int i;
13769 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13770
13771 xassert (font != NULL);
13772
13773 for (i = 0; i < dpyinfo->n_fonts; i++)
13774 if (dpyinfo->font_table[i].name
13775 && font == dpyinfo->font_table[i].font)
13776 break;
13777
13778 xassert (i < dpyinfo->n_fonts);
13779 }
13780
13781 #endif /* GLYPH_DEBUG != 0 */
13782
13783 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13784 Note: There are (broken) X fonts out there with invalid XFontStruct
13785 min_bounds contents. For example, handa@etl.go.jp reports that
13786 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13787 have font->min_bounds.width == 0. */
13788
13789 static INLINE void
13790 x_font_min_bounds (font, w, h)
13791 XFontStruct *font;
13792 int *w, *h;
13793 {
13794 *h = FONT_HEIGHT (font);
13795 *w = font->min_bounds.width;
13796
13797 /* Try to handle the case where FONT->min_bounds has invalid
13798 contents. Since the only font known to have invalid min_bounds
13799 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13800 if (*w <= 0)
13801 *w = font->max_bounds.width;
13802 }
13803
13804
13805 /* Compute the smallest character width and smallest font height over
13806 all fonts available on frame F. Set the members smallest_char_width
13807 and smallest_font_height in F's x_display_info structure to
13808 the values computed. Value is non-zero if smallest_font_height or
13809 smallest_char_width become smaller than they were before. */
13810
13811 static int
13812 x_compute_min_glyph_bounds (f)
13813 struct frame *f;
13814 {
13815 int i;
13816 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13817 XFontStruct *font;
13818 int old_width = dpyinfo->smallest_char_width;
13819 int old_height = dpyinfo->smallest_font_height;
13820
13821 dpyinfo->smallest_font_height = 100000;
13822 dpyinfo->smallest_char_width = 100000;
13823
13824 for (i = 0; i < dpyinfo->n_fonts; ++i)
13825 if (dpyinfo->font_table[i].name)
13826 {
13827 struct font_info *fontp = dpyinfo->font_table + i;
13828 int w, h;
13829
13830 font = (XFontStruct *) fontp->font;
13831 xassert (font != (XFontStruct *) ~0);
13832 x_font_min_bounds (font, &w, &h);
13833
13834 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13835 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13836 }
13837
13838 xassert (dpyinfo->smallest_char_width > 0
13839 && dpyinfo->smallest_font_height > 0);
13840
13841 return (dpyinfo->n_fonts == 1
13842 || dpyinfo->smallest_char_width < old_width
13843 || dpyinfo->smallest_font_height < old_height);
13844 }
13845
13846
13847 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13848 pointer to the structure font_info while allocating it dynamically.
13849 If SIZE is 0, load any size of font.
13850 If loading is failed, return NULL. */
13851
13852 struct font_info *
13853 x_load_font (f, fontname, size)
13854 struct frame *f;
13855 register char *fontname;
13856 int size;
13857 {
13858 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13859 Lisp_Object font_names;
13860 int count;
13861
13862 /* Get a list of all the fonts that match this name. Once we
13863 have a list of matching fonts, we compare them against the fonts
13864 we already have by comparing names. */
13865 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13866
13867 if (!NILP (font_names))
13868 {
13869 Lisp_Object tail;
13870 int i;
13871
13872 for (i = 0; i < dpyinfo->n_fonts; i++)
13873 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13874 if (dpyinfo->font_table[i].name
13875 && (!strcmp (dpyinfo->font_table[i].name,
13876 XSTRING (XCAR (tail))->data)
13877 || !strcmp (dpyinfo->font_table[i].full_name,
13878 XSTRING (XCAR (tail))->data)))
13879 return (dpyinfo->font_table + i);
13880 }
13881
13882 /* Load the font and add it to the table. */
13883 {
13884 char *full_name;
13885 XFontStruct *font;
13886 struct font_info *fontp;
13887 unsigned long value;
13888 int i;
13889
13890 /* If we have found fonts by x_list_font, load one of them. If
13891 not, we still try to load a font by the name given as FONTNAME
13892 because XListFonts (called in x_list_font) of some X server has
13893 a bug of not finding a font even if the font surely exists and
13894 is loadable by XLoadQueryFont. */
13895 if (size > 0 && !NILP (font_names))
13896 fontname = (char *) XSTRING (XCAR (font_names))->data;
13897
13898 BLOCK_INPUT;
13899 count = x_catch_errors (FRAME_X_DISPLAY (f));
13900 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13901 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13902 {
13903 /* This error is perhaps due to insufficient memory on X
13904 server. Let's just ignore it. */
13905 font = NULL;
13906 x_clear_errors (FRAME_X_DISPLAY (f));
13907 }
13908 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13909 UNBLOCK_INPUT;
13910 if (!font)
13911 return NULL;
13912
13913 /* Find a free slot in the font table. */
13914 for (i = 0; i < dpyinfo->n_fonts; ++i)
13915 if (dpyinfo->font_table[i].name == NULL)
13916 break;
13917
13918 /* If no free slot found, maybe enlarge the font table. */
13919 if (i == dpyinfo->n_fonts
13920 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13921 {
13922 int sz;
13923 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13924 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13925 dpyinfo->font_table
13926 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13927 }
13928
13929 fontp = dpyinfo->font_table + i;
13930 if (i == dpyinfo->n_fonts)
13931 ++dpyinfo->n_fonts;
13932
13933 /* Now fill in the slots of *FONTP. */
13934 BLOCK_INPUT;
13935 fontp->font = font;
13936 fontp->font_idx = i;
13937 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13938 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13939
13940 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13941 full_name = 0;
13942 if (XGetFontProperty (font, XA_FONT, &value))
13943 {
13944 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13945 char *p = name;
13946 int dashes = 0;
13947
13948 /* Count the number of dashes in the "full name".
13949 If it is too few, this isn't really the font's full name,
13950 so don't use it.
13951 In X11R4, the fonts did not come with their canonical names
13952 stored in them. */
13953 while (*p)
13954 {
13955 if (*p == '-')
13956 dashes++;
13957 p++;
13958 }
13959
13960 if (dashes >= 13)
13961 {
13962 full_name = (char *) xmalloc (p - name + 1);
13963 bcopy (name, full_name, p - name + 1);
13964 }
13965
13966 XFree (name);
13967 }
13968
13969 if (full_name != 0)
13970 fontp->full_name = full_name;
13971 else
13972 fontp->full_name = fontp->name;
13973
13974 fontp->size = font->max_bounds.width;
13975 fontp->height = FONT_HEIGHT (font);
13976
13977 if (NILP (font_names))
13978 {
13979 /* We come here because of a bug of XListFonts mentioned at
13980 the head of this block. Let's store this information in
13981 the cache for x_list_fonts. */
13982 Lisp_Object lispy_name = build_string (fontname);
13983 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13984 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13985 Qnil);
13986
13987 XSETCDR (dpyinfo->name_list_element,
13988 Fcons (Fcons (key,
13989 Fcons (Fcons (lispy_full_name,
13990 make_number (fontp->size)),
13991 Qnil)),
13992 XCDR (dpyinfo->name_list_element)));
13993 if (full_name)
13994 {
13995 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13996 Qnil);
13997 XSETCDR (dpyinfo->name_list_element,
13998 Fcons (Fcons (key,
13999 Fcons (Fcons (lispy_full_name,
14000 make_number (fontp->size)),
14001 Qnil)),
14002 XCDR (dpyinfo->name_list_element)));
14003 }
14004 }
14005
14006 /* The slot `encoding' specifies how to map a character
14007 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14008 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14009 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14010 2:0xA020..0xFF7F). For the moment, we don't know which charset
14011 uses this font. So, we set information in fontp->encoding[1]
14012 which is never used by any charset. If mapping can't be
14013 decided, set FONT_ENCODING_NOT_DECIDED. */
14014 fontp->encoding[1]
14015 = (font->max_byte1 == 0
14016 /* 1-byte font */
14017 ? (font->min_char_or_byte2 < 0x80
14018 ? (font->max_char_or_byte2 < 0x80
14019 ? 0 /* 0x20..0x7F */
14020 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14021 : 1) /* 0xA0..0xFF */
14022 /* 2-byte font */
14023 : (font->min_byte1 < 0x80
14024 ? (font->max_byte1 < 0x80
14025 ? (font->min_char_or_byte2 < 0x80
14026 ? (font->max_char_or_byte2 < 0x80
14027 ? 0 /* 0x2020..0x7F7F */
14028 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14029 : 3) /* 0x20A0..0x7FFF */
14030 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14031 : (font->min_char_or_byte2 < 0x80
14032 ? (font->max_char_or_byte2 < 0x80
14033 ? 2 /* 0xA020..0xFF7F */
14034 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14035 : 1))); /* 0xA0A0..0xFFFF */
14036
14037 fontp->baseline_offset
14038 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14039 ? (long) value : 0);
14040 fontp->relative_compose
14041 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14042 ? (long) value : 0);
14043 fontp->default_ascent
14044 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14045 ? (long) value : 0);
14046
14047 /* Set global flag fonts_changed_p to non-zero if the font loaded
14048 has a character with a smaller width than any other character
14049 before, or if the font loaded has a smalle>r height than any
14050 other font loaded before. If this happens, it will make a
14051 glyph matrix reallocation necessary. */
14052 fonts_changed_p = x_compute_min_glyph_bounds (f);
14053 UNBLOCK_INPUT;
14054 return fontp;
14055 }
14056 }
14057
14058
14059 /* Return a pointer to struct font_info of a font named FONTNAME for
14060 frame F. If no such font is loaded, return NULL. */
14061
14062 struct font_info *
14063 x_query_font (f, fontname)
14064 struct frame *f;
14065 register char *fontname;
14066 {
14067 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14068 int i;
14069
14070 for (i = 0; i < dpyinfo->n_fonts; i++)
14071 if (dpyinfo->font_table[i].name
14072 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14073 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14074 return (dpyinfo->font_table + i);
14075 return NULL;
14076 }
14077
14078
14079 /* Find a CCL program for a font specified by FONTP, and set the member
14080 `encoder' of the structure. */
14081
14082 void
14083 x_find_ccl_program (fontp)
14084 struct font_info *fontp;
14085 {
14086 Lisp_Object list, elt;
14087
14088 elt = Qnil;
14089 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14090 {
14091 elt = XCAR (list);
14092 if (CONSP (elt)
14093 && STRINGP (XCAR (elt))
14094 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14095 >= 0)
14096 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14097 >= 0)))
14098 break;
14099 }
14100
14101 if (! NILP (list))
14102 {
14103 struct ccl_program *ccl
14104 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14105
14106 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14107 xfree (ccl);
14108 else
14109 fontp->font_encoder = ccl;
14110 }
14111 }
14112
14113
14114 \f
14115 /***********************************************************************
14116 Initialization
14117 ***********************************************************************/
14118
14119 #ifdef USE_X_TOOLKIT
14120 static XrmOptionDescRec emacs_options[] = {
14121 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14122 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14123
14124 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14125 XrmoptionSepArg, NULL},
14126 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14127
14128 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14129 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14130 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14131 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14132 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14133 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14134 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14135 };
14136 #endif /* USE_X_TOOLKIT */
14137
14138 static int x_initialized;
14139
14140 #ifdef MULTI_KBOARD
14141 /* Test whether two display-name strings agree up to the dot that separates
14142 the screen number from the server number. */
14143 static int
14144 same_x_server (name1, name2)
14145 char *name1, *name2;
14146 {
14147 int seen_colon = 0;
14148 unsigned char *system_name = XSTRING (Vsystem_name)->data;
14149 int system_name_length = strlen (system_name);
14150 int length_until_period = 0;
14151
14152 while (system_name[length_until_period] != 0
14153 && system_name[length_until_period] != '.')
14154 length_until_period++;
14155
14156 /* Treat `unix' like an empty host name. */
14157 if (! strncmp (name1, "unix:", 5))
14158 name1 += 4;
14159 if (! strncmp (name2, "unix:", 5))
14160 name2 += 4;
14161 /* Treat this host's name like an empty host name. */
14162 if (! strncmp (name1, system_name, system_name_length)
14163 && name1[system_name_length] == ':')
14164 name1 += system_name_length;
14165 if (! strncmp (name2, system_name, system_name_length)
14166 && name2[system_name_length] == ':')
14167 name2 += system_name_length;
14168 /* Treat this host's domainless name like an empty host name. */
14169 if (! strncmp (name1, system_name, length_until_period)
14170 && name1[length_until_period] == ':')
14171 name1 += length_until_period;
14172 if (! strncmp (name2, system_name, length_until_period)
14173 && name2[length_until_period] == ':')
14174 name2 += length_until_period;
14175
14176 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14177 {
14178 if (*name1 == ':')
14179 seen_colon++;
14180 if (seen_colon && *name1 == '.')
14181 return 1;
14182 }
14183 return (seen_colon
14184 && (*name1 == '.' || *name1 == '\0')
14185 && (*name2 == '.' || *name2 == '\0'));
14186 }
14187 #endif
14188
14189 struct x_display_info *
14190 x_term_init (display_name, xrm_option, resource_name)
14191 Lisp_Object display_name;
14192 char *xrm_option;
14193 char *resource_name;
14194 {
14195 int connection;
14196 Display *dpy;
14197 struct x_display_info *dpyinfo;
14198 XrmDatabase xrdb;
14199
14200 BLOCK_INPUT;
14201
14202 if (!x_initialized)
14203 {
14204 x_initialize ();
14205 x_initialized = 1;
14206 }
14207
14208 #ifdef USE_X_TOOLKIT
14209 /* weiner@footloose.sps.mot.com reports that this causes
14210 errors with X11R5:
14211 X protocol error: BadAtom (invalid Atom parameter)
14212 on protocol request 18skiloaf.
14213 So let's not use it until R6. */
14214 #ifdef HAVE_X11XTR6
14215 XtSetLanguageProc (NULL, NULL, NULL);
14216 #endif
14217
14218 {
14219 int argc = 0;
14220 char *argv[3];
14221
14222 argv[0] = "";
14223 argc = 1;
14224 if (xrm_option)
14225 {
14226 argv[argc++] = "-xrm";
14227 argv[argc++] = xrm_option;
14228 }
14229 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
14230 resource_name, EMACS_CLASS,
14231 emacs_options, XtNumber (emacs_options),
14232 &argc, argv);
14233
14234 #ifdef HAVE_X11XTR6
14235 /* I think this is to compensate for XtSetLanguageProc. */
14236 fixup_locale ();
14237 #endif
14238 }
14239
14240 #else /* not USE_X_TOOLKIT */
14241 #ifdef HAVE_X11R5
14242 XSetLocaleModifiers ("");
14243 #endif
14244 dpy = XOpenDisplay (XSTRING (display_name)->data);
14245 #endif /* not USE_X_TOOLKIT */
14246
14247 /* Detect failure. */
14248 if (dpy == 0)
14249 {
14250 UNBLOCK_INPUT;
14251 return 0;
14252 }
14253
14254 /* We have definitely succeeded. Record the new connection. */
14255
14256 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14257 bzero (dpyinfo, sizeof *dpyinfo);
14258
14259 #ifdef MULTI_KBOARD
14260 {
14261 struct x_display_info *share;
14262 Lisp_Object tail;
14263
14264 for (share = x_display_list, tail = x_display_name_list; share;
14265 share = share->next, tail = XCDR (tail))
14266 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
14267 XSTRING (display_name)->data))
14268 break;
14269 if (share)
14270 dpyinfo->kboard = share->kboard;
14271 else
14272 {
14273 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14274 init_kboard (dpyinfo->kboard);
14275 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14276 {
14277 char *vendor = ServerVendor (dpy);
14278 UNBLOCK_INPUT;
14279 dpyinfo->kboard->Vsystem_key_alist
14280 = call1 (Qvendor_specific_keysyms,
14281 build_string (vendor ? vendor : ""));
14282 BLOCK_INPUT;
14283 }
14284
14285 dpyinfo->kboard->next_kboard = all_kboards;
14286 all_kboards = dpyinfo->kboard;
14287 /* Don't let the initial kboard remain current longer than necessary.
14288 That would cause problems if a file loaded on startup tries to
14289 prompt in the mini-buffer. */
14290 if (current_kboard == initial_kboard)
14291 current_kboard = dpyinfo->kboard;
14292 }
14293 dpyinfo->kboard->reference_count++;
14294 }
14295 #endif
14296
14297 /* Put this display on the chain. */
14298 dpyinfo->next = x_display_list;
14299 x_display_list = dpyinfo;
14300
14301 /* Put it on x_display_name_list as well, to keep them parallel. */
14302 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14303 x_display_name_list);
14304 dpyinfo->name_list_element = XCAR (x_display_name_list);
14305
14306 dpyinfo->display = dpy;
14307
14308 #if 0
14309 XSetAfterFunction (x_current_display, x_trace_wire);
14310 #endif /* ! 0 */
14311
14312 dpyinfo->x_id_name
14313 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
14314 + STRING_BYTES (XSTRING (Vsystem_name))
14315 + 2);
14316 sprintf (dpyinfo->x_id_name, "%s@%s",
14317 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
14318
14319 /* Figure out which modifier bits mean what. */
14320 x_find_modifier_meanings (dpyinfo);
14321
14322 /* Get the scroll bar cursor. */
14323 dpyinfo->vertical_scroll_bar_cursor
14324 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14325
14326 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14327 resource_name, EMACS_CLASS);
14328 #ifdef HAVE_XRMSETDATABASE
14329 XrmSetDatabase (dpyinfo->display, xrdb);
14330 #else
14331 dpyinfo->display->db = xrdb;
14332 #endif
14333 /* Put the rdb where we can find it in a way that works on
14334 all versions. */
14335 dpyinfo->xrdb = xrdb;
14336
14337 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14338 DefaultScreen (dpyinfo->display));
14339 select_visual (dpyinfo);
14340 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14341 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14342 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14343 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14344 dpyinfo->grabbed = 0;
14345 dpyinfo->reference_count = 0;
14346 dpyinfo->icon_bitmap_id = -1;
14347 dpyinfo->font_table = NULL;
14348 dpyinfo->n_fonts = 0;
14349 dpyinfo->font_table_size = 0;
14350 dpyinfo->bitmaps = 0;
14351 dpyinfo->bitmaps_size = 0;
14352 dpyinfo->bitmaps_last = 0;
14353 dpyinfo->scratch_cursor_gc = 0;
14354 dpyinfo->mouse_face_mouse_frame = 0;
14355 dpyinfo->mouse_face_deferred_gc = 0;
14356 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14357 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14358 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14359 dpyinfo->mouse_face_window = Qnil;
14360 dpyinfo->mouse_face_overlay = Qnil;
14361 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14362 dpyinfo->mouse_face_defer = 0;
14363 dpyinfo->x_focus_frame = 0;
14364 dpyinfo->x_focus_event_frame = 0;
14365 dpyinfo->x_highlight_frame = 0;
14366 dpyinfo->image_cache = make_image_cache ();
14367
14368 /* See if a private colormap is requested. */
14369 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14370 {
14371 if (dpyinfo->visual->class == PseudoColor)
14372 {
14373 Lisp_Object value;
14374 value = display_x_get_resource (dpyinfo,
14375 build_string ("privateColormap"),
14376 build_string ("PrivateColormap"),
14377 Qnil, Qnil);
14378 if (STRINGP (value)
14379 && (!strcmp (XSTRING (value)->data, "true")
14380 || !strcmp (XSTRING (value)->data, "on")))
14381 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14382 }
14383 }
14384 else
14385 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14386 dpyinfo->visual, AllocNone);
14387
14388 {
14389 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14390 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14391 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14392 dpyinfo->resy = pixels * 25.4 / mm;
14393 pixels = DisplayWidth (dpyinfo->display, screen_number);
14394 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14395 dpyinfo->resx = pixels * 25.4 / mm;
14396 }
14397
14398 dpyinfo->Xatom_wm_protocols
14399 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14400 dpyinfo->Xatom_wm_take_focus
14401 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14402 dpyinfo->Xatom_wm_save_yourself
14403 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14404 dpyinfo->Xatom_wm_delete_window
14405 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14406 dpyinfo->Xatom_wm_change_state
14407 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14408 dpyinfo->Xatom_wm_configure_denied
14409 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14410 dpyinfo->Xatom_wm_window_moved
14411 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14412 dpyinfo->Xatom_editres
14413 = XInternAtom (dpyinfo->display, "Editres", False);
14414 dpyinfo->Xatom_CLIPBOARD
14415 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14416 dpyinfo->Xatom_TIMESTAMP
14417 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14418 dpyinfo->Xatom_TEXT
14419 = XInternAtom (dpyinfo->display, "TEXT", False);
14420 dpyinfo->Xatom_COMPOUND_TEXT
14421 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
14422 dpyinfo->Xatom_DELETE
14423 = XInternAtom (dpyinfo->display, "DELETE", False);
14424 dpyinfo->Xatom_MULTIPLE
14425 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14426 dpyinfo->Xatom_INCR
14427 = XInternAtom (dpyinfo->display, "INCR", False);
14428 dpyinfo->Xatom_EMACS_TMP
14429 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14430 dpyinfo->Xatom_TARGETS
14431 = XInternAtom (dpyinfo->display, "TARGETS", False);
14432 dpyinfo->Xatom_NULL
14433 = XInternAtom (dpyinfo->display, "NULL", False);
14434 dpyinfo->Xatom_ATOM_PAIR
14435 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
14436 /* For properties of font. */
14437 dpyinfo->Xatom_PIXEL_SIZE
14438 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14439 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14440 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14441 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14442 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
14443 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14444 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
14445
14446 /* Ghostscript support. */
14447 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14448 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14449
14450 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14451 False);
14452
14453 dpyinfo->cut_buffers_initialized = 0;
14454
14455 connection = ConnectionNumber (dpyinfo->display);
14456 dpyinfo->connection = connection;
14457
14458 {
14459 char null_bits[1];
14460
14461 null_bits[0] = 0x00;
14462
14463 dpyinfo->null_pixel
14464 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14465 null_bits, 1, 1, (long) 0, (long) 0,
14466 1);
14467 }
14468
14469 {
14470 extern int gray_bitmap_width, gray_bitmap_height;
14471 extern char *gray_bitmap_bits;
14472 dpyinfo->gray
14473 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14474 gray_bitmap_bits,
14475 gray_bitmap_width, gray_bitmap_height,
14476 (unsigned long) 1, (unsigned long) 0, 1);
14477 }
14478
14479 #ifdef HAVE_X_I18N
14480 xim_initialize (dpyinfo, resource_name);
14481 #endif
14482
14483 #ifdef subprocesses
14484 /* This is only needed for distinguishing keyboard and process input. */
14485 if (connection != 0)
14486 add_keyboard_wait_descriptor (connection);
14487 #endif
14488
14489 #ifndef F_SETOWN_BUG
14490 #ifdef F_SETOWN
14491 #ifdef F_SETOWN_SOCK_NEG
14492 /* stdin is a socket here */
14493 fcntl (connection, F_SETOWN, -getpid ());
14494 #else /* ! defined (F_SETOWN_SOCK_NEG) */
14495 fcntl (connection, F_SETOWN, getpid ());
14496 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
14497 #endif /* ! defined (F_SETOWN) */
14498 #endif /* F_SETOWN_BUG */
14499
14500 #ifdef SIGIO
14501 if (interrupt_input)
14502 init_sigio (connection);
14503 #endif /* ! defined (SIGIO) */
14504
14505 #ifdef USE_LUCID
14506 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
14507 /* Make sure that we have a valid font for dialog boxes
14508 so that Xt does not crash. */
14509 {
14510 Display *dpy = dpyinfo->display;
14511 XrmValue d, fr, to;
14512 Font font;
14513 int count;
14514
14515 d.addr = (XPointer)&dpy;
14516 d.size = sizeof (Display *);
14517 fr.addr = XtDefaultFont;
14518 fr.size = sizeof (XtDefaultFont);
14519 to.size = sizeof (Font *);
14520 to.addr = (XPointer)&font;
14521 count = x_catch_errors (dpy);
14522 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14523 abort ();
14524 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14525 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
14526 x_uncatch_errors (dpy, count);
14527 }
14528 #endif
14529 #endif
14530
14531 /* See if we should run in synchronous mode. This is useful
14532 for debugging X code. */
14533 {
14534 Lisp_Object value;
14535 value = display_x_get_resource (dpyinfo,
14536 build_string ("synchronous"),
14537 build_string ("Synchronous"),
14538 Qnil, Qnil);
14539 if (STRINGP (value)
14540 && (!strcmp (XSTRING (value)->data, "true")
14541 || !strcmp (XSTRING (value)->data, "on")))
14542 XSynchronize (dpyinfo->display, True);
14543 }
14544
14545 UNBLOCK_INPUT;
14546
14547 return dpyinfo;
14548 }
14549 \f
14550 /* Get rid of display DPYINFO, assuming all frames are already gone,
14551 and without sending any more commands to the X server. */
14552
14553 void
14554 x_delete_display (dpyinfo)
14555 struct x_display_info *dpyinfo;
14556 {
14557 delete_keyboard_wait_descriptor (dpyinfo->connection);
14558
14559 /* Discard this display from x_display_name_list and x_display_list.
14560 We can't use Fdelq because that can quit. */
14561 if (! NILP (x_display_name_list)
14562 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14563 x_display_name_list = XCDR (x_display_name_list);
14564 else
14565 {
14566 Lisp_Object tail;
14567
14568 tail = x_display_name_list;
14569 while (CONSP (tail) && CONSP (XCDR (tail)))
14570 {
14571 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
14572 {
14573 XSETCDR (tail, XCDR (XCDR (tail)));
14574 break;
14575 }
14576 tail = XCDR (tail);
14577 }
14578 }
14579
14580 if (next_noop_dpyinfo == dpyinfo)
14581 next_noop_dpyinfo = dpyinfo->next;
14582
14583 if (x_display_list == dpyinfo)
14584 x_display_list = dpyinfo->next;
14585 else
14586 {
14587 struct x_display_info *tail;
14588
14589 for (tail = x_display_list; tail; tail = tail->next)
14590 if (tail->next == dpyinfo)
14591 tail->next = tail->next->next;
14592 }
14593
14594 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14595 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
14596 XrmDestroyDatabase (dpyinfo->xrdb);
14597 #endif
14598 #endif
14599 #ifdef MULTI_KBOARD
14600 if (--dpyinfo->kboard->reference_count == 0)
14601 delete_kboard (dpyinfo->kboard);
14602 #endif
14603 #ifdef HAVE_X_I18N
14604 if (dpyinfo->xim)
14605 xim_close_dpy (dpyinfo);
14606 #endif
14607
14608 xfree (dpyinfo->font_table);
14609 xfree (dpyinfo->x_id_name);
14610 xfree (dpyinfo->color_cells);
14611 xfree (dpyinfo);
14612 }
14613
14614 \f
14615 /* Set up use of X before we make the first connection. */
14616
14617 static struct redisplay_interface x_redisplay_interface =
14618 {
14619 x_produce_glyphs,
14620 x_write_glyphs,
14621 x_insert_glyphs,
14622 x_clear_end_of_line,
14623 x_scroll_run,
14624 x_after_update_window_line,
14625 x_update_window_begin,
14626 x_update_window_end,
14627 XTcursor_to,
14628 x_flush,
14629 x_clear_mouse_face,
14630 x_get_glyph_overhangs,
14631 x_fix_overlapping_area
14632 };
14633
14634 void
14635 x_initialize ()
14636 {
14637 rif = &x_redisplay_interface;
14638
14639 clear_frame_hook = x_clear_frame;
14640 ins_del_lines_hook = x_ins_del_lines;
14641 delete_glyphs_hook = x_delete_glyphs;
14642 ring_bell_hook = XTring_bell;
14643 reset_terminal_modes_hook = XTreset_terminal_modes;
14644 set_terminal_modes_hook = XTset_terminal_modes;
14645 update_begin_hook = x_update_begin;
14646 update_end_hook = x_update_end;
14647 set_terminal_window_hook = XTset_terminal_window;
14648 read_socket_hook = XTread_socket;
14649 frame_up_to_date_hook = XTframe_up_to_date;
14650 mouse_position_hook = XTmouse_position;
14651 frame_rehighlight_hook = XTframe_rehighlight;
14652 frame_raise_lower_hook = XTframe_raise_lower;
14653 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14654 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14655 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14656 judge_scroll_bars_hook = XTjudge_scroll_bars;
14657 estimate_mode_line_height_hook = x_estimate_mode_line_height;
14658
14659 scroll_region_ok = 1; /* we'll scroll partial frames */
14660 char_ins_del_ok = 1;
14661 line_ins_del_ok = 1; /* we'll just blt 'em */
14662 fast_clear_end_of_line = 1; /* X does this well */
14663 memory_below_frame = 0; /* we don't remember what scrolls
14664 off the bottom */
14665 baud_rate = 19200;
14666
14667 x_noop_count = 0;
14668 last_tool_bar_item = -1;
14669 any_help_event_p = 0;
14670
14671 /* Try to use interrupt input; if we can't, then start polling. */
14672 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14673
14674 #ifdef USE_X_TOOLKIT
14675 XtToolkitInitialize ();
14676
14677 Xt_app_con = XtCreateApplicationContext ();
14678
14679 /* Register a converter from strings to pixels, which uses
14680 Emacs' color allocation infrastructure. */
14681 XtAppSetTypeConverter (Xt_app_con,
14682 XtRString, XtRPixel, cvt_string_to_pixel,
14683 cvt_string_to_pixel_args,
14684 XtNumber (cvt_string_to_pixel_args),
14685 XtCacheByDisplay, cvt_pixel_dtor);
14686
14687 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
14688
14689 /* Install an asynchronous timer that processes Xt timeout events
14690 every 0.1s. This is necessary because some widget sets use
14691 timeouts internally, for example the LessTif menu bar, or the
14692 Xaw3d scroll bar. When Xt timouts aren't processed, these
14693 widgets don't behave normally. */
14694 {
14695 EMACS_TIME interval;
14696 EMACS_SET_SECS_USECS (interval, 0, 100000);
14697 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14698 }
14699 #endif
14700
14701 #ifdef USE_TOOLKIT_SCROLL_BARS
14702 xaw3d_arrow_scroll = False;
14703 xaw3d_pick_top = True;
14704 #endif
14705
14706 /* Note that there is no real way portable across R3/R4 to get the
14707 original error handler. */
14708 XSetErrorHandler (x_error_handler);
14709 XSetIOErrorHandler (x_io_error_quitter);
14710
14711 /* Disable Window Change signals; they are handled by X events. */
14712 #ifdef SIGWINCH
14713 signal (SIGWINCH, SIG_DFL);
14714 #endif /* ! defined (SIGWINCH) */
14715
14716 signal (SIGPIPE, x_connection_signal);
14717 }
14718
14719
14720 void
14721 syms_of_xterm ()
14722 {
14723 staticpro (&x_error_message_string);
14724 x_error_message_string = Qnil;
14725
14726 staticpro (&x_display_name_list);
14727 x_display_name_list = Qnil;
14728
14729 staticpro (&last_mouse_scroll_bar);
14730 last_mouse_scroll_bar = Qnil;
14731
14732 staticpro (&Qvendor_specific_keysyms);
14733 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
14734
14735 staticpro (&last_mouse_press_frame);
14736 last_mouse_press_frame = Qnil;
14737
14738 help_echo = Qnil;
14739 staticpro (&help_echo);
14740 help_echo_object = Qnil;
14741 staticpro (&help_echo_object);
14742 help_echo_window = Qnil;
14743 staticpro (&help_echo_window);
14744 previous_help_echo = Qnil;
14745 staticpro (&previous_help_echo);
14746 help_echo_pos = -1;
14747
14748 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14749 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
14750 For example, if a block cursor is over a tab, it will be drawn as
14751 wide as that tab on the display. */);
14752 x_stretch_cursor_p = 0;
14753
14754 DEFVAR_BOOL ("x-use-underline-position-properties",
14755 &x_use_underline_position_properties,
14756 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
14757 Nil means ignore them. If you encounter fonts with bogus
14758 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
14759 to 4.1, set this to nil. */);
14760 x_use_underline_position_properties = 1;
14761
14762 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14763 doc: /* What X toolkit scroll bars Emacs uses.
14764 A value of nil means Emacs doesn't use X toolkit scroll bars.
14765 Otherwise, value is a symbol describing the X toolkit. */);
14766 #ifdef USE_TOOLKIT_SCROLL_BARS
14767 #ifdef USE_MOTIF
14768 Vx_toolkit_scroll_bars = intern ("motif");
14769 #elif defined HAVE_XAW3D
14770 Vx_toolkit_scroll_bars = intern ("xaw3d");
14771 #else
14772 Vx_toolkit_scroll_bars = intern ("xaw");
14773 #endif
14774 #else
14775 Vx_toolkit_scroll_bars = Qnil;
14776 #endif
14777
14778 staticpro (&last_mouse_motion_frame);
14779 last_mouse_motion_frame = Qnil;
14780 }
14781
14782 #endif /* HAVE_X_WINDOWS */