(x_draw_glyph_string_foreground)
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
24
25 #include <config.h>
26
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
29 #include <signal.h>
30
31 #include <stdio.h>
32
33 #ifdef HAVE_X_WINDOWS
34
35 #include "lisp.h"
36 #include "blockinput.h"
37
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
41
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
46
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
56
57 #include "systty.h"
58 #include "systime.h"
59
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
69
70 #include "charset.h"
71 #include "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #include "gnu.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85 #include "process.h"
86 #include "atimer.h"
87 #include "keymap.h"
88
89 #ifdef USE_X_TOOLKIT
90 #include <X11/Shell.h>
91 #endif
92
93 #ifdef HAVE_SYS_TIME_H
94 #include <sys/time.h>
95 #endif
96 #ifdef HAVE_UNISTD_H
97 #include <unistd.h>
98 #endif
99
100 #ifdef USE_LUCID
101 extern int xlwmenu_window_p P_ ((Widget w, Window window));
102 extern void xlwmenu_redisplay P_ ((Widget));
103 #endif
104
105 #ifdef USE_X_TOOLKIT
106
107 extern void free_frame_menubar P_ ((struct frame *));
108 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
109 int));
110
111 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112 #define HACK_EDITRES
113 extern void _XEditResCheckMessages ();
114 #endif /* not NO_EDITRES */
115
116 /* Include toolkit specific headers for the scroll bar widget. */
117
118 #ifdef USE_TOOLKIT_SCROLL_BARS
119 #if defined USE_MOTIF
120 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
121 #include <Xm/ScrollBar.h>
122 #else /* !USE_MOTIF i.e. use Xaw */
123
124 #ifdef HAVE_XAW3D
125 #include <X11/Xaw3d/Simple.h>
126 #include <X11/Xaw3d/Scrollbar.h>
127 #define ARROW_SCROLLBAR
128 #include <X11/Xaw3d/ScrollbarP.h>
129 #else /* !HAVE_XAW3D */
130 #include <X11/Xaw/Simple.h>
131 #include <X11/Xaw/Scrollbar.h>
132 #endif /* !HAVE_XAW3D */
133 #ifndef XtNpickTop
134 #define XtNpickTop "pickTop"
135 #endif /* !XtNpickTop */
136 #endif /* !USE_MOTIF */
137 #endif /* USE_TOOLKIT_SCROLL_BARS */
138
139 #endif /* USE_X_TOOLKIT */
140
141 #ifndef USE_X_TOOLKIT
142 #define x_any_window_to_frame x_window_to_frame
143 #define x_top_window_to_frame x_window_to_frame
144 #endif
145
146 #ifdef USE_X_TOOLKIT
147 #include "widget.h"
148 #ifndef XtNinitialState
149 #define XtNinitialState "initialState"
150 #endif
151 #endif
152
153 #define abs(x) ((x) < 0 ? -(x) : (x))
154
155 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
156
157 \f
158 /* Fringe bitmaps. */
159
160 enum fringe_bitmap_type
161 {
162 NO_FRINGE_BITMAP,
163 LEFT_TRUNCATION_BITMAP,
164 RIGHT_TRUNCATION_BITMAP,
165 OVERLAY_ARROW_BITMAP,
166 CONTINUED_LINE_BITMAP,
167 CONTINUATION_LINE_BITMAP,
168 ZV_LINE_BITMAP
169 };
170
171 /* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
173
174 #define zv_width 8
175 #define zv_height 72
176 #define zv_period 3
177 static unsigned char zv_bits[] = {
178 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
179 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
180 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
181 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
182 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
183 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
184 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
185 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
186
187 /* An arrow like this: `<-'. */
188
189 #define left_width 8
190 #define left_height 8
191 static unsigned char left_bits[] = {
192 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
193
194 /* Right truncation arrow bitmap `->'. */
195
196 #define right_width 8
197 #define right_height 8
198 static unsigned char right_bits[] = {
199 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
200
201 /* Marker for continued lines. */
202
203 #define continued_width 8
204 #define continued_height 8
205 static unsigned char continued_bits[] = {
206 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
207
208 /* Marker for continuation lines. */
209
210 #define continuation_width 8
211 #define continuation_height 8
212 static unsigned char continuation_bits[] = {
213 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
214
215 /* Overlay arrow bitmap. */
216
217 #if 0
218 /* A bomb. */
219 #define ov_width 8
220 #define ov_height 8
221 static unsigned char ov_bits[] = {
222 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
223 #else
224 /* A triangular arrow. */
225 #define ov_width 8
226 #define ov_height 8
227 static unsigned char ov_bits[] = {
228 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
229
230 #endif
231
232 extern Lisp_Object Qhelp_echo;
233
234 \f
235 /* Non-nil means Emacs uses toolkit scroll bars. */
236
237 Lisp_Object Vx_toolkit_scroll_bars;
238
239 /* If a string, XTread_socket generates an event to display that string.
240 (The display is done in read_char.) */
241
242 static Lisp_Object help_echo;
243 static Lisp_Object help_echo_window;
244 static Lisp_Object help_echo_object;
245 static int help_echo_pos;
246
247 /* Temporary variable for XTread_socket. */
248
249 static Lisp_Object previous_help_echo;
250
251 /* Non-zero means that a HELP_EVENT has been generated since Emacs
252 start. */
253
254 static int any_help_event_p;
255
256 /* Non-zero means autoselect window with the mouse cursor. */
257
258 int mouse_autoselect_window;
259
260 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
261 static Lisp_Object last_window;
262
263 /* Non-zero means draw block and hollow cursor as wide as the glyph
264 under it. For example, if a block cursor is over a tab, it will be
265 drawn as wide as that tab on the display. */
266
267 int x_stretch_cursor_p;
268
269 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
270
271 int x_use_underline_position_properties;
272
273 /* This is a chain of structures for all the X displays currently in
274 use. */
275
276 struct x_display_info *x_display_list;
277
278 /* This is a list of cons cells, each of the form (NAME
279 . FONT-LIST-CACHE), one for each element of x_display_list and in
280 the same order. NAME is the name of the frame. FONT-LIST-CACHE
281 records previous values returned by x-list-fonts. */
282
283 Lisp_Object x_display_name_list;
284
285 /* Frame being updated by update_frame. This is declared in term.c.
286 This is set by update_begin and looked at by all the XT functions.
287 It is zero while not inside an update. In that case, the XT
288 functions assume that `selected_frame' is the frame to apply to. */
289
290 extern struct frame *updating_frame;
291
292 /* This is a frame waiting to be auto-raised, within XTread_socket. */
293
294 struct frame *pending_autoraise_frame;
295
296 #ifdef USE_X_TOOLKIT
297 /* The application context for Xt use. */
298 XtAppContext Xt_app_con;
299 static String Xt_default_resources[] = {0};
300 #endif /* USE_X_TOOLKIT */
301
302 /* Nominal cursor position -- where to draw output.
303 HPOS and VPOS are window relative glyph matrix coordinates.
304 X and Y are window relative pixel coordinates. */
305
306 struct cursor_pos output_cursor;
307
308 /* Non-zero means user is interacting with a toolkit scroll bar. */
309
310 static int toolkit_scroll_bar_interaction;
311
312 /* Mouse movement.
313
314 Formerly, we used PointerMotionHintMask (in standard_event_mask)
315 so that we would have to call XQueryPointer after each MotionNotify
316 event to ask for another such event. However, this made mouse tracking
317 slow, and there was a bug that made it eventually stop.
318
319 Simply asking for MotionNotify all the time seems to work better.
320
321 In order to avoid asking for motion events and then throwing most
322 of them away or busy-polling the server for mouse positions, we ask
323 the server for pointer motion hints. This means that we get only
324 one event per group of mouse movements. "Groups" are delimited by
325 other kinds of events (focus changes and button clicks, for
326 example), or by XQueryPointer calls; when one of these happens, we
327 get another MotionNotify event the next time the mouse moves. This
328 is at least as efficient as getting motion events when mouse
329 tracking is on, and I suspect only negligibly worse when tracking
330 is off. */
331
332 /* Where the mouse was last time we reported a mouse event. */
333
334 FRAME_PTR last_mouse_frame;
335 static XRectangle last_mouse_glyph;
336 static Lisp_Object last_mouse_press_frame;
337
338 /* The scroll bar in which the last X motion event occurred.
339
340 If the last X motion event occurred in a scroll bar, we set this so
341 XTmouse_position can know whether to report a scroll bar motion or
342 an ordinary motion.
343
344 If the last X motion event didn't occur in a scroll bar, we set
345 this to Qnil, to tell XTmouse_position to return an ordinary motion
346 event. */
347
348 static Lisp_Object last_mouse_scroll_bar;
349
350 /* This is a hack. We would really prefer that XTmouse_position would
351 return the time associated with the position it returns, but there
352 doesn't seem to be any way to wrest the time-stamp from the server
353 along with the position query. So, we just keep track of the time
354 of the last movement we received, and return that in hopes that
355 it's somewhat accurate. */
356
357 static Time last_mouse_movement_time;
358
359 /* Incremented by XTread_socket whenever it really tries to read
360 events. */
361
362 #ifdef __STDC__
363 static int volatile input_signal_count;
364 #else
365 static int input_signal_count;
366 #endif
367
368 /* Used locally within XTread_socket. */
369
370 static int x_noop_count;
371
372 /* Initial values of argv and argc. */
373
374 extern char **initial_argv;
375 extern int initial_argc;
376
377 extern Lisp_Object Vcommand_line_args, Vsystem_name;
378
379 /* Tells if a window manager is present or not. */
380
381 extern Lisp_Object Vx_no_window_manager;
382
383 extern Lisp_Object Qface, Qmouse_face, Qeql;
384
385 extern int errno;
386
387 /* A mask of extra modifier bits to put into every keyboard char. */
388
389 extern EMACS_INT extra_keyboard_modifiers;
390
391 /* The keysyms to use for the various modifiers. */
392
393 Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
394 Lisp_Object Vx_keysym_table;
395 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
396
397 static Lisp_Object Qvendor_specific_keysyms;
398 static Lisp_Object Qlatin_1, Qutf_8;
399
400 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
401 extern Lisp_Object x_icon_type P_ ((struct frame *));
402
403
404 /* Enumeration for overriding/changing the face to use for drawing
405 glyphs in x_draw_glyphs. */
406
407 enum draw_glyphs_face
408 {
409 DRAW_NORMAL_TEXT,
410 DRAW_INVERSE_VIDEO,
411 DRAW_CURSOR,
412 DRAW_MOUSE_FACE,
413 DRAW_IMAGE_RAISED,
414 DRAW_IMAGE_SUNKEN
415 };
416
417 static int cursor_in_mouse_face_p P_ ((struct window *));
418 static int clear_mouse_face P_ ((struct x_display_info *));
419 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
420 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
421 static const XColor *x_color_cells P_ ((Display *, int *));
422 static void x_update_window_end P_ ((struct window *, int, int));
423 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
424 void x_delete_display P_ ((struct x_display_info *));
425 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
426 unsigned));
427 static int fast_find_position P_ ((struct window *, int, int *, int *,
428 int *, int *, Lisp_Object));
429 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
430 int *, int *, int *, int *, int));
431 static void set_output_cursor P_ ((struct cursor_pos *));
432 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
433 int *, int *, int *, int));
434 static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
435 int, int));
436 static void note_mouse_highlight P_ ((struct frame *, int, int));
437 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
438 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
439 static void show_mouse_face P_ ((struct x_display_info *,
440 enum draw_glyphs_face));
441 static int x_io_error_quitter P_ ((Display *));
442 int x_catch_errors P_ ((Display *));
443 void x_uncatch_errors P_ ((Display *, int));
444 void x_lower_frame P_ ((struct frame *));
445 void x_scroll_bar_clear P_ ((struct frame *));
446 int x_had_errors_p P_ ((Display *));
447 void x_wm_set_size_hint P_ ((struct frame *, long, int));
448 void x_raise_frame P_ ((struct frame *));
449 void x_set_window_size P_ ((struct frame *, int, int, int));
450 void x_wm_set_window_state P_ ((struct frame *, int));
451 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
452 void x_initialize P_ ((void));
453 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
454 static int x_compute_min_glyph_bounds P_ ((struct frame *));
455 static void x_draw_phys_cursor_glyph P_ ((struct window *,
456 struct glyph_row *,
457 enum draw_glyphs_face));
458 static void x_update_end P_ ((struct frame *));
459 static void XTframe_up_to_date P_ ((struct frame *));
460 static void XTset_terminal_modes P_ ((void));
461 static void XTreset_terminal_modes P_ ((void));
462 static void XTcursor_to P_ ((int, int, int, int));
463 static void x_write_glyphs P_ ((struct glyph *, int));
464 static void x_clear_end_of_line P_ ((int));
465 static void x_clear_frame P_ ((void));
466 static void x_clear_cursor P_ ((struct window *));
467 static void frame_highlight P_ ((struct frame *));
468 static void frame_unhighlight P_ ((struct frame *));
469 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
470 static int x_focus_changed P_ ((int,
471 int,
472 struct x_display_info *,
473 struct frame *,
474 struct input_event *,
475 int));
476 static int x_detect_focus_change P_ ((struct x_display_info *,
477 XEvent *,
478 struct input_event *,
479 int));
480 static void XTframe_rehighlight P_ ((struct frame *));
481 static void x_frame_rehighlight P_ ((struct x_display_info *));
482 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
483 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
484 enum text_cursor_kinds));
485 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
486 XRectangle *));
487 static void expose_frame P_ ((struct frame *, int, int, int, int));
488 static int expose_window_tree P_ ((struct window *, XRectangle *));
489 static void expose_overlaps P_ ((struct window *, struct glyph_row *,
490 struct glyph_row *));
491 static int expose_window P_ ((struct window *, XRectangle *));
492 static void expose_area P_ ((struct window *, struct glyph_row *,
493 XRectangle *, enum glyph_row_area));
494 static int expose_line P_ ((struct window *, struct glyph_row *,
495 XRectangle *));
496 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
497 static void x_update_window_cursor P_ ((struct window *, int));
498 static void x_erase_phys_cursor P_ ((struct window *));
499 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
500 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
501 enum fringe_bitmap_type, int left_p));
502
503 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
504 GC, int));
505 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
506 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
507 static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
508 int, int, int, int));
509 static void x_flush P_ ((struct frame *f));
510 static void x_update_begin P_ ((struct frame *));
511 static void x_update_window_begin P_ ((struct window *));
512 static void x_draw_vertical_border P_ ((struct window *));
513 static void x_after_update_window_line P_ ((struct glyph_row *));
514 static INLINE void take_vertical_position_into_account P_ ((struct it *));
515 static void x_produce_stretch_glyph P_ ((struct it *));
516 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
517 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
518 enum scroll_bar_part *,
519 Lisp_Object *, Lisp_Object *,
520 unsigned long *));
521 static void x_check_fullscreen P_ ((struct frame *));
522 static void x_check_fullscreen_move P_ ((struct frame *));
523
524 /* Flush display of frame F, or of all frames if F is null. */
525
526 static void
527 x_flush (f)
528 struct frame *f;
529 {
530 BLOCK_INPUT;
531 if (f == NULL)
532 {
533 Lisp_Object rest, frame;
534 FOR_EACH_FRAME (rest, frame)
535 x_flush (XFRAME (frame));
536 }
537 else if (FRAME_X_P (f))
538 XFlush (FRAME_X_DISPLAY (f));
539 UNBLOCK_INPUT;
540 }
541
542
543 /* Remove calls to XFlush by defining XFlush to an empty replacement.
544 Calls to XFlush should be unnecessary because the X output buffer
545 is flushed automatically as needed by calls to XPending,
546 XNextEvent, or XWindowEvent according to the XFlush man page.
547 XTread_socket calls XPending. Removing XFlush improves
548 performance. */
549
550 #define XFlush(DISPLAY) (void) 0
551
552 \f
553 /***********************************************************************
554 Debugging
555 ***********************************************************************/
556
557 #if 0
558
559 /* This is a function useful for recording debugging information about
560 the sequence of occurrences in this file. */
561
562 struct record
563 {
564 char *locus;
565 int type;
566 };
567
568 struct record event_record[100];
569
570 int event_record_index;
571
572 record_event (locus, type)
573 char *locus;
574 int type;
575 {
576 if (event_record_index == sizeof (event_record) / sizeof (struct record))
577 event_record_index = 0;
578
579 event_record[event_record_index].locus = locus;
580 event_record[event_record_index].type = type;
581 event_record_index++;
582 }
583
584 #endif /* 0 */
585
586
587 \f
588 /* Return the struct x_display_info corresponding to DPY. */
589
590 struct x_display_info *
591 x_display_info_for_display (dpy)
592 Display *dpy;
593 {
594 struct x_display_info *dpyinfo;
595
596 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
597 if (dpyinfo->display == dpy)
598 return dpyinfo;
599
600 return 0;
601 }
602
603
604 \f
605 /***********************************************************************
606 Starting and ending an update
607 ***********************************************************************/
608
609 /* Start an update of frame F. This function is installed as a hook
610 for update_begin, i.e. it is called when update_begin is called.
611 This function is called prior to calls to x_update_window_begin for
612 each window being updated. Currently, there is nothing to do here
613 because all interesting stuff is done on a window basis. */
614
615 static void
616 x_update_begin (f)
617 struct frame *f;
618 {
619 /* Nothing to do. */
620 }
621
622
623 /* Start update of window W. Set the global variable updated_window
624 to the window being updated and set output_cursor to the cursor
625 position of W. */
626
627 static void
628 x_update_window_begin (w)
629 struct window *w;
630 {
631 struct frame *f = XFRAME (WINDOW_FRAME (w));
632 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
633
634 updated_window = w;
635 set_output_cursor (&w->cursor);
636
637 BLOCK_INPUT;
638
639 if (f == display_info->mouse_face_mouse_frame)
640 {
641 /* Don't do highlighting for mouse motion during the update. */
642 display_info->mouse_face_defer = 1;
643
644 /* If F needs to be redrawn, simply forget about any prior mouse
645 highlighting. */
646 if (FRAME_GARBAGED_P (f))
647 display_info->mouse_face_window = Qnil;
648
649 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
650 their mouse_face_p flag set, which means that they are always
651 unequal to rows in a desired matrix which never have that
652 flag set. So, rows containing mouse-face glyphs are never
653 scrolled, and we don't have to switch the mouse highlight off
654 here to prevent it from being scrolled. */
655
656 /* Can we tell that this update does not affect the window
657 where the mouse highlight is? If so, no need to turn off.
658 Likewise, don't do anything if the frame is garbaged;
659 in that case, the frame's current matrix that we would use
660 is all wrong, and we will redisplay that line anyway. */
661 if (!NILP (display_info->mouse_face_window)
662 && w == XWINDOW (display_info->mouse_face_window))
663 {
664 int i;
665
666 for (i = 0; i < w->desired_matrix->nrows; ++i)
667 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
668 break;
669
670 if (i < w->desired_matrix->nrows)
671 clear_mouse_face (display_info);
672 }
673 #endif /* 0 */
674 }
675
676 UNBLOCK_INPUT;
677 }
678
679
680 /* Draw a vertical window border to the right of window W if W doesn't
681 have vertical scroll bars. */
682
683 static void
684 x_draw_vertical_border (w)
685 struct window *w;
686 {
687 struct frame *f = XFRAME (WINDOW_FRAME (w));
688
689 /* Redraw borders between horizontally adjacent windows. Don't
690 do it for frames with vertical scroll bars because either the
691 right scroll bar of a window, or the left scroll bar of its
692 neighbor will suffice as a border. */
693 if (!WINDOW_RIGHTMOST_P (w)
694 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
695 {
696 int x0, x1, y0, y1;
697
698 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
699 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
700 y1 -= 1;
701
702 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
703 f->output_data.x->normal_gc, x1, y0, x1, y1);
704 }
705 }
706
707
708 /* End update of window W (which is equal to updated_window).
709
710 Draw vertical borders between horizontally adjacent windows, and
711 display W's cursor if CURSOR_ON_P is non-zero.
712
713 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
714 glyphs in mouse-face were overwritten. In that case we have to
715 make sure that the mouse-highlight is properly redrawn.
716
717 W may be a menu bar pseudo-window in case we don't have X toolkit
718 support. Such windows don't have a cursor, so don't display it
719 here. */
720
721 static void
722 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
723 struct window *w;
724 int cursor_on_p, mouse_face_overwritten_p;
725 {
726 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
727
728 if (!w->pseudo_window_p)
729 {
730 BLOCK_INPUT;
731
732 if (cursor_on_p)
733 x_display_and_set_cursor (w, 1, output_cursor.hpos,
734 output_cursor.vpos,
735 output_cursor.x, output_cursor.y);
736
737 x_draw_vertical_border (w);
738 UNBLOCK_INPUT;
739 }
740
741 /* If a row with mouse-face was overwritten, arrange for
742 XTframe_up_to_date to redisplay the mouse highlight. */
743 if (mouse_face_overwritten_p)
744 {
745 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
746 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
747 dpyinfo->mouse_face_window = Qnil;
748 }
749
750 updated_window = NULL;
751 }
752
753
754 /* End update of frame F. This function is installed as a hook in
755 update_end. */
756
757 static void
758 x_update_end (f)
759 struct frame *f;
760 {
761 /* Mouse highlight may be displayed again. */
762 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
763
764 BLOCK_INPUT;
765 XFlush (FRAME_X_DISPLAY (f));
766 UNBLOCK_INPUT;
767 }
768
769
770 /* This function is called from various places in xdisp.c whenever a
771 complete update has been performed. The global variable
772 updated_window is not available here. */
773
774 static void
775 XTframe_up_to_date (f)
776 struct frame *f;
777 {
778 if (FRAME_X_P (f))
779 {
780 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
781
782 if (dpyinfo->mouse_face_deferred_gc
783 || f == dpyinfo->mouse_face_mouse_frame)
784 {
785 BLOCK_INPUT;
786 if (dpyinfo->mouse_face_mouse_frame)
787 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
788 dpyinfo->mouse_face_mouse_x,
789 dpyinfo->mouse_face_mouse_y);
790 dpyinfo->mouse_face_deferred_gc = 0;
791 UNBLOCK_INPUT;
792 }
793 }
794 }
795
796
797 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
798 arrow bitmaps, or clear the fringes if no bitmaps are required
799 before DESIRED_ROW is made current. The window being updated is
800 found in updated_window. This function It is called from
801 update_window_line only if it is known that there are differences
802 between bitmaps to be drawn between current row and DESIRED_ROW. */
803
804 static void
805 x_after_update_window_line (desired_row)
806 struct glyph_row *desired_row;
807 {
808 struct window *w = updated_window;
809 struct frame *f;
810 int width, height;
811
812 xassert (w);
813
814 if (!desired_row->mode_line_p && !w->pseudo_window_p)
815 {
816 BLOCK_INPUT;
817 x_draw_row_fringe_bitmaps (w, desired_row);
818 UNBLOCK_INPUT;
819 }
820
821 /* When a window has disappeared, make sure that no rest of
822 full-width rows stays visible in the internal border. Could
823 check here if updated_window is the leftmost/rightmost window,
824 but I guess it's not worth doing since vertically split windows
825 are almost never used, internal border is rarely set, and the
826 overhead is very small. */
827 if (windows_or_buffers_changed
828 && desired_row->full_width_p
829 && (f = XFRAME (w->frame),
830 width = FRAME_INTERNAL_BORDER_WIDTH (f),
831 width != 0)
832 && (height = desired_row->visible_height,
833 height > 0))
834 {
835 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
836
837 /* Internal border is drawn below the tool bar. */
838 if (WINDOWP (f->tool_bar_window)
839 && w == XWINDOW (f->tool_bar_window))
840 y -= width;
841
842 BLOCK_INPUT;
843 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
844 0, y, width, height, False);
845 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
846 f->output_data.x->pixel_width - width,
847 y, width, height, False);
848 UNBLOCK_INPUT;
849 }
850 }
851
852
853 /* Draw the bitmap WHICH in one of the left or right fringes of
854 window W. ROW is the glyph row for which to display the bitmap; it
855 determines the vertical position at which the bitmap has to be
856 drawn. */
857
858 static void
859 x_draw_fringe_bitmap (w, row, which, left_p)
860 struct window *w;
861 struct glyph_row *row;
862 enum fringe_bitmap_type which;
863 int left_p;
864 {
865 struct frame *f = XFRAME (WINDOW_FRAME (w));
866 Display *display = FRAME_X_DISPLAY (f);
867 Window window = FRAME_X_WINDOW (f);
868 int x, y, wd, h, dy;
869 int b1, b2;
870 unsigned char *bits = NULL;
871 Pixmap pixmap;
872 GC gc = f->output_data.x->normal_gc;
873 struct face *face;
874 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
875
876 /* Must clip because of partially visible lines. */
877 x_clip_to_row (w, row, gc, 1);
878
879 /* Convert row to frame coordinates. */
880 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
881
882 switch (which)
883 {
884 case NO_FRINGE_BITMAP:
885 wd = 0;
886 h = 0;
887 break;
888
889 case LEFT_TRUNCATION_BITMAP:
890 wd = left_width;
891 h = left_height;
892 bits = left_bits;
893 break;
894
895 case OVERLAY_ARROW_BITMAP:
896 wd = ov_width;
897 h = ov_height;
898 bits = ov_bits;
899 break;
900
901 case RIGHT_TRUNCATION_BITMAP:
902 wd = right_width;
903 h = right_height;
904 bits = right_bits;
905 break;
906
907 case CONTINUED_LINE_BITMAP:
908 wd = continued_width;
909 h = continued_height;
910 bits = continued_bits;
911 break;
912
913 case CONTINUATION_LINE_BITMAP:
914 wd = continuation_width;
915 h = continuation_height;
916 bits = continuation_bits;
917 break;
918
919 case ZV_LINE_BITMAP:
920 wd = zv_width;
921 h = zv_height - (y % zv_period);
922 bits = zv_bits + (y % zv_period);
923 break;
924
925 default:
926 abort ();
927 }
928
929 /* Clip bitmap if too high. */
930 if (h > row->height)
931 h = row->height;
932
933 /* Set dy to the offset in the row to start drawing the bitmap. */
934 dy = (row->height - h) / 2;
935
936 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
937 PREPARE_FACE_FOR_DISPLAY (f, face);
938
939 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
940 the fringe. */
941 b1 = b2 = -1;
942 if (left_p)
943 {
944 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
945 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
946 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
947 - wd
948 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
949 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
950 {
951 /* If W has a vertical border to its left, don't draw over it. */
952 int border = ((XFASTINT (w->left) > 0
953 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
954 ? 1 : 0);
955 b1 = (window_box_left (w, -1)
956 - FRAME_X_LEFT_FRINGE_WIDTH (f)
957 + border);
958 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
959 }
960 }
961 else
962 {
963 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
964 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
965 x = (window_box_right (w, -1)
966 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
967 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
968 the fringe. */
969 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
970 {
971 b1 = window_box_right (w, -1);
972 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
973 }
974 }
975
976 if (b1 >= 0)
977 {
978 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
979
980 /* In case the same realized face is used for fringes and
981 for something displayed in the text (e.g. face `region' on
982 mono-displays, the fill style may have been changed to
983 FillSolid in x_draw_glyph_string_background. */
984 if (face->stipple)
985 XSetFillStyle (display, face->gc, FillOpaqueStippled);
986 else
987 XSetForeground (display, face->gc, face->background);
988
989 XFillRectangle (display, window, face->gc,
990 b1,
991 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
992 row->y)),
993 b2,
994 row->visible_height);
995 if (!face->stipple)
996 XSetForeground (display, face->gc, face->foreground);
997 }
998
999 if (which != NO_FRINGE_BITMAP)
1000 {
1001 /* Draw the bitmap. I believe these small pixmaps can be cached
1002 by the server. */
1003 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
1004 face->foreground,
1005 face->background, depth);
1006 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
1007 XFreePixmap (display, pixmap);
1008 }
1009
1010 XSetClipMask (display, gc, None);
1011 }
1012
1013
1014 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
1015 function with input blocked. */
1016
1017 static void
1018 x_draw_row_fringe_bitmaps (w, row)
1019 struct window *w;
1020 struct glyph_row *row;
1021 {
1022 struct frame *f = XFRAME (w->frame);
1023 enum fringe_bitmap_type bitmap;
1024
1025 xassert (interrupt_input_blocked);
1026
1027 /* If row is completely invisible, because of vscrolling, we
1028 don't have to draw anything. */
1029 if (row->visible_height <= 0)
1030 return;
1031
1032 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
1033 {
1034 /* Decide which bitmap to draw in the left fringe. */
1035 if (row->overlay_arrow_p)
1036 bitmap = OVERLAY_ARROW_BITMAP;
1037 else if (row->truncated_on_left_p)
1038 bitmap = LEFT_TRUNCATION_BITMAP;
1039 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1040 bitmap = CONTINUATION_LINE_BITMAP;
1041 else if (row->indicate_empty_line_p)
1042 bitmap = ZV_LINE_BITMAP;
1043 else
1044 bitmap = NO_FRINGE_BITMAP;
1045
1046 x_draw_fringe_bitmap (w, row, bitmap, 1);
1047 }
1048
1049 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1050 {
1051 /* Decide which bitmap to draw in the right fringe. */
1052 if (row->truncated_on_right_p)
1053 bitmap = RIGHT_TRUNCATION_BITMAP;
1054 else if (row->continued_p)
1055 bitmap = CONTINUED_LINE_BITMAP;
1056 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1057 bitmap = ZV_LINE_BITMAP;
1058 else
1059 bitmap = NO_FRINGE_BITMAP;
1060
1061 x_draw_fringe_bitmap (w, row, bitmap, 0);
1062 }
1063 }
1064
1065 \f
1066
1067 /* This is called when starting Emacs and when restarting after
1068 suspend. When starting Emacs, no X window is mapped. And nothing
1069 must be done to Emacs's own window if it is suspended (though that
1070 rarely happens). */
1071
1072 static void
1073 XTset_terminal_modes ()
1074 {
1075 }
1076
1077 /* This is called when exiting or suspending Emacs. Exiting will make
1078 the X-windows go away, and suspending requires no action. */
1079
1080 static void
1081 XTreset_terminal_modes ()
1082 {
1083 }
1084
1085
1086 \f
1087 /***********************************************************************
1088 Output Cursor
1089 ***********************************************************************/
1090
1091 /* Set the global variable output_cursor to CURSOR. All cursor
1092 positions are relative to updated_window. */
1093
1094 static void
1095 set_output_cursor (cursor)
1096 struct cursor_pos *cursor;
1097 {
1098 output_cursor.hpos = cursor->hpos;
1099 output_cursor.vpos = cursor->vpos;
1100 output_cursor.x = cursor->x;
1101 output_cursor.y = cursor->y;
1102 }
1103
1104
1105 /* Set a nominal cursor position.
1106
1107 HPOS and VPOS are column/row positions in a window glyph matrix. X
1108 and Y are window text area relative pixel positions.
1109
1110 If this is done during an update, updated_window will contain the
1111 window that is being updated and the position is the future output
1112 cursor position for that window. If updated_window is null, use
1113 selected_window and display the cursor at the given position. */
1114
1115 static void
1116 XTcursor_to (vpos, hpos, y, x)
1117 int vpos, hpos, y, x;
1118 {
1119 struct window *w;
1120
1121 /* If updated_window is not set, work on selected_window. */
1122 if (updated_window)
1123 w = updated_window;
1124 else
1125 w = XWINDOW (selected_window);
1126
1127 /* Set the output cursor. */
1128 output_cursor.hpos = hpos;
1129 output_cursor.vpos = vpos;
1130 output_cursor.x = x;
1131 output_cursor.y = y;
1132
1133 /* If not called as part of an update, really display the cursor.
1134 This will also set the cursor position of W. */
1135 if (updated_window == NULL)
1136 {
1137 BLOCK_INPUT;
1138 x_display_cursor (w, 1, hpos, vpos, x, y);
1139 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1140 UNBLOCK_INPUT;
1141 }
1142 }
1143
1144
1145 \f
1146 /***********************************************************************
1147 Display Iterator
1148 ***********************************************************************/
1149
1150 /* Function prototypes of this page. */
1151
1152 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1153 struct glyph *,
1154 XChar2b *,
1155 int *));
1156 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1157 int, XChar2b *, int,
1158 int));
1159 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1160 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1161 static void x_append_glyph P_ ((struct it *));
1162 static void x_append_composite_glyph P_ ((struct it *));
1163 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1164 int, int, double));
1165 static void x_produce_glyphs P_ ((struct it *));
1166 static void x_produce_image_glyph P_ ((struct it *it));
1167
1168
1169 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1170 is not contained in the font. */
1171
1172 static INLINE XCharStruct *
1173 x_per_char_metric (font, char2b)
1174 XFontStruct *font;
1175 XChar2b *char2b;
1176 {
1177 /* The result metric information. */
1178 XCharStruct *pcm = NULL;
1179
1180 xassert (font && char2b);
1181
1182 if (font->per_char != NULL)
1183 {
1184 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1185 {
1186 /* min_char_or_byte2 specifies the linear character index
1187 corresponding to the first element of the per_char array,
1188 max_char_or_byte2 is the index of the last character. A
1189 character with non-zero CHAR2B->byte1 is not in the font.
1190 A character with byte2 less than min_char_or_byte2 or
1191 greater max_char_or_byte2 is not in the font. */
1192 if (char2b->byte1 == 0
1193 && char2b->byte2 >= font->min_char_or_byte2
1194 && char2b->byte2 <= font->max_char_or_byte2)
1195 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1196 }
1197 else
1198 {
1199 /* If either min_byte1 or max_byte1 are nonzero, both
1200 min_char_or_byte2 and max_char_or_byte2 are less than
1201 256, and the 2-byte character index values corresponding
1202 to the per_char array element N (counting from 0) are:
1203
1204 byte1 = N/D + min_byte1
1205 byte2 = N\D + min_char_or_byte2
1206
1207 where:
1208
1209 D = max_char_or_byte2 - min_char_or_byte2 + 1
1210 / = integer division
1211 \ = integer modulus */
1212 if (char2b->byte1 >= font->min_byte1
1213 && char2b->byte1 <= font->max_byte1
1214 && char2b->byte2 >= font->min_char_or_byte2
1215 && char2b->byte2 <= font->max_char_or_byte2)
1216 {
1217 pcm = (font->per_char
1218 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1219 * (char2b->byte1 - font->min_byte1))
1220 + (char2b->byte2 - font->min_char_or_byte2));
1221 }
1222 }
1223 }
1224 else
1225 {
1226 /* If the per_char pointer is null, all glyphs between the first
1227 and last character indexes inclusive have the same
1228 information, as given by both min_bounds and max_bounds. */
1229 if (char2b->byte2 >= font->min_char_or_byte2
1230 && char2b->byte2 <= font->max_char_or_byte2)
1231 pcm = &font->max_bounds;
1232 }
1233
1234 return ((pcm == NULL
1235 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1236 ? NULL : pcm);
1237 }
1238
1239
1240 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1241 the two-byte form of C. Encoding is returned in *CHAR2B. */
1242
1243 static INLINE void
1244 x_encode_char (c, char2b, font_info)
1245 int c;
1246 XChar2b *char2b;
1247 struct font_info *font_info;
1248 {
1249 int charset = CHAR_CHARSET (c);
1250 XFontStruct *font = font_info->font;
1251
1252 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1253 This may be either a program in a special encoder language or a
1254 fixed encoding. */
1255 if (font_info->font_encoder)
1256 {
1257 /* It's a program. */
1258 struct ccl_program *ccl = font_info->font_encoder;
1259
1260 if (CHARSET_DIMENSION (charset) == 1)
1261 {
1262 ccl->reg[0] = charset;
1263 ccl->reg[1] = char2b->byte2;
1264 ccl->reg[2] = -1;
1265 }
1266 else
1267 {
1268 ccl->reg[0] = charset;
1269 ccl->reg[1] = char2b->byte1;
1270 ccl->reg[2] = char2b->byte2;
1271 }
1272
1273 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1274
1275 /* We assume that MSBs are appropriately set/reset by CCL
1276 program. */
1277 if (font->max_byte1 == 0) /* 1-byte font */
1278 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1279 else
1280 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1281 }
1282 else if (font_info->encoding[charset])
1283 {
1284 /* Fixed encoding scheme. See fontset.h for the meaning of the
1285 encoding numbers. */
1286 int enc = font_info->encoding[charset];
1287
1288 if ((enc == 1 || enc == 2)
1289 && CHARSET_DIMENSION (charset) == 2)
1290 char2b->byte1 |= 0x80;
1291
1292 if (enc == 1 || enc == 3)
1293 char2b->byte2 |= 0x80;
1294 }
1295 }
1296
1297
1298 /* Get face and two-byte form of character C in face FACE_ID on frame
1299 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1300 means we want to display multibyte text. DISPLAY_P non-zero means
1301 make sure that X resources for the face returned are allocated.
1302 Value is a pointer to a realized face that is ready for display if
1303 DISPLAY_P is non-zero. */
1304
1305 static INLINE struct face *
1306 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
1307 struct frame *f;
1308 int c, face_id;
1309 XChar2b *char2b;
1310 int multibyte_p, display_p;
1311 {
1312 struct face *face = FACE_FROM_ID (f, face_id);
1313
1314 if (!multibyte_p)
1315 {
1316 /* Unibyte case. We don't have to encode, but we have to make
1317 sure to use a face suitable for unibyte. */
1318 char2b->byte1 = 0;
1319 char2b->byte2 = c;
1320 face_id = FACE_FOR_CHAR (f, face, c);
1321 face = FACE_FROM_ID (f, face_id);
1322 }
1323 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1324 {
1325 /* Case of ASCII in a face known to fit ASCII. */
1326 char2b->byte1 = 0;
1327 char2b->byte2 = c;
1328 }
1329 else
1330 {
1331 int c1, c2, charset;
1332
1333 /* Split characters into bytes. If c2 is -1 afterwards, C is
1334 really a one-byte character so that byte1 is zero. */
1335 SPLIT_CHAR (c, charset, c1, c2);
1336 if (c2 > 0)
1337 char2b->byte1 = c1, char2b->byte2 = c2;
1338 else
1339 char2b->byte1 = 0, char2b->byte2 = c1;
1340
1341 /* Maybe encode the character in *CHAR2B. */
1342 if (face->font != NULL)
1343 {
1344 struct font_info *font_info
1345 = FONT_INFO_FROM_ID (f, face->font_info_id);
1346 if (font_info)
1347 x_encode_char (c, char2b, font_info);
1348 }
1349 }
1350
1351 /* Make sure X resources of the face are allocated. */
1352 if (display_p)
1353 {
1354 xassert (face != NULL);
1355 PREPARE_FACE_FOR_DISPLAY (f, face);
1356 }
1357
1358 return face;
1359 }
1360
1361
1362 /* Get face and two-byte form of character glyph GLYPH on frame F.
1363 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1364 a pointer to a realized face that is ready for display. */
1365
1366 static INLINE struct face *
1367 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1368 struct frame *f;
1369 struct glyph *glyph;
1370 XChar2b *char2b;
1371 int *two_byte_p;
1372 {
1373 struct face *face;
1374
1375 xassert (glyph->type == CHAR_GLYPH);
1376 face = FACE_FROM_ID (f, glyph->face_id);
1377
1378 if (two_byte_p)
1379 *two_byte_p = 0;
1380
1381 if (!glyph->multibyte_p)
1382 {
1383 /* Unibyte case. We don't have to encode, but we have to make
1384 sure to use a face suitable for unibyte. */
1385 char2b->byte1 = 0;
1386 char2b->byte2 = glyph->u.ch;
1387 }
1388 else if (glyph->u.ch < 128
1389 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1390 {
1391 /* Case of ASCII in a face known to fit ASCII. */
1392 char2b->byte1 = 0;
1393 char2b->byte2 = glyph->u.ch;
1394 }
1395 else
1396 {
1397 int c1, c2, charset;
1398
1399 /* Split characters into bytes. If c2 is -1 afterwards, C is
1400 really a one-byte character so that byte1 is zero. */
1401 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1402 if (c2 > 0)
1403 char2b->byte1 = c1, char2b->byte2 = c2;
1404 else
1405 char2b->byte1 = 0, char2b->byte2 = c1;
1406
1407 /* Maybe encode the character in *CHAR2B. */
1408 if (charset != CHARSET_ASCII)
1409 {
1410 struct font_info *font_info
1411 = FONT_INFO_FROM_ID (f, face->font_info_id);
1412 if (font_info)
1413 {
1414 x_encode_char (glyph->u.ch, char2b, font_info);
1415 if (two_byte_p)
1416 *two_byte_p
1417 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1418 }
1419 }
1420 }
1421
1422 /* Make sure X resources of the face are allocated. */
1423 xassert (face != NULL);
1424 PREPARE_FACE_FOR_DISPLAY (f, face);
1425 return face;
1426 }
1427
1428
1429 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1430 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1431
1432 static INLINE void
1433 x_append_glyph (it)
1434 struct it *it;
1435 {
1436 struct glyph *glyph;
1437 enum glyph_row_area area = it->area;
1438
1439 xassert (it->glyph_row);
1440 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1441
1442 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1443 if (glyph < it->glyph_row->glyphs[area + 1])
1444 {
1445 glyph->charpos = CHARPOS (it->position);
1446 glyph->object = it->object;
1447 glyph->pixel_width = it->pixel_width;
1448 glyph->voffset = it->voffset;
1449 glyph->type = CHAR_GLYPH;
1450 glyph->multibyte_p = it->multibyte_p;
1451 glyph->left_box_line_p = it->start_of_box_run_p;
1452 glyph->right_box_line_p = it->end_of_box_run_p;
1453 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1454 || it->phys_descent > it->descent);
1455 glyph->padding_p = 0;
1456 glyph->glyph_not_available_p = it->glyph_not_available_p;
1457 glyph->face_id = it->face_id;
1458 glyph->u.ch = it->char_to_display;
1459 ++it->glyph_row->used[area];
1460 }
1461 }
1462
1463 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1464 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1465
1466 static INLINE void
1467 x_append_composite_glyph (it)
1468 struct it *it;
1469 {
1470 struct glyph *glyph;
1471 enum glyph_row_area area = it->area;
1472
1473 xassert (it->glyph_row);
1474
1475 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1476 if (glyph < it->glyph_row->glyphs[area + 1])
1477 {
1478 glyph->charpos = CHARPOS (it->position);
1479 glyph->object = it->object;
1480 glyph->pixel_width = it->pixel_width;
1481 glyph->voffset = it->voffset;
1482 glyph->type = COMPOSITE_GLYPH;
1483 glyph->multibyte_p = it->multibyte_p;
1484 glyph->left_box_line_p = it->start_of_box_run_p;
1485 glyph->right_box_line_p = it->end_of_box_run_p;
1486 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1487 || it->phys_descent > it->descent);
1488 glyph->padding_p = 0;
1489 glyph->glyph_not_available_p = 0;
1490 glyph->face_id = it->face_id;
1491 glyph->u.cmp_id = it->cmp_id;
1492 ++it->glyph_row->used[area];
1493 }
1494 }
1495
1496
1497 /* Change IT->ascent and IT->height according to the setting of
1498 IT->voffset. */
1499
1500 static INLINE void
1501 take_vertical_position_into_account (it)
1502 struct it *it;
1503 {
1504 if (it->voffset)
1505 {
1506 if (it->voffset < 0)
1507 /* Increase the ascent so that we can display the text higher
1508 in the line. */
1509 it->ascent += abs (it->voffset);
1510 else
1511 /* Increase the descent so that we can display the text lower
1512 in the line. */
1513 it->descent += it->voffset;
1514 }
1515 }
1516
1517
1518 /* Produce glyphs/get display metrics for the image IT is loaded with.
1519 See the description of struct display_iterator in dispextern.h for
1520 an overview of struct display_iterator. */
1521
1522 static void
1523 x_produce_image_glyph (it)
1524 struct it *it;
1525 {
1526 struct image *img;
1527 struct face *face;
1528
1529 xassert (it->what == IT_IMAGE);
1530
1531 face = FACE_FROM_ID (it->f, it->face_id);
1532 img = IMAGE_FROM_ID (it->f, it->image_id);
1533 xassert (img);
1534
1535 /* Make sure X resources of the face and image are loaded. */
1536 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1537 prepare_image_for_display (it->f, img);
1538
1539 it->ascent = it->phys_ascent = image_ascent (img, face);
1540 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1541 it->pixel_width = img->width + 2 * img->hmargin;
1542
1543 it->nglyphs = 1;
1544
1545 if (face->box != FACE_NO_BOX)
1546 {
1547 if (face->box_line_width > 0)
1548 {
1549 it->ascent += face->box_line_width;
1550 it->descent += face->box_line_width;
1551 }
1552
1553 if (it->start_of_box_run_p)
1554 it->pixel_width += abs (face->box_line_width);
1555 if (it->end_of_box_run_p)
1556 it->pixel_width += abs (face->box_line_width);
1557 }
1558
1559 take_vertical_position_into_account (it);
1560
1561 if (it->glyph_row)
1562 {
1563 struct glyph *glyph;
1564 enum glyph_row_area area = it->area;
1565
1566 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1567 if (glyph < it->glyph_row->glyphs[area + 1])
1568 {
1569 glyph->charpos = CHARPOS (it->position);
1570 glyph->object = it->object;
1571 glyph->pixel_width = it->pixel_width;
1572 glyph->voffset = it->voffset;
1573 glyph->type = IMAGE_GLYPH;
1574 glyph->multibyte_p = it->multibyte_p;
1575 glyph->left_box_line_p = it->start_of_box_run_p;
1576 glyph->right_box_line_p = it->end_of_box_run_p;
1577 glyph->overlaps_vertically_p = 0;
1578 glyph->padding_p = 0;
1579 glyph->glyph_not_available_p = 0;
1580 glyph->face_id = it->face_id;
1581 glyph->u.img_id = img->id;
1582 ++it->glyph_row->used[area];
1583 }
1584 }
1585 }
1586
1587
1588 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1589 of the glyph, WIDTH and HEIGHT are the width and height of the
1590 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1591 ascent of the glyph (0 <= ASCENT <= 1). */
1592
1593 static void
1594 x_append_stretch_glyph (it, object, width, height, ascent)
1595 struct it *it;
1596 Lisp_Object object;
1597 int width, height;
1598 double ascent;
1599 {
1600 struct glyph *glyph;
1601 enum glyph_row_area area = it->area;
1602
1603 xassert (ascent >= 0 && ascent <= 1);
1604
1605 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1606 if (glyph < it->glyph_row->glyphs[area + 1])
1607 {
1608 glyph->charpos = CHARPOS (it->position);
1609 glyph->object = object;
1610 glyph->pixel_width = width;
1611 glyph->voffset = it->voffset;
1612 glyph->type = STRETCH_GLYPH;
1613 glyph->multibyte_p = it->multibyte_p;
1614 glyph->left_box_line_p = it->start_of_box_run_p;
1615 glyph->right_box_line_p = it->end_of_box_run_p;
1616 glyph->overlaps_vertically_p = 0;
1617 glyph->padding_p = 0;
1618 glyph->glyph_not_available_p = 0;
1619 glyph->face_id = it->face_id;
1620 glyph->u.stretch.ascent = height * ascent;
1621 glyph->u.stretch.height = height;
1622 ++it->glyph_row->used[area];
1623 }
1624 }
1625
1626
1627 /* Produce a stretch glyph for iterator IT. IT->object is the value
1628 of the glyph property displayed. The value must be a list
1629 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1630 being recognized:
1631
1632 1. `:width WIDTH' specifies that the space should be WIDTH *
1633 canonical char width wide. WIDTH may be an integer or floating
1634 point number.
1635
1636 2. `:relative-width FACTOR' specifies that the width of the stretch
1637 should be computed from the width of the first character having the
1638 `glyph' property, and should be FACTOR times that width.
1639
1640 3. `:align-to HPOS' specifies that the space should be wide enough
1641 to reach HPOS, a value in canonical character units.
1642
1643 Exactly one of the above pairs must be present.
1644
1645 4. `:height HEIGHT' specifies that the height of the stretch produced
1646 should be HEIGHT, measured in canonical character units.
1647
1648 5. `:relative-height FACTOR' specifies that the height of the
1649 stretch should be FACTOR times the height of the characters having
1650 the glyph property.
1651
1652 Either none or exactly one of 4 or 5 must be present.
1653
1654 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1655 of the stretch should be used for the ascent of the stretch.
1656 ASCENT must be in the range 0 <= ASCENT <= 100. */
1657
1658 #define NUMVAL(X) \
1659 ((INTEGERP (X) || FLOATP (X)) \
1660 ? XFLOATINT (X) \
1661 : - 1)
1662
1663
1664 static void
1665 x_produce_stretch_glyph (it)
1666 struct it *it;
1667 {
1668 /* (space :width WIDTH :height HEIGHT. */
1669 #if GLYPH_DEBUG
1670 extern Lisp_Object Qspace;
1671 #endif
1672 extern Lisp_Object QCwidth, QCheight, QCascent;
1673 extern Lisp_Object QCrelative_width, QCrelative_height;
1674 extern Lisp_Object QCalign_to;
1675 Lisp_Object prop, plist;
1676 double width = 0, height = 0, ascent = 0;
1677 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1678 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1679
1680 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1681
1682 /* List should start with `space'. */
1683 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1684 plist = XCDR (it->object);
1685
1686 /* Compute the width of the stretch. */
1687 if (prop = Fplist_get (plist, QCwidth),
1688 NUMVAL (prop) > 0)
1689 /* Absolute width `:width WIDTH' specified and valid. */
1690 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1691 else if (prop = Fplist_get (plist, QCrelative_width),
1692 NUMVAL (prop) > 0)
1693 {
1694 /* Relative width `:relative-width FACTOR' specified and valid.
1695 Compute the width of the characters having the `glyph'
1696 property. */
1697 struct it it2;
1698 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1699
1700 it2 = *it;
1701 if (it->multibyte_p)
1702 {
1703 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1704 - IT_BYTEPOS (*it));
1705 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1706 }
1707 else
1708 it2.c = *p, it2.len = 1;
1709
1710 it2.glyph_row = NULL;
1711 it2.what = IT_CHARACTER;
1712 x_produce_glyphs (&it2);
1713 width = NUMVAL (prop) * it2.pixel_width;
1714 }
1715 else if (prop = Fplist_get (plist, QCalign_to),
1716 NUMVAL (prop) > 0)
1717 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1718 else
1719 /* Nothing specified -> width defaults to canonical char width. */
1720 width = CANON_X_UNIT (it->f);
1721
1722 /* Compute height. */
1723 if (prop = Fplist_get (plist, QCheight),
1724 NUMVAL (prop) > 0)
1725 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1726 else if (prop = Fplist_get (plist, QCrelative_height),
1727 NUMVAL (prop) > 0)
1728 height = FONT_HEIGHT (font) * NUMVAL (prop);
1729 else
1730 height = FONT_HEIGHT (font);
1731
1732 /* Compute percentage of height used for ascent. If
1733 `:ascent ASCENT' is present and valid, use that. Otherwise,
1734 derive the ascent from the font in use. */
1735 if (prop = Fplist_get (plist, QCascent),
1736 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1737 ascent = NUMVAL (prop) / 100.0;
1738 else
1739 ascent = (double) font->ascent / FONT_HEIGHT (font);
1740
1741 if (width <= 0)
1742 width = 1;
1743 if (height <= 0)
1744 height = 1;
1745
1746 if (it->glyph_row)
1747 {
1748 Lisp_Object object = it->stack[it->sp - 1].string;
1749 if (!STRINGP (object))
1750 object = it->w->buffer;
1751 x_append_stretch_glyph (it, object, width, height, ascent);
1752 }
1753
1754 it->pixel_width = width;
1755 it->ascent = it->phys_ascent = height * ascent;
1756 it->descent = it->phys_descent = height - it->ascent;
1757 it->nglyphs = 1;
1758
1759 if (face->box != FACE_NO_BOX)
1760 {
1761 if (face->box_line_width > 0)
1762 {
1763 it->ascent += face->box_line_width;
1764 it->descent += face->box_line_width;
1765 }
1766
1767 if (it->start_of_box_run_p)
1768 it->pixel_width += abs (face->box_line_width);
1769 if (it->end_of_box_run_p)
1770 it->pixel_width += abs (face->box_line_width);
1771 }
1772
1773 take_vertical_position_into_account (it);
1774 }
1775
1776 /* Return proper value to be used as baseline offset of font that has
1777 ASCENT and DESCENT to draw characters by the font at the vertical
1778 center of the line of frame F.
1779
1780 Here, out task is to find the value of BOFF in the following figure;
1781
1782 -------------------------+-----------+-
1783 -+-+---------+-+ | |
1784 | | | | | |
1785 | | | | F_ASCENT F_HEIGHT
1786 | | | ASCENT | |
1787 HEIGHT | | | | |
1788 | | |-|-+------+-----------|------- baseline
1789 | | | | BOFF | |
1790 | |---------|-+-+ | |
1791 | | | DESCENT | |
1792 -+-+---------+-+ F_DESCENT |
1793 -------------------------+-----------+-
1794
1795 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1796 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1797 DESCENT = FONT->descent
1798 HEIGHT = FONT_HEIGHT (FONT)
1799 F_DESCENT = (F->output_data.x->font->descent
1800 - F->output_data.x->baseline_offset)
1801 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1802 */
1803
1804 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1805 ((FONT)->descent \
1806 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1807 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1808 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1809
1810 /* Produce glyphs/get display metrics for the display element IT is
1811 loaded with. See the description of struct display_iterator in
1812 dispextern.h for an overview of struct display_iterator. */
1813
1814 static void
1815 x_produce_glyphs (it)
1816 struct it *it;
1817 {
1818 it->glyph_not_available_p = 0;
1819
1820 if (it->what == IT_CHARACTER)
1821 {
1822 XChar2b char2b;
1823 XFontStruct *font;
1824 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1825 XCharStruct *pcm;
1826 int font_not_found_p;
1827 struct font_info *font_info;
1828 int boff; /* baseline offset */
1829 /* We may change it->multibyte_p upon unibyte<->multibyte
1830 conversion. So, save the current value now and restore it
1831 later.
1832
1833 Note: It seems that we don't have to record multibyte_p in
1834 struct glyph because the character code itself tells if or
1835 not the character is multibyte. Thus, in the future, we must
1836 consider eliminating the field `multibyte_p' in the struct
1837 glyph. */
1838 int saved_multibyte_p = it->multibyte_p;
1839
1840 /* Maybe translate single-byte characters to multibyte, or the
1841 other way. */
1842 it->char_to_display = it->c;
1843 if (!ASCII_BYTE_P (it->c))
1844 {
1845 if (unibyte_display_via_language_environment
1846 && SINGLE_BYTE_CHAR_P (it->c)
1847 && (it->c >= 0240
1848 || !NILP (Vnonascii_translation_table)))
1849 {
1850 it->char_to_display = unibyte_char_to_multibyte (it->c);
1851 it->multibyte_p = 1;
1852 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1853 face = FACE_FROM_ID (it->f, it->face_id);
1854 }
1855 else if (!SINGLE_BYTE_CHAR_P (it->c)
1856 && !it->multibyte_p)
1857 {
1858 it->multibyte_p = 1;
1859 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1860 face = FACE_FROM_ID (it->f, it->face_id);
1861 }
1862 }
1863
1864 /* Get font to use. Encode IT->char_to_display. */
1865 x_get_char_face_and_encoding (it->f, it->char_to_display,
1866 it->face_id, &char2b,
1867 it->multibyte_p, 0);
1868 font = face->font;
1869
1870 /* When no suitable font found, use the default font. */
1871 font_not_found_p = font == NULL;
1872 if (font_not_found_p)
1873 {
1874 font = FRAME_FONT (it->f);
1875 boff = it->f->output_data.x->baseline_offset;
1876 font_info = NULL;
1877 }
1878 else
1879 {
1880 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1881 boff = font_info->baseline_offset;
1882 if (font_info->vertical_centering)
1883 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1884 }
1885
1886 if (it->char_to_display >= ' '
1887 && (!it->multibyte_p || it->char_to_display < 128))
1888 {
1889 /* Either unibyte or ASCII. */
1890 int stretched_p;
1891
1892 it->nglyphs = 1;
1893
1894 pcm = x_per_char_metric (font, &char2b);
1895 it->ascent = font->ascent + boff;
1896 it->descent = font->descent - boff;
1897
1898 if (pcm)
1899 {
1900 it->phys_ascent = pcm->ascent + boff;
1901 it->phys_descent = pcm->descent - boff;
1902 it->pixel_width = pcm->width;
1903 }
1904 else
1905 {
1906 it->glyph_not_available_p = 1;
1907 it->phys_ascent = font->ascent + boff;
1908 it->phys_descent = font->descent - boff;
1909 it->pixel_width = FONT_WIDTH (font);
1910 }
1911
1912 /* If this is a space inside a region of text with
1913 `space-width' property, change its width. */
1914 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1915 if (stretched_p)
1916 it->pixel_width *= XFLOATINT (it->space_width);
1917
1918 /* If face has a box, add the box thickness to the character
1919 height. If character has a box line to the left and/or
1920 right, add the box line width to the character's width. */
1921 if (face->box != FACE_NO_BOX)
1922 {
1923 int thick = face->box_line_width;
1924
1925 if (thick > 0)
1926 {
1927 it->ascent += thick;
1928 it->descent += thick;
1929 }
1930 else
1931 thick = -thick;
1932
1933 if (it->start_of_box_run_p)
1934 it->pixel_width += thick;
1935 if (it->end_of_box_run_p)
1936 it->pixel_width += thick;
1937 }
1938
1939 /* If face has an overline, add the height of the overline
1940 (1 pixel) and a 1 pixel margin to the character height. */
1941 if (face->overline_p)
1942 it->ascent += 2;
1943
1944 take_vertical_position_into_account (it);
1945
1946 /* If we have to actually produce glyphs, do it. */
1947 if (it->glyph_row)
1948 {
1949 if (stretched_p)
1950 {
1951 /* Translate a space with a `space-width' property
1952 into a stretch glyph. */
1953 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1954 x_append_stretch_glyph (it, it->object, it->pixel_width,
1955 it->ascent + it->descent, ascent);
1956 }
1957 else
1958 x_append_glyph (it);
1959
1960 /* If characters with lbearing or rbearing are displayed
1961 in this line, record that fact in a flag of the
1962 glyph row. This is used to optimize X output code. */
1963 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1964 it->glyph_row->contains_overlapping_glyphs_p = 1;
1965 }
1966 }
1967 else if (it->char_to_display == '\n')
1968 {
1969 /* A newline has no width but we need the height of the line. */
1970 it->pixel_width = 0;
1971 it->nglyphs = 0;
1972 it->ascent = it->phys_ascent = font->ascent + boff;
1973 it->descent = it->phys_descent = font->descent - boff;
1974
1975 if (face->box != FACE_NO_BOX
1976 && face->box_line_width > 0)
1977 {
1978 it->ascent += face->box_line_width;
1979 it->descent += face->box_line_width;
1980 }
1981 }
1982 else if (it->char_to_display == '\t')
1983 {
1984 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1985 int x = it->current_x + it->continuation_lines_width;
1986 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1987
1988 /* If the distance from the current position to the next tab
1989 stop is less than a canonical character width, use the
1990 tab stop after that. */
1991 if (next_tab_x - x < CANON_X_UNIT (it->f))
1992 next_tab_x += tab_width;
1993
1994 it->pixel_width = next_tab_x - x;
1995 it->nglyphs = 1;
1996 it->ascent = it->phys_ascent = font->ascent + boff;
1997 it->descent = it->phys_descent = font->descent - boff;
1998
1999 if (it->glyph_row)
2000 {
2001 double ascent = (double) it->ascent / (it->ascent + it->descent);
2002 x_append_stretch_glyph (it, it->object, it->pixel_width,
2003 it->ascent + it->descent, ascent);
2004 }
2005 }
2006 else
2007 {
2008 /* A multi-byte character. Assume that the display width of the
2009 character is the width of the character multiplied by the
2010 width of the font. */
2011
2012 /* If we found a font, this font should give us the right
2013 metrics. If we didn't find a font, use the frame's
2014 default font and calculate the width of the character
2015 from the charset width; this is what old redisplay code
2016 did. */
2017 pcm = x_per_char_metric (font, &char2b);
2018 if (font_not_found_p || !pcm)
2019 {
2020 int charset = CHAR_CHARSET (it->char_to_display);
2021
2022 it->glyph_not_available_p = 1;
2023 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2024 * CHARSET_WIDTH (charset));
2025 it->phys_ascent = font->ascent + boff;
2026 it->phys_descent = font->descent - boff;
2027 }
2028 else
2029 {
2030 it->pixel_width = pcm->width;
2031 it->phys_ascent = pcm->ascent + boff;
2032 it->phys_descent = pcm->descent - boff;
2033 if (it->glyph_row
2034 && (pcm->lbearing < 0
2035 || pcm->rbearing > pcm->width))
2036 it->glyph_row->contains_overlapping_glyphs_p = 1;
2037 }
2038 it->nglyphs = 1;
2039 it->ascent = font->ascent + boff;
2040 it->descent = font->descent - boff;
2041 if (face->box != FACE_NO_BOX)
2042 {
2043 int thick = face->box_line_width;
2044
2045 if (thick > 0)
2046 {
2047 it->ascent += thick;
2048 it->descent += thick;
2049 }
2050 else
2051 thick = - thick;
2052
2053 if (it->start_of_box_run_p)
2054 it->pixel_width += thick;
2055 if (it->end_of_box_run_p)
2056 it->pixel_width += thick;
2057 }
2058
2059 /* If face has an overline, add the height of the overline
2060 (1 pixel) and a 1 pixel margin to the character height. */
2061 if (face->overline_p)
2062 it->ascent += 2;
2063
2064 take_vertical_position_into_account (it);
2065
2066 if (it->glyph_row)
2067 x_append_glyph (it);
2068 }
2069 it->multibyte_p = saved_multibyte_p;
2070 }
2071 else if (it->what == IT_COMPOSITION)
2072 {
2073 /* Note: A composition is represented as one glyph in the
2074 glyph matrix. There are no padding glyphs. */
2075 XChar2b char2b;
2076 XFontStruct *font;
2077 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2078 XCharStruct *pcm;
2079 int font_not_found_p;
2080 struct font_info *font_info;
2081 int boff; /* baseline offset */
2082 struct composition *cmp = composition_table[it->cmp_id];
2083
2084 /* Maybe translate single-byte characters to multibyte. */
2085 it->char_to_display = it->c;
2086 if (unibyte_display_via_language_environment
2087 && SINGLE_BYTE_CHAR_P (it->c)
2088 && (it->c >= 0240
2089 || (it->c >= 0200
2090 && !NILP (Vnonascii_translation_table))))
2091 {
2092 it->char_to_display = unibyte_char_to_multibyte (it->c);
2093 }
2094
2095 /* Get face and font to use. Encode IT->char_to_display. */
2096 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2097 face = FACE_FROM_ID (it->f, it->face_id);
2098 x_get_char_face_and_encoding (it->f, it->char_to_display,
2099 it->face_id, &char2b, it->multibyte_p, 0);
2100 font = face->font;
2101
2102 /* When no suitable font found, use the default font. */
2103 font_not_found_p = font == NULL;
2104 if (font_not_found_p)
2105 {
2106 font = FRAME_FONT (it->f);
2107 boff = it->f->output_data.x->baseline_offset;
2108 font_info = NULL;
2109 }
2110 else
2111 {
2112 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2113 boff = font_info->baseline_offset;
2114 if (font_info->vertical_centering)
2115 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2116 }
2117
2118 /* There are no padding glyphs, so there is only one glyph to
2119 produce for the composition. Important is that pixel_width,
2120 ascent and descent are the values of what is drawn by
2121 draw_glyphs (i.e. the values of the overall glyphs composed). */
2122 it->nglyphs = 1;
2123
2124 /* If we have not yet calculated pixel size data of glyphs of
2125 the composition for the current face font, calculate them
2126 now. Theoretically, we have to check all fonts for the
2127 glyphs, but that requires much time and memory space. So,
2128 here we check only the font of the first glyph. This leads
2129 to incorrect display very rarely, and C-l (recenter) can
2130 correct the display anyway. */
2131 if (cmp->font != (void *) font)
2132 {
2133 /* Ascent and descent of the font of the first character of
2134 this composition (adjusted by baseline offset). Ascent
2135 and descent of overall glyphs should not be less than
2136 them respectively. */
2137 int font_ascent = font->ascent + boff;
2138 int font_descent = font->descent - boff;
2139 /* Bounding box of the overall glyphs. */
2140 int leftmost, rightmost, lowest, highest;
2141 int i, width, ascent, descent;
2142
2143 cmp->font = (void *) font;
2144
2145 /* Initialize the bounding box. */
2146 if (font_info
2147 && (pcm = x_per_char_metric (font, &char2b)))
2148 {
2149 width = pcm->width;
2150 ascent = pcm->ascent;
2151 descent = pcm->descent;
2152 }
2153 else
2154 {
2155 width = FONT_WIDTH (font);
2156 ascent = font->ascent;
2157 descent = font->descent;
2158 }
2159
2160 rightmost = width;
2161 lowest = - descent + boff;
2162 highest = ascent + boff;
2163 leftmost = 0;
2164
2165 if (font_info
2166 && font_info->default_ascent
2167 && CHAR_TABLE_P (Vuse_default_ascent)
2168 && !NILP (Faref (Vuse_default_ascent,
2169 make_number (it->char_to_display))))
2170 highest = font_info->default_ascent + boff;
2171
2172 /* Draw the first glyph at the normal position. It may be
2173 shifted to right later if some other glyphs are drawn at
2174 the left. */
2175 cmp->offsets[0] = 0;
2176 cmp->offsets[1] = boff;
2177
2178 /* Set cmp->offsets for the remaining glyphs. */
2179 for (i = 1; i < cmp->glyph_len; i++)
2180 {
2181 int left, right, btm, top;
2182 int ch = COMPOSITION_GLYPH (cmp, i);
2183 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2184
2185 face = FACE_FROM_ID (it->f, face_id);
2186 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2187 it->multibyte_p, 0);
2188 font = face->font;
2189 if (font == NULL)
2190 {
2191 font = FRAME_FONT (it->f);
2192 boff = it->f->output_data.x->baseline_offset;
2193 font_info = NULL;
2194 }
2195 else
2196 {
2197 font_info
2198 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2199 boff = font_info->baseline_offset;
2200 if (font_info->vertical_centering)
2201 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2202 }
2203
2204 if (font_info
2205 && (pcm = x_per_char_metric (font, &char2b)))
2206 {
2207 width = pcm->width;
2208 ascent = pcm->ascent;
2209 descent = pcm->descent;
2210 }
2211 else
2212 {
2213 width = FONT_WIDTH (font);
2214 ascent = 1;
2215 descent = 0;
2216 }
2217
2218 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2219 {
2220 /* Relative composition with or without
2221 alternate chars. */
2222 left = (leftmost + rightmost - width) / 2;
2223 btm = - descent + boff;
2224 if (font_info && font_info->relative_compose
2225 && (! CHAR_TABLE_P (Vignore_relative_composition)
2226 || NILP (Faref (Vignore_relative_composition,
2227 make_number (ch)))))
2228 {
2229
2230 if (- descent >= font_info->relative_compose)
2231 /* One extra pixel between two glyphs. */
2232 btm = highest + 1;
2233 else if (ascent <= 0)
2234 /* One extra pixel between two glyphs. */
2235 btm = lowest - 1 - ascent - descent;
2236 }
2237 }
2238 else
2239 {
2240 /* A composition rule is specified by an integer
2241 value that encodes global and new reference
2242 points (GREF and NREF). GREF and NREF are
2243 specified by numbers as below:
2244
2245 0---1---2 -- ascent
2246 | |
2247 | |
2248 | |
2249 9--10--11 -- center
2250 | |
2251 ---3---4---5--- baseline
2252 | |
2253 6---7---8 -- descent
2254 */
2255 int rule = COMPOSITION_RULE (cmp, i);
2256 int gref, nref, grefx, grefy, nrefx, nrefy;
2257
2258 COMPOSITION_DECODE_RULE (rule, gref, nref);
2259 grefx = gref % 3, nrefx = nref % 3;
2260 grefy = gref / 3, nrefy = nref / 3;
2261
2262 left = (leftmost
2263 + grefx * (rightmost - leftmost) / 2
2264 - nrefx * width / 2);
2265 btm = ((grefy == 0 ? highest
2266 : grefy == 1 ? 0
2267 : grefy == 2 ? lowest
2268 : (highest + lowest) / 2)
2269 - (nrefy == 0 ? ascent + descent
2270 : nrefy == 1 ? descent - boff
2271 : nrefy == 2 ? 0
2272 : (ascent + descent) / 2));
2273 }
2274
2275 cmp->offsets[i * 2] = left;
2276 cmp->offsets[i * 2 + 1] = btm + descent;
2277
2278 /* Update the bounding box of the overall glyphs. */
2279 right = left + width;
2280 top = btm + descent + ascent;
2281 if (left < leftmost)
2282 leftmost = left;
2283 if (right > rightmost)
2284 rightmost = right;
2285 if (top > highest)
2286 highest = top;
2287 if (btm < lowest)
2288 lowest = btm;
2289 }
2290
2291 /* If there are glyphs whose x-offsets are negative,
2292 shift all glyphs to the right and make all x-offsets
2293 non-negative. */
2294 if (leftmost < 0)
2295 {
2296 for (i = 0; i < cmp->glyph_len; i++)
2297 cmp->offsets[i * 2] -= leftmost;
2298 rightmost -= leftmost;
2299 }
2300
2301 cmp->pixel_width = rightmost;
2302 cmp->ascent = highest;
2303 cmp->descent = - lowest;
2304 if (cmp->ascent < font_ascent)
2305 cmp->ascent = font_ascent;
2306 if (cmp->descent < font_descent)
2307 cmp->descent = font_descent;
2308 }
2309
2310 it->pixel_width = cmp->pixel_width;
2311 it->ascent = it->phys_ascent = cmp->ascent;
2312 it->descent = it->phys_descent = cmp->descent;
2313
2314 if (face->box != FACE_NO_BOX)
2315 {
2316 int thick = face->box_line_width;
2317
2318 if (thick > 0)
2319 {
2320 it->ascent += thick;
2321 it->descent += thick;
2322 }
2323 else
2324 thick = - thick;
2325
2326 if (it->start_of_box_run_p)
2327 it->pixel_width += thick;
2328 if (it->end_of_box_run_p)
2329 it->pixel_width += thick;
2330 }
2331
2332 /* If face has an overline, add the height of the overline
2333 (1 pixel) and a 1 pixel margin to the character height. */
2334 if (face->overline_p)
2335 it->ascent += 2;
2336
2337 take_vertical_position_into_account (it);
2338
2339 if (it->glyph_row)
2340 x_append_composite_glyph (it);
2341 }
2342 else if (it->what == IT_IMAGE)
2343 x_produce_image_glyph (it);
2344 else if (it->what == IT_STRETCH)
2345 x_produce_stretch_glyph (it);
2346
2347 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2348 because this isn't true for images with `:ascent 100'. */
2349 xassert (it->ascent >= 0 && it->descent >= 0);
2350 if (it->area == TEXT_AREA)
2351 it->current_x += it->pixel_width;
2352
2353 it->descent += it->extra_line_spacing;
2354
2355 it->max_ascent = max (it->max_ascent, it->ascent);
2356 it->max_descent = max (it->max_descent, it->descent);
2357 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2358 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2359 }
2360
2361
2362 /* Estimate the pixel height of the mode or top line on frame F.
2363 FACE_ID specifies what line's height to estimate. */
2364
2365 int
2366 x_estimate_mode_line_height (f, face_id)
2367 struct frame *f;
2368 enum face_id face_id;
2369 {
2370 int height = FONT_HEIGHT (FRAME_FONT (f));
2371
2372 /* This function is called so early when Emacs starts that the face
2373 cache and mode line face are not yet initialized. */
2374 if (FRAME_FACE_CACHE (f))
2375 {
2376 struct face *face = FACE_FROM_ID (f, face_id);
2377 if (face)
2378 {
2379 if (face->font)
2380 height = FONT_HEIGHT (face->font);
2381 if (face->box_line_width > 0)
2382 height += 2 * face->box_line_width;
2383 }
2384 }
2385
2386 return height;
2387 }
2388
2389 \f
2390 /***********************************************************************
2391 Glyph display
2392 ***********************************************************************/
2393
2394 /* A sequence of glyphs to be drawn in the same face.
2395
2396 This data structure is not really completely X specific, so it
2397 could possibly, at least partially, be useful for other systems. It
2398 is currently not part of the external redisplay interface because
2399 it's not clear what other systems will need. */
2400
2401 struct glyph_string
2402 {
2403 /* X-origin of the string. */
2404 int x;
2405
2406 /* Y-origin and y-position of the base line of this string. */
2407 int y, ybase;
2408
2409 /* The width of the string, not including a face extension. */
2410 int width;
2411
2412 /* The width of the string, including a face extension. */
2413 int background_width;
2414
2415 /* The height of this string. This is the height of the line this
2416 string is drawn in, and can be different from the height of the
2417 font the string is drawn in. */
2418 int height;
2419
2420 /* Number of pixels this string overwrites in front of its x-origin.
2421 This number is zero if the string has an lbearing >= 0; it is
2422 -lbearing, if the string has an lbearing < 0. */
2423 int left_overhang;
2424
2425 /* Number of pixels this string overwrites past its right-most
2426 nominal x-position, i.e. x + width. Zero if the string's
2427 rbearing is <= its nominal width, rbearing - width otherwise. */
2428 int right_overhang;
2429
2430 /* The frame on which the glyph string is drawn. */
2431 struct frame *f;
2432
2433 /* The window on which the glyph string is drawn. */
2434 struct window *w;
2435
2436 /* X display and window for convenience. */
2437 Display *display;
2438 Window window;
2439
2440 /* The glyph row for which this string was built. It determines the
2441 y-origin and height of the string. */
2442 struct glyph_row *row;
2443
2444 /* The area within row. */
2445 enum glyph_row_area area;
2446
2447 /* Characters to be drawn, and number of characters. */
2448 XChar2b *char2b;
2449 int nchars;
2450
2451 /* A face-override for drawing cursors, mouse face and similar. */
2452 enum draw_glyphs_face hl;
2453
2454 /* Face in which this string is to be drawn. */
2455 struct face *face;
2456
2457 /* Font in which this string is to be drawn. */
2458 XFontStruct *font;
2459
2460 /* Font info for this string. */
2461 struct font_info *font_info;
2462
2463 /* Non-null means this string describes (part of) a composition.
2464 All characters from char2b are drawn composed. */
2465 struct composition *cmp;
2466
2467 /* Index of this glyph string's first character in the glyph
2468 definition of CMP. If this is zero, this glyph string describes
2469 the first character of a composition. */
2470 int gidx;
2471
2472 /* 1 means this glyph strings face has to be drawn to the right end
2473 of the window's drawing area. */
2474 unsigned extends_to_end_of_line_p : 1;
2475
2476 /* 1 means the background of this string has been drawn. */
2477 unsigned background_filled_p : 1;
2478
2479 /* 1 means glyph string must be drawn with 16-bit functions. */
2480 unsigned two_byte_p : 1;
2481
2482 /* 1 means that the original font determined for drawing this glyph
2483 string could not be loaded. The member `font' has been set to
2484 the frame's default font in this case. */
2485 unsigned font_not_found_p : 1;
2486
2487 /* 1 means that the face in which this glyph string is drawn has a
2488 stipple pattern. */
2489 unsigned stippled_p : 1;
2490
2491 /* 1 means only the foreground of this glyph string must be drawn,
2492 and we should use the physical height of the line this glyph
2493 string appears in as clip rect. */
2494 unsigned for_overlaps_p : 1;
2495
2496 /* The GC to use for drawing this glyph string. */
2497 GC gc;
2498
2499 /* A pointer to the first glyph in the string. This glyph
2500 corresponds to char2b[0]. Needed to draw rectangles if
2501 font_not_found_p is 1. */
2502 struct glyph *first_glyph;
2503
2504 /* Image, if any. */
2505 struct image *img;
2506
2507 struct glyph_string *next, *prev;
2508 };
2509
2510
2511 #if GLYPH_DEBUG
2512
2513 static void
2514 x_dump_glyph_string (s)
2515 struct glyph_string *s;
2516 {
2517 fprintf (stderr, "glyph string\n");
2518 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2519 s->x, s->y, s->width, s->height);
2520 fprintf (stderr, " ybase = %d\n", s->ybase);
2521 fprintf (stderr, " hl = %d\n", s->hl);
2522 fprintf (stderr, " left overhang = %d, right = %d\n",
2523 s->left_overhang, s->right_overhang);
2524 fprintf (stderr, " nchars = %d\n", s->nchars);
2525 fprintf (stderr, " extends to end of line = %d\n",
2526 s->extends_to_end_of_line_p);
2527 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2528 fprintf (stderr, " bg width = %d\n", s->background_width);
2529 }
2530
2531 #endif /* GLYPH_DEBUG */
2532
2533
2534
2535 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2536 struct glyph_string **,
2537 struct glyph_string *,
2538 struct glyph_string *));
2539 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2540 struct glyph_string **,
2541 struct glyph_string *,
2542 struct glyph_string *));
2543 static void x_append_glyph_string P_ ((struct glyph_string **,
2544 struct glyph_string **,
2545 struct glyph_string *));
2546 static int x_left_overwritten P_ ((struct glyph_string *));
2547 static int x_left_overwriting P_ ((struct glyph_string *));
2548 static int x_right_overwritten P_ ((struct glyph_string *));
2549 static int x_right_overwriting P_ ((struct glyph_string *));
2550 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2551 int));
2552 static void x_init_glyph_string P_ ((struct glyph_string *,
2553 XChar2b *, struct window *,
2554 struct glyph_row *,
2555 enum glyph_row_area, int,
2556 enum draw_glyphs_face));
2557 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2558 enum glyph_row_area, int, int,
2559 enum draw_glyphs_face, int));
2560 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2561 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2562 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2563 int));
2564 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2565 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2566 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2567 static void x_draw_glyph_string P_ ((struct glyph_string *));
2568 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2569 static void x_set_cursor_gc P_ ((struct glyph_string *));
2570 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2571 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2572 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2573 int *, int *));
2574 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2575 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2576 unsigned long *, double, int));
2577 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2578 double, int, unsigned long));
2579 static void x_setup_relief_colors P_ ((struct glyph_string *));
2580 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2581 static void x_draw_image_relief P_ ((struct glyph_string *));
2582 static void x_draw_image_foreground P_ ((struct glyph_string *));
2583 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2584 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2585 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2586 int, int, int));
2587 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2588 int, int, int, int, XRectangle *));
2589 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2590 int, int, int, XRectangle *));
2591 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2592 enum glyph_row_area));
2593 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2594 struct glyph_row *,
2595 enum glyph_row_area, int, int));
2596
2597 #if GLYPH_DEBUG
2598 static void x_check_font P_ ((struct frame *, XFontStruct *));
2599 #endif
2600
2601
2602 /* Append the list of glyph strings with head H and tail T to the list
2603 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2604
2605 static INLINE void
2606 x_append_glyph_string_lists (head, tail, h, t)
2607 struct glyph_string **head, **tail;
2608 struct glyph_string *h, *t;
2609 {
2610 if (h)
2611 {
2612 if (*head)
2613 (*tail)->next = h;
2614 else
2615 *head = h;
2616 h->prev = *tail;
2617 *tail = t;
2618 }
2619 }
2620
2621
2622 /* Prepend the list of glyph strings with head H and tail T to the
2623 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2624 result. */
2625
2626 static INLINE void
2627 x_prepend_glyph_string_lists (head, tail, h, t)
2628 struct glyph_string **head, **tail;
2629 struct glyph_string *h, *t;
2630 {
2631 if (h)
2632 {
2633 if (*head)
2634 (*head)->prev = t;
2635 else
2636 *tail = t;
2637 t->next = *head;
2638 *head = h;
2639 }
2640 }
2641
2642
2643 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2644 Set *HEAD and *TAIL to the resulting list. */
2645
2646 static INLINE void
2647 x_append_glyph_string (head, tail, s)
2648 struct glyph_string **head, **tail;
2649 struct glyph_string *s;
2650 {
2651 s->next = s->prev = NULL;
2652 x_append_glyph_string_lists (head, tail, s, s);
2653 }
2654
2655
2656 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2657 face. */
2658
2659 static void
2660 x_set_cursor_gc (s)
2661 struct glyph_string *s;
2662 {
2663 if (s->font == FRAME_FONT (s->f)
2664 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2665 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2666 && !s->cmp)
2667 s->gc = s->f->output_data.x->cursor_gc;
2668 else
2669 {
2670 /* Cursor on non-default face: must merge. */
2671 XGCValues xgcv;
2672 unsigned long mask;
2673
2674 xgcv.background = s->f->output_data.x->cursor_pixel;
2675 xgcv.foreground = s->face->background;
2676
2677 /* If the glyph would be invisible, try a different foreground. */
2678 if (xgcv.foreground == xgcv.background)
2679 xgcv.foreground = s->face->foreground;
2680 if (xgcv.foreground == xgcv.background)
2681 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2682 if (xgcv.foreground == xgcv.background)
2683 xgcv.foreground = s->face->foreground;
2684
2685 /* Make sure the cursor is distinct from text in this face. */
2686 if (xgcv.background == s->face->background
2687 && xgcv.foreground == s->face->foreground)
2688 {
2689 xgcv.background = s->face->foreground;
2690 xgcv.foreground = s->face->background;
2691 }
2692
2693 IF_DEBUG (x_check_font (s->f, s->font));
2694 xgcv.font = s->font->fid;
2695 xgcv.graphics_exposures = False;
2696 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2697
2698 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2699 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2700 mask, &xgcv);
2701 else
2702 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2703 = XCreateGC (s->display, s->window, mask, &xgcv);
2704
2705 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2706 }
2707 }
2708
2709
2710 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2711
2712 static void
2713 x_set_mouse_face_gc (s)
2714 struct glyph_string *s;
2715 {
2716 int face_id;
2717 struct face *face;
2718
2719 /* What face has to be used last for the mouse face? */
2720 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2721 face = FACE_FROM_ID (s->f, face_id);
2722 if (face == NULL)
2723 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2724
2725 if (s->first_glyph->type == CHAR_GLYPH)
2726 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2727 else
2728 face_id = FACE_FOR_CHAR (s->f, face, 0);
2729 s->face = FACE_FROM_ID (s->f, face_id);
2730 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2731
2732 /* If font in this face is same as S->font, use it. */
2733 if (s->font == s->face->font)
2734 s->gc = s->face->gc;
2735 else
2736 {
2737 /* Otherwise construct scratch_cursor_gc with values from FACE
2738 but font FONT. */
2739 XGCValues xgcv;
2740 unsigned long mask;
2741
2742 xgcv.background = s->face->background;
2743 xgcv.foreground = s->face->foreground;
2744 IF_DEBUG (x_check_font (s->f, s->font));
2745 xgcv.font = s->font->fid;
2746 xgcv.graphics_exposures = False;
2747 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2748
2749 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2750 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2751 mask, &xgcv);
2752 else
2753 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2754 = XCreateGC (s->display, s->window, mask, &xgcv);
2755
2756 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2757 }
2758
2759 xassert (s->gc != 0);
2760 }
2761
2762
2763 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2764 Faces to use in the mode line have already been computed when the
2765 matrix was built, so there isn't much to do, here. */
2766
2767 static INLINE void
2768 x_set_mode_line_face_gc (s)
2769 struct glyph_string *s;
2770 {
2771 s->gc = s->face->gc;
2772 }
2773
2774
2775 /* Set S->gc of glyph string S for drawing that glyph string. Set
2776 S->stippled_p to a non-zero value if the face of S has a stipple
2777 pattern. */
2778
2779 static INLINE void
2780 x_set_glyph_string_gc (s)
2781 struct glyph_string *s;
2782 {
2783 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2784
2785 if (s->hl == DRAW_NORMAL_TEXT)
2786 {
2787 s->gc = s->face->gc;
2788 s->stippled_p = s->face->stipple != 0;
2789 }
2790 else if (s->hl == DRAW_INVERSE_VIDEO)
2791 {
2792 x_set_mode_line_face_gc (s);
2793 s->stippled_p = s->face->stipple != 0;
2794 }
2795 else if (s->hl == DRAW_CURSOR)
2796 {
2797 x_set_cursor_gc (s);
2798 s->stippled_p = 0;
2799 }
2800 else if (s->hl == DRAW_MOUSE_FACE)
2801 {
2802 x_set_mouse_face_gc (s);
2803 s->stippled_p = s->face->stipple != 0;
2804 }
2805 else if (s->hl == DRAW_IMAGE_RAISED
2806 || s->hl == DRAW_IMAGE_SUNKEN)
2807 {
2808 s->gc = s->face->gc;
2809 s->stippled_p = s->face->stipple != 0;
2810 }
2811 else
2812 {
2813 s->gc = s->face->gc;
2814 s->stippled_p = s->face->stipple != 0;
2815 }
2816
2817 /* GC must have been set. */
2818 xassert (s->gc != 0);
2819 }
2820
2821
2822 /* Return in *R the clipping rectangle for glyph string S. */
2823
2824 static void
2825 x_get_glyph_string_clip_rect (s, r)
2826 struct glyph_string *s;
2827 XRectangle *r;
2828 {
2829 if (s->row->full_width_p)
2830 {
2831 /* Draw full-width. X coordinates are relative to S->w->left. */
2832 int canon_x = CANON_X_UNIT (s->f);
2833
2834 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2835 r->width = XFASTINT (s->w->width) * canon_x;
2836
2837 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2838 {
2839 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2840 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2841 r->x -= width;
2842 }
2843
2844 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2845
2846 /* Unless displaying a mode or menu bar line, which are always
2847 fully visible, clip to the visible part of the row. */
2848 if (s->w->pseudo_window_p)
2849 r->height = s->row->visible_height;
2850 else
2851 r->height = s->height;
2852 }
2853 else
2854 {
2855 /* This is a text line that may be partially visible. */
2856 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2857 r->width = window_box_width (s->w, s->area);
2858 r->height = s->row->visible_height;
2859 }
2860
2861 /* If S draws overlapping rows, it's sufficient to use the top and
2862 bottom of the window for clipping because this glyph string
2863 intentionally draws over other lines. */
2864 if (s->for_overlaps_p)
2865 {
2866 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2867 r->height = window_text_bottom_y (s->w) - r->y;
2868 }
2869 else
2870 {
2871 /* Don't use S->y for clipping because it doesn't take partially
2872 visible lines into account. For example, it can be negative for
2873 partially visible lines at the top of a window. */
2874 if (!s->row->full_width_p
2875 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2876 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2877 else
2878 r->y = max (0, s->row->y);
2879
2880 /* If drawing a tool-bar window, draw it over the internal border
2881 at the top of the window. */
2882 if (s->w == XWINDOW (s->f->tool_bar_window))
2883 r->y -= s->f->output_data.x->internal_border_width;
2884 }
2885
2886 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2887 }
2888
2889
2890 /* Set clipping for output of glyph string S. S may be part of a mode
2891 line or menu if we don't have X toolkit support. */
2892
2893 static INLINE void
2894 x_set_glyph_string_clipping (s)
2895 struct glyph_string *s;
2896 {
2897 XRectangle r;
2898 x_get_glyph_string_clip_rect (s, &r);
2899 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2900 }
2901
2902
2903 /* Compute left and right overhang of glyph string S. If S is a glyph
2904 string for a composition, assume overhangs don't exist. */
2905
2906 static INLINE void
2907 x_compute_glyph_string_overhangs (s)
2908 struct glyph_string *s;
2909 {
2910 if (s->cmp == NULL
2911 && s->first_glyph->type == CHAR_GLYPH)
2912 {
2913 XCharStruct cs;
2914 int direction, font_ascent, font_descent;
2915 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2916 &font_ascent, &font_descent, &cs);
2917 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2918 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2919 }
2920 }
2921
2922
2923 /* Compute overhangs and x-positions for glyph string S and its
2924 predecessors, or successors. X is the starting x-position for S.
2925 BACKWARD_P non-zero means process predecessors. */
2926
2927 static void
2928 x_compute_overhangs_and_x (s, x, backward_p)
2929 struct glyph_string *s;
2930 int x;
2931 int backward_p;
2932 {
2933 if (backward_p)
2934 {
2935 while (s)
2936 {
2937 x_compute_glyph_string_overhangs (s);
2938 x -= s->width;
2939 s->x = x;
2940 s = s->prev;
2941 }
2942 }
2943 else
2944 {
2945 while (s)
2946 {
2947 x_compute_glyph_string_overhangs (s);
2948 s->x = x;
2949 x += s->width;
2950 s = s->next;
2951 }
2952 }
2953 }
2954
2955
2956 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2957 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2958 assumed to be zero. */
2959
2960 static void
2961 x_get_glyph_overhangs (glyph, f, left, right)
2962 struct glyph *glyph;
2963 struct frame *f;
2964 int *left, *right;
2965 {
2966 *left = *right = 0;
2967
2968 if (glyph->type == CHAR_GLYPH)
2969 {
2970 XFontStruct *font;
2971 struct face *face;
2972 struct font_info *font_info;
2973 XChar2b char2b;
2974 XCharStruct *pcm;
2975
2976 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2977 font = face->font;
2978 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2979 if (font
2980 && (pcm = x_per_char_metric (font, &char2b)))
2981 {
2982 if (pcm->rbearing > pcm->width)
2983 *right = pcm->rbearing - pcm->width;
2984 if (pcm->lbearing < 0)
2985 *left = -pcm->lbearing;
2986 }
2987 }
2988 }
2989
2990
2991 /* Return the index of the first glyph preceding glyph string S that
2992 is overwritten by S because of S's left overhang. Value is -1
2993 if no glyphs are overwritten. */
2994
2995 static int
2996 x_left_overwritten (s)
2997 struct glyph_string *s;
2998 {
2999 int k;
3000
3001 if (s->left_overhang)
3002 {
3003 int x = 0, i;
3004 struct glyph *glyphs = s->row->glyphs[s->area];
3005 int first = s->first_glyph - glyphs;
3006
3007 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3008 x -= glyphs[i].pixel_width;
3009
3010 k = i + 1;
3011 }
3012 else
3013 k = -1;
3014
3015 return k;
3016 }
3017
3018
3019 /* Return the index of the first glyph preceding glyph string S that
3020 is overwriting S because of its right overhang. Value is -1 if no
3021 glyph in front of S overwrites S. */
3022
3023 static int
3024 x_left_overwriting (s)
3025 struct glyph_string *s;
3026 {
3027 int i, k, x;
3028 struct glyph *glyphs = s->row->glyphs[s->area];
3029 int first = s->first_glyph - glyphs;
3030
3031 k = -1;
3032 x = 0;
3033 for (i = first - 1; i >= 0; --i)
3034 {
3035 int left, right;
3036 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3037 if (x + right > 0)
3038 k = i;
3039 x -= glyphs[i].pixel_width;
3040 }
3041
3042 return k;
3043 }
3044
3045
3046 /* Return the index of the last glyph following glyph string S that is
3047 not overwritten by S because of S's right overhang. Value is -1 if
3048 no such glyph is found. */
3049
3050 static int
3051 x_right_overwritten (s)
3052 struct glyph_string *s;
3053 {
3054 int k = -1;
3055
3056 if (s->right_overhang)
3057 {
3058 int x = 0, i;
3059 struct glyph *glyphs = s->row->glyphs[s->area];
3060 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3061 int end = s->row->used[s->area];
3062
3063 for (i = first; i < end && s->right_overhang > x; ++i)
3064 x += glyphs[i].pixel_width;
3065
3066 k = i;
3067 }
3068
3069 return k;
3070 }
3071
3072
3073 /* Return the index of the last glyph following glyph string S that
3074 overwrites S because of its left overhang. Value is negative
3075 if no such glyph is found. */
3076
3077 static int
3078 x_right_overwriting (s)
3079 struct glyph_string *s;
3080 {
3081 int i, k, x;
3082 int end = s->row->used[s->area];
3083 struct glyph *glyphs = s->row->glyphs[s->area];
3084 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3085
3086 k = -1;
3087 x = 0;
3088 for (i = first; i < end; ++i)
3089 {
3090 int left, right;
3091 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3092 if (x - left < 0)
3093 k = i;
3094 x += glyphs[i].pixel_width;
3095 }
3096
3097 return k;
3098 }
3099
3100
3101 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3102
3103 static INLINE void
3104 x_clear_glyph_string_rect (s, x, y, w, h)
3105 struct glyph_string *s;
3106 int x, y, w, h;
3107 {
3108 XGCValues xgcv;
3109 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3110 XSetForeground (s->display, s->gc, xgcv.background);
3111 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3112 XSetForeground (s->display, s->gc, xgcv.foreground);
3113 }
3114
3115
3116 /* Draw the background of glyph_string S. If S->background_filled_p
3117 is non-zero don't draw it. FORCE_P non-zero means draw the
3118 background even if it wouldn't be drawn normally. This is used
3119 when a string preceding S draws into the background of S, or S
3120 contains the first component of a composition. */
3121
3122 static void
3123 x_draw_glyph_string_background (s, force_p)
3124 struct glyph_string *s;
3125 int force_p;
3126 {
3127 /* Nothing to do if background has already been drawn or if it
3128 shouldn't be drawn in the first place. */
3129 if (!s->background_filled_p)
3130 {
3131 int box_line_width = max (s->face->box_line_width, 0);
3132
3133 if (s->stippled_p)
3134 {
3135 /* Fill background with a stipple pattern. */
3136 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3137 XFillRectangle (s->display, s->window, s->gc, s->x,
3138 s->y + box_line_width,
3139 s->background_width,
3140 s->height - 2 * box_line_width);
3141 XSetFillStyle (s->display, s->gc, FillSolid);
3142 s->background_filled_p = 1;
3143 }
3144 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3145 || s->font_not_found_p
3146 || s->extends_to_end_of_line_p
3147 || force_p)
3148 {
3149 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3150 s->background_width,
3151 s->height - 2 * box_line_width);
3152 s->background_filled_p = 1;
3153 }
3154 }
3155 }
3156
3157
3158 /* Draw the foreground of glyph string S. */
3159
3160 static void
3161 x_draw_glyph_string_foreground (s)
3162 struct glyph_string *s;
3163 {
3164 int i, x;
3165
3166 /* If first glyph of S has a left box line, start drawing the text
3167 of S to the right of that box line. */
3168 if (s->face->box != FACE_NO_BOX
3169 && s->first_glyph->left_box_line_p)
3170 x = s->x + abs (s->face->box_line_width);
3171 else
3172 x = s->x;
3173
3174 /* Draw characters of S as rectangles if S's font could not be
3175 loaded. */
3176 if (s->font_not_found_p)
3177 {
3178 for (i = 0; i < s->nchars; ++i)
3179 {
3180 struct glyph *g = s->first_glyph + i;
3181 XDrawRectangle (s->display, s->window,
3182 s->gc, x, s->y, g->pixel_width - 1,
3183 s->height - 1);
3184 x += g->pixel_width;
3185 }
3186 }
3187 else
3188 {
3189 char *char1b = (char *) s->char2b;
3190 int boff = s->font_info->baseline_offset;
3191
3192 if (s->font_info->vertical_centering)
3193 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3194
3195 /* If we can use 8-bit functions, condense S->char2b. */
3196 if (!s->two_byte_p)
3197 for (i = 0; i < s->nchars; ++i)
3198 char1b[i] = s->char2b[i].byte2;
3199
3200 /* Draw text with XDrawString if background has already been
3201 filled. Otherwise, use XDrawImageString. (Note that
3202 XDrawImageString is usually faster than XDrawString.) Always
3203 use XDrawImageString when drawing the cursor so that there is
3204 no chance that characters under a box cursor are invisible. */
3205 if (s->for_overlaps_p
3206 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3207 {
3208 /* Draw characters with 16-bit or 8-bit functions. */
3209 if (s->two_byte_p)
3210 XDrawString16 (s->display, s->window, s->gc, x,
3211 s->ybase - boff, s->char2b, s->nchars);
3212 else
3213 XDrawString (s->display, s->window, s->gc, x,
3214 s->ybase - boff, char1b, s->nchars);
3215 }
3216 else
3217 {
3218 if (s->two_byte_p)
3219 XDrawImageString16 (s->display, s->window, s->gc, x,
3220 s->ybase - boff, s->char2b, s->nchars);
3221 else
3222 XDrawImageString (s->display, s->window, s->gc, x,
3223 s->ybase - boff, char1b, s->nchars);
3224 }
3225
3226 if (s->face->overstrike)
3227 {
3228 /* For overstriking (to simulate bold-face), draw the
3229 characters again shifted to the right by one pixel. */
3230 if (s->two_byte_p)
3231 XDrawString16 (s->display, s->window, s->gc, x + 1,
3232 s->ybase - boff, s->char2b, s->nchars);
3233 else
3234 XDrawString (s->display, s->window, s->gc, x + 1,
3235 s->ybase - boff, char1b, s->nchars);
3236 }
3237 }
3238 }
3239
3240 /* Draw the foreground of composite glyph string S. */
3241
3242 static void
3243 x_draw_composite_glyph_string_foreground (s)
3244 struct glyph_string *s;
3245 {
3246 int i, x;
3247
3248 /* If first glyph of S has a left box line, start drawing the text
3249 of S to the right of that box line. */
3250 if (s->face->box != FACE_NO_BOX
3251 && s->first_glyph->left_box_line_p)
3252 x = s->x + abs (s->face->box_line_width);
3253 else
3254 x = s->x;
3255
3256 /* S is a glyph string for a composition. S->gidx is the index of
3257 the first character drawn for glyphs of this composition.
3258 S->gidx == 0 means we are drawing the very first character of
3259 this composition. */
3260
3261 /* Draw a rectangle for the composition if the font for the very
3262 first character of the composition could not be loaded. */
3263 if (s->font_not_found_p)
3264 {
3265 if (s->gidx == 0)
3266 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3267 s->width - 1, s->height - 1);
3268 }
3269 else
3270 {
3271 for (i = 0; i < s->nchars; i++, ++s->gidx)
3272 {
3273 XDrawString16 (s->display, s->window, s->gc,
3274 x + s->cmp->offsets[s->gidx * 2],
3275 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3276 s->char2b + i, 1);
3277 if (s->face->overstrike)
3278 XDrawString16 (s->display, s->window, s->gc,
3279 x + s->cmp->offsets[s->gidx * 2] + 1,
3280 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3281 s->char2b + i, 1);
3282 }
3283 }
3284 }
3285
3286
3287 #ifdef USE_X_TOOLKIT
3288
3289 static struct frame *x_frame_of_widget P_ ((Widget));
3290 static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3291 XrmValue *, XrmValue *, XtPointer *));
3292 static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3293 XrmValue *, Cardinal *));
3294
3295
3296 /* Return the frame on which widget WIDGET is used.. Abort if frame
3297 cannot be determined. */
3298
3299 static struct frame *
3300 x_frame_of_widget (widget)
3301 Widget widget;
3302 {
3303 struct x_display_info *dpyinfo;
3304 Lisp_Object tail;
3305 struct frame *f;
3306
3307 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3308
3309 /* Find the top-level shell of the widget. Note that this function
3310 can be called when the widget is not yet realized, so XtWindow
3311 (widget) == 0. That's the reason we can't simply use
3312 x_any_window_to_frame. */
3313 while (!XtIsTopLevelShell (widget))
3314 widget = XtParent (widget);
3315
3316 /* Look for a frame with that top-level widget. Allocate the color
3317 on that frame to get the right gamma correction value. */
3318 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3319 if (GC_FRAMEP (XCAR (tail))
3320 && (f = XFRAME (XCAR (tail)),
3321 (f->output_data.nothing != 1
3322 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3323 && f->output_data.x->widget == widget)
3324 return f;
3325
3326 abort ();
3327 }
3328
3329
3330 /* Allocate the color COLOR->pixel on the screen and display of
3331 widget WIDGET in colormap CMAP. If an exact match cannot be
3332 allocated, try the nearest color available. Value is non-zero
3333 if successful. This is called from lwlib. */
3334
3335 int
3336 x_alloc_nearest_color_for_widget (widget, cmap, color)
3337 Widget widget;
3338 Colormap cmap;
3339 XColor *color;
3340 {
3341 struct frame *f = x_frame_of_widget (widget);
3342 return x_alloc_nearest_color (f, cmap, color);
3343 }
3344
3345
3346 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3347 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3348 If this produces the same color as PIXEL, try a color where all RGB
3349 values have DELTA added. Return the allocated color in *PIXEL.
3350 DISPLAY is the X display, CMAP is the colormap to operate on.
3351 Value is non-zero if successful. */
3352
3353 int
3354 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3355 Widget widget;
3356 Display *display;
3357 Colormap cmap;
3358 unsigned long *pixel;
3359 double factor;
3360 int delta;
3361 {
3362 struct frame *f = x_frame_of_widget (widget);
3363 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3364 }
3365
3366
3367 /* Structure specifying which arguments should be passed by Xt to
3368 cvt_string_to_pixel. We want the widget's screen and colormap. */
3369
3370 static XtConvertArgRec cvt_string_to_pixel_args[] =
3371 {
3372 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3373 sizeof (Screen *)},
3374 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3375 sizeof (Colormap)}
3376 };
3377
3378
3379 /* The address of this variable is returned by
3380 cvt_string_to_pixel. */
3381
3382 static Pixel cvt_string_to_pixel_value;
3383
3384
3385 /* Convert a color name to a pixel color.
3386
3387 DPY is the display we are working on.
3388
3389 ARGS is an array of *NARGS XrmValue structures holding additional
3390 information about the widget for which the conversion takes place.
3391 The contents of this array are determined by the specification
3392 in cvt_string_to_pixel_args.
3393
3394 FROM is a pointer to an XrmValue which points to the color name to
3395 convert. TO is an XrmValue in which to return the pixel color.
3396
3397 CLOSURE_RET is a pointer to user-data, in which we record if
3398 we allocated the color or not.
3399
3400 Value is True if successful, False otherwise. */
3401
3402 static Boolean
3403 cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3404 Display *dpy;
3405 XrmValue *args;
3406 Cardinal *nargs;
3407 XrmValue *from, *to;
3408 XtPointer *closure_ret;
3409 {
3410 Screen *screen;
3411 Colormap cmap;
3412 Pixel pixel;
3413 String color_name;
3414 XColor color;
3415
3416 if (*nargs != 2)
3417 {
3418 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3419 "wrongParameters", "cvt_string_to_pixel",
3420 "XtToolkitError",
3421 "Screen and colormap args required", NULL, NULL);
3422 return False;
3423 }
3424
3425 screen = *(Screen **) args[0].addr;
3426 cmap = *(Colormap *) args[1].addr;
3427 color_name = (String) from->addr;
3428
3429 if (strcmp (color_name, XtDefaultBackground) == 0)
3430 {
3431 *closure_ret = (XtPointer) False;
3432 pixel = WhitePixelOfScreen (screen);
3433 }
3434 else if (strcmp (color_name, XtDefaultForeground) == 0)
3435 {
3436 *closure_ret = (XtPointer) False;
3437 pixel = BlackPixelOfScreen (screen);
3438 }
3439 else if (XParseColor (dpy, cmap, color_name, &color)
3440 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3441 {
3442 pixel = color.pixel;
3443 *closure_ret = (XtPointer) True;
3444 }
3445 else
3446 {
3447 String params[1];
3448 Cardinal nparams = 1;
3449
3450 params[0] = color_name;
3451 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3452 "badValue", "cvt_string_to_pixel",
3453 "XtToolkitError", "Invalid color `%s'",
3454 params, &nparams);
3455 return False;
3456 }
3457
3458 if (to->addr != NULL)
3459 {
3460 if (to->size < sizeof (Pixel))
3461 {
3462 to->size = sizeof (Pixel);
3463 return False;
3464 }
3465
3466 *(Pixel *) to->addr = pixel;
3467 }
3468 else
3469 {
3470 cvt_string_to_pixel_value = pixel;
3471 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3472 }
3473
3474 to->size = sizeof (Pixel);
3475 return True;
3476 }
3477
3478
3479 /* Free a pixel color which was previously allocated via
3480 cvt_string_to_pixel. This is registered as the destructor
3481 for this type of resource via XtSetTypeConverter.
3482
3483 APP is the application context in which we work.
3484
3485 TO is a pointer to an XrmValue holding the color to free.
3486 CLOSURE is the value we stored in CLOSURE_RET for this color
3487 in cvt_string_to_pixel.
3488
3489 ARGS and NARGS are like for cvt_string_to_pixel. */
3490
3491 static void
3492 cvt_pixel_dtor (app, to, closure, args, nargs)
3493 XtAppContext app;
3494 XrmValuePtr to;
3495 XtPointer closure;
3496 XrmValuePtr args;
3497 Cardinal *nargs;
3498 {
3499 if (*nargs != 2)
3500 {
3501 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3502 "XtToolkitError",
3503 "Screen and colormap arguments required",
3504 NULL, NULL);
3505 }
3506 else if (closure != NULL)
3507 {
3508 /* We did allocate the pixel, so free it. */
3509 Screen *screen = *(Screen **) args[0].addr;
3510 Colormap cmap = *(Colormap *) args[1].addr;
3511 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
3512 (Pixel *) to->addr, 1);
3513 }
3514 }
3515
3516
3517 #endif /* USE_X_TOOLKIT */
3518
3519
3520 /* Value is an array of XColor structures for the contents of the
3521 color map of display DPY. Set *NCELLS to the size of the array.
3522 Note that this probably shouldn't be called for large color maps,
3523 say a 24-bit TrueColor map. */
3524
3525 static const XColor *
3526 x_color_cells (dpy, ncells)
3527 Display *dpy;
3528 int *ncells;
3529 {
3530 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3531
3532 if (dpyinfo->color_cells == NULL)
3533 {
3534 Screen *screen = dpyinfo->screen;
3535 int i;
3536
3537 dpyinfo->ncolor_cells
3538 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
3539 dpyinfo->color_cells
3540 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3541 * sizeof *dpyinfo->color_cells);
3542
3543 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3544 dpyinfo->color_cells[i].pixel = i;
3545
3546 XQueryColors (dpy, dpyinfo->cmap,
3547 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3548 }
3549
3550 *ncells = dpyinfo->ncolor_cells;
3551 return dpyinfo->color_cells;
3552 }
3553
3554
3555 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3556 colors in COLORS. Use cached information, if available. */
3557
3558 void
3559 x_query_colors (f, colors, ncolors)
3560 struct frame *f;
3561 XColor *colors;
3562 int ncolors;
3563 {
3564 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3565
3566 if (dpyinfo->color_cells)
3567 {
3568 int i;
3569 for (i = 0; i < ncolors; ++i)
3570 {
3571 unsigned long pixel = colors[i].pixel;
3572 xassert (pixel < dpyinfo->ncolor_cells);
3573 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3574 colors[i] = dpyinfo->color_cells[pixel];
3575 }
3576 }
3577 else
3578 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3579 }
3580
3581
3582 /* On frame F, translate pixel color to RGB values for the color in
3583 COLOR. Use cached information, if available. */
3584
3585 void
3586 x_query_color (f, color)
3587 struct frame *f;
3588 XColor *color;
3589 {
3590 x_query_colors (f, color, 1);
3591 }
3592
3593
3594 /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3595 exact match can't be allocated, try the nearest color available.
3596 Value is non-zero if successful. Set *COLOR to the color
3597 allocated. */
3598
3599 static int
3600 x_alloc_nearest_color_1 (dpy, cmap, color)
3601 Display *dpy;
3602 Colormap cmap;
3603 XColor *color;
3604 {
3605 int rc;
3606
3607 rc = XAllocColor (dpy, cmap, color);
3608 if (rc == 0)
3609 {
3610 /* If we got to this point, the colormap is full, so we're going
3611 to try to get the next closest color. The algorithm used is
3612 a least-squares matching, which is what X uses for closest
3613 color matching with StaticColor visuals. */
3614 int nearest, i;
3615 unsigned long nearest_delta = ~0;
3616 int ncells;
3617 const XColor *cells = x_color_cells (dpy, &ncells);
3618
3619 for (nearest = i = 0; i < ncells; ++i)
3620 {
3621 long dred = (color->red >> 8) - (cells[i].red >> 8);
3622 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3623 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3624 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3625
3626 if (delta < nearest_delta)
3627 {
3628 nearest = i;
3629 nearest_delta = delta;
3630 }
3631 }
3632
3633 color->red = cells[nearest].red;
3634 color->green = cells[nearest].green;
3635 color->blue = cells[nearest].blue;
3636 rc = XAllocColor (dpy, cmap, color);
3637 }
3638 else
3639 {
3640 /* If allocation succeeded, and the allocated pixel color is not
3641 equal to a cached pixel color recorded earlier, there was a
3642 change in the colormap, so clear the color cache. */
3643 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
3644 XColor *cached_color;
3645
3646 if (dpyinfo->color_cells
3647 && (cached_color = &dpyinfo->color_cells[color->pixel],
3648 (cached_color->red != color->red
3649 || cached_color->blue != color->blue
3650 || cached_color->green != color->green)))
3651 {
3652 xfree (dpyinfo->color_cells);
3653 dpyinfo->color_cells = NULL;
3654 dpyinfo->ncolor_cells = 0;
3655 }
3656 }
3657
3658 #ifdef DEBUG_X_COLORS
3659 if (rc)
3660 register_color (color->pixel);
3661 #endif /* DEBUG_X_COLORS */
3662
3663 return rc;
3664 }
3665
3666
3667 /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3668 exact match can't be allocated, try the nearest color available.
3669 Value is non-zero if successful. Set *COLOR to the color
3670 allocated. */
3671
3672 int
3673 x_alloc_nearest_color (f, cmap, color)
3674 struct frame *f;
3675 Colormap cmap;
3676 XColor *color;
3677 {
3678 gamma_correct (f, color);
3679 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3680 }
3681
3682
3683 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3684 It's necessary to do this instead of just using PIXEL directly to
3685 get color reference counts right. */
3686
3687 unsigned long
3688 x_copy_color (f, pixel)
3689 struct frame *f;
3690 unsigned long pixel;
3691 {
3692 XColor color;
3693
3694 color.pixel = pixel;
3695 BLOCK_INPUT;
3696 x_query_color (f, &color);
3697 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3698 UNBLOCK_INPUT;
3699 #ifdef DEBUG_X_COLORS
3700 register_color (pixel);
3701 #endif
3702 return color.pixel;
3703 }
3704
3705
3706 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3707 It's necessary to do this instead of just using PIXEL directly to
3708 get color reference counts right. */
3709
3710 unsigned long
3711 x_copy_dpy_color (dpy, cmap, pixel)
3712 Display *dpy;
3713 Colormap cmap;
3714 unsigned long pixel;
3715 {
3716 XColor color;
3717
3718 color.pixel = pixel;
3719 BLOCK_INPUT;
3720 XQueryColor (dpy, cmap, &color);
3721 XAllocColor (dpy, cmap, &color);
3722 UNBLOCK_INPUT;
3723 #ifdef DEBUG_X_COLORS
3724 register_color (pixel);
3725 #endif
3726 return color.pixel;
3727 }
3728
3729
3730 /* Brightness beyond which a color won't have its highlight brightness
3731 boosted.
3732
3733 Nominally, highlight colors for `3d' faces are calculated by
3734 brightening an object's color by a constant scale factor, but this
3735 doesn't yield good results for dark colors, so for colors who's
3736 brightness is less than this value (on a scale of 0-65535) have an
3737 use an additional additive factor.
3738
3739 The value here is set so that the default menu-bar/mode-line color
3740 (grey75) will not have its highlights changed at all. */
3741 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3742
3743
3744 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3745 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3746 If this produces the same color as PIXEL, try a color where all RGB
3747 values have DELTA added. Return the allocated color in *PIXEL.
3748 DISPLAY is the X display, CMAP is the colormap to operate on.
3749 Value is non-zero if successful. */
3750
3751 static int
3752 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3753 struct frame *f;
3754 Display *display;
3755 Colormap cmap;
3756 unsigned long *pixel;
3757 double factor;
3758 int delta;
3759 {
3760 XColor color, new;
3761 long bright;
3762 int success_p;
3763
3764 /* Get RGB color values. */
3765 color.pixel = *pixel;
3766 x_query_color (f, &color);
3767
3768 /* Change RGB values by specified FACTOR. Avoid overflow! */
3769 xassert (factor >= 0);
3770 new.red = min (0xffff, factor * color.red);
3771 new.green = min (0xffff, factor * color.green);
3772 new.blue = min (0xffff, factor * color.blue);
3773
3774 /* Calculate brightness of COLOR. */
3775 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3776
3777 /* We only boost colors that are darker than
3778 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3779 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3780 /* Make an additive adjustment to NEW, because it's dark enough so
3781 that scaling by FACTOR alone isn't enough. */
3782 {
3783 /* How far below the limit this color is (0 - 1, 1 being darker). */
3784 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3785 /* The additive adjustment. */
3786 int min_delta = delta * dimness * factor / 2;
3787
3788 if (factor < 1)
3789 {
3790 new.red = max (0, new.red - min_delta);
3791 new.green = max (0, new.green - min_delta);
3792 new.blue = max (0, new.blue - min_delta);
3793 }
3794 else
3795 {
3796 new.red = min (0xffff, min_delta + new.red);
3797 new.green = min (0xffff, min_delta + new.green);
3798 new.blue = min (0xffff, min_delta + new.blue);
3799 }
3800 }
3801
3802 /* Try to allocate the color. */
3803 success_p = x_alloc_nearest_color (f, cmap, &new);
3804 if (success_p)
3805 {
3806 if (new.pixel == *pixel)
3807 {
3808 /* If we end up with the same color as before, try adding
3809 delta to the RGB values. */
3810 x_free_colors (f, &new.pixel, 1);
3811
3812 new.red = min (0xffff, delta + color.red);
3813 new.green = min (0xffff, delta + color.green);
3814 new.blue = min (0xffff, delta + color.blue);
3815 success_p = x_alloc_nearest_color (f, cmap, &new);
3816 }
3817 else
3818 success_p = 1;
3819 *pixel = new.pixel;
3820 }
3821
3822 return success_p;
3823 }
3824
3825
3826 /* Set up the foreground color for drawing relief lines of glyph
3827 string S. RELIEF is a pointer to a struct relief containing the GC
3828 with which lines will be drawn. Use a color that is FACTOR or
3829 DELTA lighter or darker than the relief's background which is found
3830 in S->f->output_data.x->relief_background. If such a color cannot
3831 be allocated, use DEFAULT_PIXEL, instead. */
3832
3833 static void
3834 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3835 struct frame *f;
3836 struct relief *relief;
3837 double factor;
3838 int delta;
3839 unsigned long default_pixel;
3840 {
3841 XGCValues xgcv;
3842 struct x_output *di = f->output_data.x;
3843 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3844 unsigned long pixel;
3845 unsigned long background = di->relief_background;
3846 Colormap cmap = FRAME_X_COLORMAP (f);
3847 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3848 Display *dpy = FRAME_X_DISPLAY (f);
3849
3850 xgcv.graphics_exposures = False;
3851 xgcv.line_width = 1;
3852
3853 /* Free previously allocated color. The color cell will be reused
3854 when it has been freed as many times as it was allocated, so this
3855 doesn't affect faces using the same colors. */
3856 if (relief->gc
3857 && relief->allocated_p)
3858 {
3859 x_free_colors (f, &relief->pixel, 1);
3860 relief->allocated_p = 0;
3861 }
3862
3863 /* Allocate new color. */
3864 xgcv.foreground = default_pixel;
3865 pixel = background;
3866 if (dpyinfo->n_planes != 1
3867 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3868 {
3869 relief->allocated_p = 1;
3870 xgcv.foreground = relief->pixel = pixel;
3871 }
3872
3873 if (relief->gc == 0)
3874 {
3875 xgcv.stipple = dpyinfo->gray;
3876 mask |= GCStipple;
3877 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3878 }
3879 else
3880 XChangeGC (dpy, relief->gc, mask, &xgcv);
3881 }
3882
3883
3884 /* Set up colors for the relief lines around glyph string S. */
3885
3886 static void
3887 x_setup_relief_colors (s)
3888 struct glyph_string *s;
3889 {
3890 struct x_output *di = s->f->output_data.x;
3891 unsigned long color;
3892
3893 if (s->face->use_box_color_for_shadows_p)
3894 color = s->face->box_color;
3895 else if (s->first_glyph->type == IMAGE_GLYPH
3896 && s->img->pixmap
3897 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3898 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3899 else
3900 {
3901 XGCValues xgcv;
3902
3903 /* Get the background color of the face. */
3904 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3905 color = xgcv.background;
3906 }
3907
3908 if (di->white_relief.gc == 0
3909 || color != di->relief_background)
3910 {
3911 di->relief_background = color;
3912 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3913 WHITE_PIX_DEFAULT (s->f));
3914 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3915 BLACK_PIX_DEFAULT (s->f));
3916 }
3917 }
3918
3919
3920 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3921 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3922 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3923 relief. LEFT_P non-zero means draw a relief on the left side of
3924 the rectangle. RIGHT_P non-zero means draw a relief on the right
3925 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3926 when drawing. */
3927
3928 static void
3929 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3930 raised_p, left_p, right_p, clip_rect)
3931 struct frame *f;
3932 int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
3933 XRectangle *clip_rect;
3934 {
3935 Display *dpy = FRAME_X_DISPLAY (f);
3936 Window window = FRAME_X_WINDOW (f);
3937 int i;
3938 GC gc;
3939
3940 if (raised_p)
3941 gc = f->output_data.x->white_relief.gc;
3942 else
3943 gc = f->output_data.x->black_relief.gc;
3944 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3945
3946 /* Top. */
3947 for (i = 0; i < width; ++i)
3948 XDrawLine (dpy, window, gc,
3949 left_x + i * left_p, top_y + i,
3950 right_x + 1 - i * right_p, top_y + i);
3951
3952 /* Left. */
3953 if (left_p)
3954 for (i = 0; i < width; ++i)
3955 XDrawLine (dpy, window, gc,
3956 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3957
3958 XSetClipMask (dpy, gc, None);
3959 if (raised_p)
3960 gc = f->output_data.x->black_relief.gc;
3961 else
3962 gc = f->output_data.x->white_relief.gc;
3963 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
3964
3965 /* Bottom. */
3966 for (i = 0; i < width; ++i)
3967 XDrawLine (dpy, window, gc,
3968 left_x + i * left_p, bottom_y - i,
3969 right_x + 1 - i * right_p, bottom_y - i);
3970
3971 /* Right. */
3972 if (right_p)
3973 for (i = 0; i < width; ++i)
3974 XDrawLine (dpy, window, gc,
3975 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3976
3977 XSetClipMask (dpy, gc, None);
3978 }
3979
3980
3981 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3982 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3983 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3984 left side of the rectangle. RIGHT_P non-zero means draw a line
3985 on the right side of the rectangle. CLIP_RECT is the clipping
3986 rectangle to use when drawing. */
3987
3988 static void
3989 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3990 left_p, right_p, clip_rect)
3991 struct glyph_string *s;
3992 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3993 XRectangle *clip_rect;
3994 {
3995 XGCValues xgcv;
3996
3997 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3998 XSetForeground (s->display, s->gc, s->face->box_color);
3999 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
4000
4001 /* Top. */
4002 XFillRectangle (s->display, s->window, s->gc,
4003 left_x, top_y, right_x - left_x + 1, width);
4004
4005 /* Left. */
4006 if (left_p)
4007 XFillRectangle (s->display, s->window, s->gc,
4008 left_x, top_y, width, bottom_y - top_y + 1);
4009
4010 /* Bottom. */
4011 XFillRectangle (s->display, s->window, s->gc,
4012 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
4013
4014 /* Right. */
4015 if (right_p)
4016 XFillRectangle (s->display, s->window, s->gc,
4017 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
4018
4019 XSetForeground (s->display, s->gc, xgcv.foreground);
4020 XSetClipMask (s->display, s->gc, None);
4021 }
4022
4023
4024 /* Draw a box around glyph string S. */
4025
4026 static void
4027 x_draw_glyph_string_box (s)
4028 struct glyph_string *s;
4029 {
4030 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
4031 int left_p, right_p;
4032 struct glyph *last_glyph;
4033 XRectangle clip_rect;
4034
4035 last_x = window_box_right (s->w, s->area);
4036 if (s->row->full_width_p
4037 && !s->w->pseudo_window_p)
4038 {
4039 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
4040 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
4041 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
4042 }
4043
4044 /* The glyph that may have a right box line. */
4045 last_glyph = (s->cmp || s->img
4046 ? s->first_glyph
4047 : s->first_glyph + s->nchars - 1);
4048
4049 width = abs (s->face->box_line_width);
4050 raised_p = s->face->box == FACE_RAISED_BOX;
4051 left_x = s->x;
4052 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
4053 ? last_x - 1
4054 : min (last_x, s->x + s->background_width) - 1);
4055 top_y = s->y;
4056 bottom_y = top_y + s->height - 1;
4057
4058 left_p = (s->first_glyph->left_box_line_p
4059 || (s->hl == DRAW_MOUSE_FACE
4060 && (s->prev == NULL
4061 || s->prev->hl != s->hl)));
4062 right_p = (last_glyph->right_box_line_p
4063 || (s->hl == DRAW_MOUSE_FACE
4064 && (s->next == NULL
4065 || s->next->hl != s->hl)));
4066
4067 x_get_glyph_string_clip_rect (s, &clip_rect);
4068
4069 if (s->face->box == FACE_SIMPLE_BOX)
4070 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
4071 left_p, right_p, &clip_rect);
4072 else
4073 {
4074 x_setup_relief_colors (s);
4075 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4076 width, raised_p, left_p, right_p, &clip_rect);
4077 }
4078 }
4079
4080
4081 /* Draw foreground of image glyph string S. */
4082
4083 static void
4084 x_draw_image_foreground (s)
4085 struct glyph_string *s;
4086 {
4087 int x;
4088 int y = s->ybase - image_ascent (s->img, s->face);
4089
4090 /* If first glyph of S has a left box line, start drawing it to the
4091 right of that line. */
4092 if (s->face->box != FACE_NO_BOX
4093 && s->first_glyph->left_box_line_p)
4094 x = s->x + abs (s->face->box_line_width);
4095 else
4096 x = s->x;
4097
4098 /* If there is a margin around the image, adjust x- and y-position
4099 by that margin. */
4100 x += s->img->hmargin;
4101 y += s->img->vmargin;
4102
4103 if (s->img->pixmap)
4104 {
4105 if (s->img->mask)
4106 {
4107 /* We can't set both a clip mask and use XSetClipRectangles
4108 because the latter also sets a clip mask. We also can't
4109 trust on the shape extension to be available
4110 (XShapeCombineRegion). So, compute the rectangle to draw
4111 manually. */
4112 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4113 | GCFunction);
4114 XGCValues xgcv;
4115 XRectangle clip_rect, image_rect, r;
4116
4117 xgcv.clip_mask = s->img->mask;
4118 xgcv.clip_x_origin = x;
4119 xgcv.clip_y_origin = y;
4120 xgcv.function = GXcopy;
4121 XChangeGC (s->display, s->gc, mask, &xgcv);
4122
4123 x_get_glyph_string_clip_rect (s, &clip_rect);
4124 image_rect.x = x;
4125 image_rect.y = y;
4126 image_rect.width = s->img->width;
4127 image_rect.height = s->img->height;
4128 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4129 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4130 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4131 }
4132 else
4133 {
4134 XRectangle clip_rect, image_rect, r;
4135
4136 x_get_glyph_string_clip_rect (s, &clip_rect);
4137 image_rect.x = x;
4138 image_rect.y = y;
4139 image_rect.width = s->img->width;
4140 image_rect.height = s->img->height;
4141 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4142 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4143 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4144
4145 /* When the image has a mask, we can expect that at
4146 least part of a mouse highlight or a block cursor will
4147 be visible. If the image doesn't have a mask, make
4148 a block cursor visible by drawing a rectangle around
4149 the image. I believe it's looking better if we do
4150 nothing here for mouse-face. */
4151 if (s->hl == DRAW_CURSOR)
4152 {
4153 int r = s->img->relief;
4154 if (r < 0) r = -r;
4155 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
4156 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4157 }
4158 }
4159 }
4160 else
4161 /* Draw a rectangle if image could not be loaded. */
4162 XDrawRectangle (s->display, s->window, s->gc, x, y,
4163 s->img->width - 1, s->img->height - 1);
4164 }
4165
4166
4167 /* Draw a relief around the image glyph string S. */
4168
4169 static void
4170 x_draw_image_relief (s)
4171 struct glyph_string *s;
4172 {
4173 int x0, y0, x1, y1, thick, raised_p;
4174 XRectangle r;
4175 int x;
4176 int y = s->ybase - image_ascent (s->img, s->face);
4177
4178 /* If first glyph of S has a left box line, start drawing it to the
4179 right of that line. */
4180 if (s->face->box != FACE_NO_BOX
4181 && s->first_glyph->left_box_line_p)
4182 x = s->x + abs (s->face->box_line_width);
4183 else
4184 x = s->x;
4185
4186 /* If there is a margin around the image, adjust x- and y-position
4187 by that margin. */
4188 x += s->img->hmargin;
4189 y += s->img->vmargin;
4190
4191 if (s->hl == DRAW_IMAGE_SUNKEN
4192 || s->hl == DRAW_IMAGE_RAISED)
4193 {
4194 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
4195 raised_p = s->hl == DRAW_IMAGE_RAISED;
4196 }
4197 else
4198 {
4199 thick = abs (s->img->relief);
4200 raised_p = s->img->relief > 0;
4201 }
4202
4203 x0 = x - thick;
4204 y0 = y - thick;
4205 x1 = x + s->img->width + thick - 1;
4206 y1 = y + s->img->height + thick - 1;
4207
4208 x_setup_relief_colors (s);
4209 x_get_glyph_string_clip_rect (s, &r);
4210 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4211 }
4212
4213
4214 /* Draw the foreground of image glyph string S to PIXMAP. */
4215
4216 static void
4217 x_draw_image_foreground_1 (s, pixmap)
4218 struct glyph_string *s;
4219 Pixmap pixmap;
4220 {
4221 int x;
4222 int y = s->ybase - s->y - image_ascent (s->img, s->face);
4223
4224 /* If first glyph of S has a left box line, start drawing it to the
4225 right of that line. */
4226 if (s->face->box != FACE_NO_BOX
4227 && s->first_glyph->left_box_line_p)
4228 x = abs (s->face->box_line_width);
4229 else
4230 x = 0;
4231
4232 /* If there is a margin around the image, adjust x- and y-position
4233 by that margin. */
4234 x += s->img->hmargin;
4235 y += s->img->vmargin;
4236
4237 if (s->img->pixmap)
4238 {
4239 if (s->img->mask)
4240 {
4241 /* We can't set both a clip mask and use XSetClipRectangles
4242 because the latter also sets a clip mask. We also can't
4243 trust on the shape extension to be available
4244 (XShapeCombineRegion). So, compute the rectangle to draw
4245 manually. */
4246 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4247 | GCFunction);
4248 XGCValues xgcv;
4249
4250 xgcv.clip_mask = s->img->mask;
4251 xgcv.clip_x_origin = x;
4252 xgcv.clip_y_origin = y;
4253 xgcv.function = GXcopy;
4254 XChangeGC (s->display, s->gc, mask, &xgcv);
4255
4256 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4257 0, 0, s->img->width, s->img->height, x, y);
4258 XSetClipMask (s->display, s->gc, None);
4259 }
4260 else
4261 {
4262 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4263 0, 0, s->img->width, s->img->height, x, y);
4264
4265 /* When the image has a mask, we can expect that at
4266 least part of a mouse highlight or a block cursor will
4267 be visible. If the image doesn't have a mask, make
4268 a block cursor visible by drawing a rectangle around
4269 the image. I believe it's looking better if we do
4270 nothing here for mouse-face. */
4271 if (s->hl == DRAW_CURSOR)
4272 {
4273 int r = s->img->relief;
4274 if (r < 0) r = -r;
4275 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
4276 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
4277 }
4278 }
4279 }
4280 else
4281 /* Draw a rectangle if image could not be loaded. */
4282 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4283 s->img->width - 1, s->img->height - 1);
4284 }
4285
4286
4287 /* Draw part of the background of glyph string S. X, Y, W, and H
4288 give the rectangle to draw. */
4289
4290 static void
4291 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4292 struct glyph_string *s;
4293 int x, y, w, h;
4294 {
4295 if (s->stippled_p)
4296 {
4297 /* Fill background with a stipple pattern. */
4298 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4299 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4300 XSetFillStyle (s->display, s->gc, FillSolid);
4301 }
4302 else
4303 x_clear_glyph_string_rect (s, x, y, w, h);
4304 }
4305
4306
4307 /* Draw image glyph string S.
4308
4309 s->y
4310 s->x +-------------------------
4311 | s->face->box
4312 |
4313 | +-------------------------
4314 | | s->img->margin
4315 | |
4316 | | +-------------------
4317 | | | the image
4318
4319 */
4320
4321 static void
4322 x_draw_image_glyph_string (s)
4323 struct glyph_string *s;
4324 {
4325 int x, y;
4326 int box_line_hwidth = abs (s->face->box_line_width);
4327 int box_line_vwidth = max (s->face->box_line_width, 0);
4328 int height;
4329 Pixmap pixmap = None;
4330
4331 height = s->height - 2 * box_line_vwidth;
4332
4333 /* Fill background with face under the image. Do it only if row is
4334 taller than image or if image has a clip mask to reduce
4335 flickering. */
4336 s->stippled_p = s->face->stipple != 0;
4337 if (height > s->img->height
4338 || s->img->hmargin
4339 || s->img->vmargin
4340 || s->img->mask
4341 || s->img->pixmap == 0
4342 || s->width != s->background_width)
4343 {
4344 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4345 x = s->x + box_line_hwidth;
4346 else
4347 x = s->x;
4348
4349 y = s->y + box_line_vwidth;
4350
4351 if (s->img->mask)
4352 {
4353 /* Create a pixmap as large as the glyph string. Fill it
4354 with the background color. Copy the image to it, using
4355 its mask. Copy the temporary pixmap to the display. */
4356 Screen *screen = FRAME_X_SCREEN (s->f);
4357 int depth = DefaultDepthOfScreen (screen);
4358
4359 /* Create a pixmap as large as the glyph string. */
4360 pixmap = XCreatePixmap (s->display, s->window,
4361 s->background_width,
4362 s->height, depth);
4363
4364 /* Don't clip in the following because we're working on the
4365 pixmap. */
4366 XSetClipMask (s->display, s->gc, None);
4367
4368 /* Fill the pixmap with the background color/stipple. */
4369 if (s->stippled_p)
4370 {
4371 /* Fill background with a stipple pattern. */
4372 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4373 XFillRectangle (s->display, pixmap, s->gc,
4374 0, 0, s->background_width, s->height);
4375 XSetFillStyle (s->display, s->gc, FillSolid);
4376 }
4377 else
4378 {
4379 XGCValues xgcv;
4380 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4381 &xgcv);
4382 XSetForeground (s->display, s->gc, xgcv.background);
4383 XFillRectangle (s->display, pixmap, s->gc,
4384 0, 0, s->background_width, s->height);
4385 XSetForeground (s->display, s->gc, xgcv.foreground);
4386 }
4387 }
4388 else
4389 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4390
4391 s->background_filled_p = 1;
4392 }
4393
4394 /* Draw the foreground. */
4395 if (pixmap != None)
4396 {
4397 x_draw_image_foreground_1 (s, pixmap);
4398 x_set_glyph_string_clipping (s);
4399 XCopyArea (s->display, pixmap, s->window, s->gc,
4400 0, 0, s->background_width, s->height, s->x, s->y);
4401 XFreePixmap (s->display, pixmap);
4402 }
4403 else
4404 x_draw_image_foreground (s);
4405
4406 /* If we must draw a relief around the image, do it. */
4407 if (s->img->relief
4408 || s->hl == DRAW_IMAGE_RAISED
4409 || s->hl == DRAW_IMAGE_SUNKEN)
4410 x_draw_image_relief (s);
4411 }
4412
4413
4414 /* Draw stretch glyph string S. */
4415
4416 static void
4417 x_draw_stretch_glyph_string (s)
4418 struct glyph_string *s;
4419 {
4420 xassert (s->first_glyph->type == STRETCH_GLYPH);
4421 s->stippled_p = s->face->stipple != 0;
4422
4423 if (s->hl == DRAW_CURSOR
4424 && !x_stretch_cursor_p)
4425 {
4426 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4427 as wide as the stretch glyph. */
4428 int width = min (CANON_X_UNIT (s->f), s->background_width);
4429
4430 /* Draw cursor. */
4431 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4432
4433 /* Clear rest using the GC of the original non-cursor face. */
4434 if (width < s->background_width)
4435 {
4436 int x = s->x + width, y = s->y;
4437 int w = s->background_width - width, h = s->height;
4438 XRectangle r;
4439 GC gc;
4440
4441 if (s->row->mouse_face_p
4442 && cursor_in_mouse_face_p (s->w))
4443 {
4444 x_set_mouse_face_gc (s);
4445 gc = s->gc;
4446 }
4447 else
4448 gc = s->face->gc;
4449
4450 x_get_glyph_string_clip_rect (s, &r);
4451 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4452
4453 if (s->face->stipple)
4454 {
4455 /* Fill background with a stipple pattern. */
4456 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4457 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4458 XSetFillStyle (s->display, gc, FillSolid);
4459 }
4460 else
4461 {
4462 XGCValues xgcv;
4463 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4464 XSetForeground (s->display, gc, xgcv.background);
4465 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4466 XSetForeground (s->display, gc, xgcv.foreground);
4467 }
4468 }
4469 }
4470 else if (!s->background_filled_p)
4471 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4472 s->height);
4473
4474 s->background_filled_p = 1;
4475 }
4476
4477
4478 /* Draw glyph string S. */
4479
4480 static void
4481 x_draw_glyph_string (s)
4482 struct glyph_string *s;
4483 {
4484 int relief_drawn_p = 0;
4485
4486 /* If S draws into the background of its successor, draw the
4487 background of the successor first so that S can draw into it.
4488 This makes S->next use XDrawString instead of XDrawImageString. */
4489 if (s->next && s->right_overhang && !s->for_overlaps_p)
4490 {
4491 xassert (s->next->img == NULL);
4492 x_set_glyph_string_gc (s->next);
4493 x_set_glyph_string_clipping (s->next);
4494 x_draw_glyph_string_background (s->next, 1);
4495 }
4496
4497 /* Set up S->gc, set clipping and draw S. */
4498 x_set_glyph_string_gc (s);
4499
4500 /* Draw relief (if any) in advance for char/composition so that the
4501 glyph string can be drawn over it. */
4502 if (!s->for_overlaps_p
4503 && s->face->box != FACE_NO_BOX
4504 && (s->first_glyph->type == CHAR_GLYPH
4505 || s->first_glyph->type == COMPOSITE_GLYPH))
4506
4507 {
4508 x_set_glyph_string_clipping (s);
4509 x_draw_glyph_string_background (s, 1);
4510 x_draw_glyph_string_box (s);
4511 x_set_glyph_string_clipping (s);
4512 relief_drawn_p = 1;
4513 }
4514 else
4515 x_set_glyph_string_clipping (s);
4516
4517 switch (s->first_glyph->type)
4518 {
4519 case IMAGE_GLYPH:
4520 x_draw_image_glyph_string (s);
4521 break;
4522
4523 case STRETCH_GLYPH:
4524 x_draw_stretch_glyph_string (s);
4525 break;
4526
4527 case CHAR_GLYPH:
4528 if (s->for_overlaps_p)
4529 s->background_filled_p = 1;
4530 else
4531 x_draw_glyph_string_background (s, 0);
4532 x_draw_glyph_string_foreground (s);
4533 break;
4534
4535 case COMPOSITE_GLYPH:
4536 if (s->for_overlaps_p || s->gidx > 0)
4537 s->background_filled_p = 1;
4538 else
4539 x_draw_glyph_string_background (s, 1);
4540 x_draw_composite_glyph_string_foreground (s);
4541 break;
4542
4543 default:
4544 abort ();
4545 }
4546
4547 if (!s->for_overlaps_p)
4548 {
4549 /* Draw underline. */
4550 if (s->face->underline_p)
4551 {
4552 unsigned long tem, h;
4553 int y;
4554
4555 /* Get the underline thickness. Default is 1 pixel. */
4556 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4557 h = 1;
4558
4559 /* Get the underline position. This is the recommended
4560 vertical offset in pixels from the baseline to the top of
4561 the underline. This is a signed value according to the
4562 specs, and its default is
4563
4564 ROUND ((maximum descent) / 2), with
4565 ROUND(x) = floor (x + 0.5) */
4566
4567 if (x_use_underline_position_properties
4568 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4569 y = s->ybase + (long) tem;
4570 else if (s->face->font)
4571 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4572 else
4573 y = s->y + s->height - h;
4574
4575 if (s->face->underline_defaulted_p)
4576 XFillRectangle (s->display, s->window, s->gc,
4577 s->x, y, s->width, h);
4578 else
4579 {
4580 XGCValues xgcv;
4581 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4582 XSetForeground (s->display, s->gc, s->face->underline_color);
4583 XFillRectangle (s->display, s->window, s->gc,
4584 s->x, y, s->width, h);
4585 XSetForeground (s->display, s->gc, xgcv.foreground);
4586 }
4587 }
4588
4589 /* Draw overline. */
4590 if (s->face->overline_p)
4591 {
4592 unsigned long dy = 0, h = 1;
4593
4594 if (s->face->overline_color_defaulted_p)
4595 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4596 s->width, h);
4597 else
4598 {
4599 XGCValues xgcv;
4600 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4601 XSetForeground (s->display, s->gc, s->face->overline_color);
4602 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4603 s->width, h);
4604 XSetForeground (s->display, s->gc, xgcv.foreground);
4605 }
4606 }
4607
4608 /* Draw strike-through. */
4609 if (s->face->strike_through_p)
4610 {
4611 unsigned long h = 1;
4612 unsigned long dy = (s->height - h) / 2;
4613
4614 if (s->face->strike_through_color_defaulted_p)
4615 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4616 s->width, h);
4617 else
4618 {
4619 XGCValues xgcv;
4620 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4621 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4622 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4623 s->width, h);
4624 XSetForeground (s->display, s->gc, xgcv.foreground);
4625 }
4626 }
4627
4628 /* Draw relief if not yet drawn. */
4629 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4630 x_draw_glyph_string_box (s);
4631 }
4632
4633 /* Reset clipping. */
4634 XSetClipMask (s->display, s->gc, None);
4635 }
4636
4637
4638 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4639 struct face **, int));
4640
4641
4642 /* Fill glyph string S with composition components specified by S->cmp.
4643
4644 FACES is an array of faces for all components of this composition.
4645 S->gidx is the index of the first component for S.
4646 OVERLAPS_P non-zero means S should draw the foreground only, and
4647 use its physical height for clipping.
4648
4649 Value is the index of a component not in S. */
4650
4651 static int
4652 x_fill_composite_glyph_string (s, faces, overlaps_p)
4653 struct glyph_string *s;
4654 struct face **faces;
4655 int overlaps_p;
4656 {
4657 int i;
4658
4659 xassert (s);
4660
4661 s->for_overlaps_p = overlaps_p;
4662
4663 s->face = faces[s->gidx];
4664 s->font = s->face->font;
4665 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4666
4667 /* For all glyphs of this composition, starting at the offset
4668 S->gidx, until we reach the end of the definition or encounter a
4669 glyph that requires the different face, add it to S. */
4670 ++s->nchars;
4671 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4672 ++s->nchars;
4673
4674 /* All glyph strings for the same composition has the same width,
4675 i.e. the width set for the first component of the composition. */
4676
4677 s->width = s->first_glyph->pixel_width;
4678
4679 /* If the specified font could not be loaded, use the frame's
4680 default font, but record the fact that we couldn't load it in
4681 the glyph string so that we can draw rectangles for the
4682 characters of the glyph string. */
4683 if (s->font == NULL)
4684 {
4685 s->font_not_found_p = 1;
4686 s->font = FRAME_FONT (s->f);
4687 }
4688
4689 /* Adjust base line for subscript/superscript text. */
4690 s->ybase += s->first_glyph->voffset;
4691
4692 xassert (s->face && s->face->gc);
4693
4694 /* This glyph string must always be drawn with 16-bit functions. */
4695 s->two_byte_p = 1;
4696
4697 return s->gidx + s->nchars;
4698 }
4699
4700
4701 /* Fill glyph string S from a sequence of character glyphs.
4702
4703 FACE_ID is the face id of the string. START is the index of the
4704 first glyph to consider, END is the index of the last + 1.
4705 OVERLAPS_P non-zero means S should draw the foreground only, and
4706 use its physical height for clipping.
4707
4708 Value is the index of the first glyph not in S. */
4709
4710 static int
4711 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4712 struct glyph_string *s;
4713 int face_id;
4714 int start, end, overlaps_p;
4715 {
4716 struct glyph *glyph, *last;
4717 int voffset;
4718 int glyph_not_available_p;
4719
4720 xassert (s->f == XFRAME (s->w->frame));
4721 xassert (s->nchars == 0);
4722 xassert (start >= 0 && end > start);
4723
4724 s->for_overlaps_p = overlaps_p,
4725 glyph = s->row->glyphs[s->area] + start;
4726 last = s->row->glyphs[s->area] + end;
4727 voffset = glyph->voffset;
4728
4729 glyph_not_available_p = glyph->glyph_not_available_p;
4730
4731 while (glyph < last
4732 && glyph->type == CHAR_GLYPH
4733 && glyph->voffset == voffset
4734 /* Same face id implies same font, nowadays. */
4735 && glyph->face_id == face_id
4736 && glyph->glyph_not_available_p == glyph_not_available_p)
4737 {
4738 int two_byte_p;
4739
4740 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4741 s->char2b + s->nchars,
4742 &two_byte_p);
4743 s->two_byte_p = two_byte_p;
4744 ++s->nchars;
4745 xassert (s->nchars <= end - start);
4746 s->width += glyph->pixel_width;
4747 ++glyph;
4748 }
4749
4750 s->font = s->face->font;
4751 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4752
4753 /* If the specified font could not be loaded, use the frame's font,
4754 but record the fact that we couldn't load it in
4755 S->font_not_found_p so that we can draw rectangles for the
4756 characters of the glyph string. */
4757 if (s->font == NULL || glyph_not_available_p)
4758 {
4759 s->font_not_found_p = 1;
4760 s->font = FRAME_FONT (s->f);
4761 }
4762
4763 /* Adjust base line for subscript/superscript text. */
4764 s->ybase += voffset;
4765
4766 xassert (s->face && s->face->gc);
4767 return glyph - s->row->glyphs[s->area];
4768 }
4769
4770
4771 /* Fill glyph string S from image glyph S->first_glyph. */
4772
4773 static void
4774 x_fill_image_glyph_string (s)
4775 struct glyph_string *s;
4776 {
4777 xassert (s->first_glyph->type == IMAGE_GLYPH);
4778 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4779 xassert (s->img);
4780 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4781 s->font = s->face->font;
4782 s->width = s->first_glyph->pixel_width;
4783
4784 /* Adjust base line for subscript/superscript text. */
4785 s->ybase += s->first_glyph->voffset;
4786 }
4787
4788
4789 /* Fill glyph string S from a sequence of stretch glyphs.
4790
4791 ROW is the glyph row in which the glyphs are found, AREA is the
4792 area within the row. START is the index of the first glyph to
4793 consider, END is the index of the last + 1.
4794
4795 Value is the index of the first glyph not in S. */
4796
4797 static int
4798 x_fill_stretch_glyph_string (s, row, area, start, end)
4799 struct glyph_string *s;
4800 struct glyph_row *row;
4801 enum glyph_row_area area;
4802 int start, end;
4803 {
4804 struct glyph *glyph, *last;
4805 int voffset, face_id;
4806
4807 xassert (s->first_glyph->type == STRETCH_GLYPH);
4808
4809 glyph = s->row->glyphs[s->area] + start;
4810 last = s->row->glyphs[s->area] + end;
4811 face_id = glyph->face_id;
4812 s->face = FACE_FROM_ID (s->f, face_id);
4813 s->font = s->face->font;
4814 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4815 s->width = glyph->pixel_width;
4816 voffset = glyph->voffset;
4817
4818 for (++glyph;
4819 (glyph < last
4820 && glyph->type == STRETCH_GLYPH
4821 && glyph->voffset == voffset
4822 && glyph->face_id == face_id);
4823 ++glyph)
4824 s->width += glyph->pixel_width;
4825
4826 /* Adjust base line for subscript/superscript text. */
4827 s->ybase += voffset;
4828
4829 /* The case that face->gc == 0 is handled when drawing the glyph
4830 string by calling PREPARE_FACE_FOR_DISPLAY. */
4831 xassert (s->face);
4832 return glyph - s->row->glyphs[s->area];
4833 }
4834
4835
4836 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4837 of XChar2b structures for S; it can't be allocated in
4838 x_init_glyph_string because it must be allocated via `alloca'. W
4839 is the window on which S is drawn. ROW and AREA are the glyph row
4840 and area within the row from which S is constructed. START is the
4841 index of the first glyph structure covered by S. HL is a
4842 face-override for drawing S. */
4843
4844 static void
4845 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4846 struct glyph_string *s;
4847 XChar2b *char2b;
4848 struct window *w;
4849 struct glyph_row *row;
4850 enum glyph_row_area area;
4851 int start;
4852 enum draw_glyphs_face hl;
4853 {
4854 bzero (s, sizeof *s);
4855 s->w = w;
4856 s->f = XFRAME (w->frame);
4857 s->display = FRAME_X_DISPLAY (s->f);
4858 s->window = FRAME_X_WINDOW (s->f);
4859 s->char2b = char2b;
4860 s->hl = hl;
4861 s->row = row;
4862 s->area = area;
4863 s->first_glyph = row->glyphs[area] + start;
4864 s->height = row->height;
4865 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4866
4867 /* Display the internal border below the tool-bar window. */
4868 if (s->w == XWINDOW (s->f->tool_bar_window))
4869 s->y -= s->f->output_data.x->internal_border_width;
4870
4871 s->ybase = s->y + row->ascent;
4872 }
4873
4874
4875 /* Set background width of glyph string S. START is the index of the
4876 first glyph following S. LAST_X is the right-most x-position + 1
4877 in the drawing area. */
4878
4879 static INLINE void
4880 x_set_glyph_string_background_width (s, start, last_x)
4881 struct glyph_string *s;
4882 int start;
4883 int last_x;
4884 {
4885 /* If the face of this glyph string has to be drawn to the end of
4886 the drawing area, set S->extends_to_end_of_line_p. */
4887 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4888
4889 if (start == s->row->used[s->area]
4890 && s->area == TEXT_AREA
4891 && ((s->hl == DRAW_NORMAL_TEXT
4892 && (s->row->fill_line_p
4893 || s->face->background != default_face->background
4894 || s->face->stipple != default_face->stipple
4895 || s->row->mouse_face_p))
4896 || s->hl == DRAW_MOUSE_FACE
4897 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4898 && s->row->fill_line_p)))
4899 s->extends_to_end_of_line_p = 1;
4900
4901 /* If S extends its face to the end of the line, set its
4902 background_width to the distance to the right edge of the drawing
4903 area. */
4904 if (s->extends_to_end_of_line_p)
4905 s->background_width = last_x - s->x + 1;
4906 else
4907 s->background_width = s->width;
4908 }
4909
4910
4911 /* Add a glyph string for a stretch glyph to the list of strings
4912 between HEAD and TAIL. START is the index of the stretch glyph in
4913 row area AREA of glyph row ROW. END is the index of the last glyph
4914 in that glyph row area. X is the current output position assigned
4915 to the new glyph string constructed. HL overrides that face of the
4916 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4917 is the right-most x-position of the drawing area. */
4918
4919 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4920 and below -- keep them on one line. */
4921 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4922 do \
4923 { \
4924 s = (struct glyph_string *) alloca (sizeof *s); \
4925 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4926 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4927 x_append_glyph_string (&HEAD, &TAIL, s); \
4928 s->x = (X); \
4929 } \
4930 while (0)
4931
4932
4933 /* Add a glyph string for an image glyph to the list of strings
4934 between HEAD and TAIL. START is the index of the image glyph in
4935 row area AREA of glyph row ROW. END is the index of the last glyph
4936 in that glyph row area. X is the current output position assigned
4937 to the new glyph string constructed. HL overrides that face of the
4938 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4939 is the right-most x-position of the drawing area. */
4940
4941 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4942 do \
4943 { \
4944 s = (struct glyph_string *) alloca (sizeof *s); \
4945 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4946 x_fill_image_glyph_string (s); \
4947 x_append_glyph_string (&HEAD, &TAIL, s); \
4948 ++START; \
4949 s->x = (X); \
4950 } \
4951 while (0)
4952
4953
4954 /* Add a glyph string for a sequence of character glyphs to the list
4955 of strings between HEAD and TAIL. START is the index of the first
4956 glyph in row area AREA of glyph row ROW that is part of the new
4957 glyph string. END is the index of the last glyph in that glyph row
4958 area. X is the current output position assigned to the new glyph
4959 string constructed. HL overrides that face of the glyph; e.g. it
4960 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4961 right-most x-position of the drawing area. */
4962
4963 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4964 do \
4965 { \
4966 int c, face_id; \
4967 XChar2b *char2b; \
4968 \
4969 c = (ROW)->glyphs[AREA][START].u.ch; \
4970 face_id = (ROW)->glyphs[AREA][START].face_id; \
4971 \
4972 s = (struct glyph_string *) alloca (sizeof *s); \
4973 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4974 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4975 x_append_glyph_string (&HEAD, &TAIL, s); \
4976 s->x = (X); \
4977 START = x_fill_glyph_string (s, face_id, START, END, \
4978 OVERLAPS_P); \
4979 } \
4980 while (0)
4981
4982
4983 /* Add a glyph string for a composite sequence to the list of strings
4984 between HEAD and TAIL. START is the index of the first glyph in
4985 row area AREA of glyph row ROW that is part of the new glyph
4986 string. END is the index of the last glyph in that glyph row area.
4987 X is the current output position assigned to the new glyph string
4988 constructed. HL overrides that face of the glyph; e.g. it is
4989 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4990 x-position of the drawing area. */
4991
4992 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4993 do { \
4994 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4995 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4996 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4997 struct composition *cmp = composition_table[cmp_id]; \
4998 int glyph_len = cmp->glyph_len; \
4999 XChar2b *char2b; \
5000 struct face **faces; \
5001 struct glyph_string *first_s = NULL; \
5002 int n; \
5003 \
5004 base_face = base_face->ascii_face; \
5005 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
5006 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
5007 /* At first, fill in `char2b' and `faces'. */ \
5008 for (n = 0; n < glyph_len; n++) \
5009 { \
5010 int c = COMPOSITION_GLYPH (cmp, n); \
5011 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
5012 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
5013 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
5014 this_face_id, char2b + n, 1, 1); \
5015 } \
5016 \
5017 /* Make glyph_strings for each glyph sequence that is drawable by \
5018 the same face, and append them to HEAD/TAIL. */ \
5019 for (n = 0; n < cmp->glyph_len;) \
5020 { \
5021 s = (struct glyph_string *) alloca (sizeof *s); \
5022 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
5023 x_append_glyph_string (&(HEAD), &(TAIL), s); \
5024 s->cmp = cmp; \
5025 s->gidx = n; \
5026 s->x = (X); \
5027 \
5028 if (n == 0) \
5029 first_s = s; \
5030 \
5031 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
5032 } \
5033 \
5034 ++START; \
5035 s = first_s; \
5036 } while (0)
5037
5038
5039 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
5040 of AREA of glyph row ROW on window W between indices START and END.
5041 HL overrides the face for drawing glyph strings, e.g. it is
5042 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
5043 x-positions of the drawing area.
5044
5045 This is an ugly monster macro construct because we must use alloca
5046 to allocate glyph strings (because x_draw_glyphs can be called
5047 asynchronously). */
5048
5049 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
5050 do \
5051 { \
5052 HEAD = TAIL = NULL; \
5053 while (START < END) \
5054 { \
5055 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
5056 switch (first_glyph->type) \
5057 { \
5058 case CHAR_GLYPH: \
5059 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
5060 TAIL, HL, X, LAST_X, \
5061 OVERLAPS_P); \
5062 break; \
5063 \
5064 case COMPOSITE_GLYPH: \
5065 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
5066 HEAD, TAIL, HL, X, LAST_X,\
5067 OVERLAPS_P); \
5068 break; \
5069 \
5070 case STRETCH_GLYPH: \
5071 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
5072 HEAD, TAIL, HL, X, LAST_X); \
5073 break; \
5074 \
5075 case IMAGE_GLYPH: \
5076 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
5077 TAIL, HL, X, LAST_X); \
5078 break; \
5079 \
5080 default: \
5081 abort (); \
5082 } \
5083 \
5084 x_set_glyph_string_background_width (s, START, LAST_X); \
5085 (X) += s->width; \
5086 } \
5087 } \
5088 while (0)
5089
5090
5091 /* Draw glyphs between START and END in AREA of ROW on window W,
5092 starting at x-position X. X is relative to AREA in W. HL is a
5093 face-override with the following meaning:
5094
5095 DRAW_NORMAL_TEXT draw normally
5096 DRAW_CURSOR draw in cursor face
5097 DRAW_MOUSE_FACE draw in mouse face.
5098 DRAW_INVERSE_VIDEO draw in mode line face
5099 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5100 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5101
5102 If OVERLAPS_P is non-zero, draw only the foreground of characters
5103 and clip to the physical height of ROW.
5104
5105 Value is the x-position reached, relative to AREA of W. */
5106
5107 static int
5108 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
5109 struct window *w;
5110 int x;
5111 struct glyph_row *row;
5112 enum glyph_row_area area;
5113 int start, end;
5114 enum draw_glyphs_face hl;
5115 int overlaps_p;
5116 {
5117 struct glyph_string *head, *tail;
5118 struct glyph_string *s;
5119 int last_x, area_width;
5120 int x_reached;
5121 int i, j;
5122
5123 /* Let's rather be paranoid than getting a SEGV. */
5124 end = min (end, row->used[area]);
5125 start = max (0, start);
5126 start = min (end, start);
5127
5128 /* Translate X to frame coordinates. Set last_x to the right
5129 end of the drawing area. */
5130 if (row->full_width_p)
5131 {
5132 /* X is relative to the left edge of W, without scroll bars
5133 or fringes. */
5134 struct frame *f = XFRAME (w->frame);
5135 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
5136
5137 x += window_left_x;
5138 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5139 last_x = window_left_x + area_width;
5140
5141 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5142 {
5143 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5144 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5145 last_x += width;
5146 else
5147 x -= width;
5148 }
5149
5150 x += FRAME_INTERNAL_BORDER_WIDTH (f);
5151 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
5152 }
5153 else
5154 {
5155 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5156 area_width = window_box_width (w, area);
5157 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
5158 }
5159
5160 /* Build a doubly-linked list of glyph_string structures between
5161 head and tail from what we have to draw. Note that the macro
5162 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5163 the reason we use a separate variable `i'. */
5164 i = start;
5165 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5166 overlaps_p);
5167 if (tail)
5168 x_reached = tail->x + tail->background_width;
5169 else
5170 x_reached = x;
5171
5172 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5173 the row, redraw some glyphs in front or following the glyph
5174 strings built above. */
5175 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
5176 {
5177 int dummy_x = 0;
5178 struct glyph_string *h, *t;
5179
5180 /* Compute overhangs for all glyph strings. */
5181 for (s = head; s; s = s->next)
5182 x_compute_glyph_string_overhangs (s);
5183
5184 /* Prepend glyph strings for glyphs in front of the first glyph
5185 string that are overwritten because of the first glyph
5186 string's left overhang. The background of all strings
5187 prepended must be drawn because the first glyph string
5188 draws over it. */
5189 i = x_left_overwritten (head);
5190 if (i >= 0)
5191 {
5192 j = i;
5193 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
5194 DRAW_NORMAL_TEXT, dummy_x, last_x,
5195 overlaps_p);
5196 start = i;
5197 x_compute_overhangs_and_x (t, head->x, 1);
5198 x_prepend_glyph_string_lists (&head, &tail, h, t);
5199 }
5200
5201 /* Prepend glyph strings for glyphs in front of the first glyph
5202 string that overwrite that glyph string because of their
5203 right overhang. For these strings, only the foreground must
5204 be drawn, because it draws over the glyph string at `head'.
5205 The background must not be drawn because this would overwrite
5206 right overhangs of preceding glyphs for which no glyph
5207 strings exist. */
5208 i = x_left_overwriting (head);
5209 if (i >= 0)
5210 {
5211 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
5212 DRAW_NORMAL_TEXT, dummy_x, last_x,
5213 overlaps_p);
5214 for (s = h; s; s = s->next)
5215 s->background_filled_p = 1;
5216 x_compute_overhangs_and_x (t, head->x, 1);
5217 x_prepend_glyph_string_lists (&head, &tail, h, t);
5218 }
5219
5220 /* Append glyphs strings for glyphs following the last glyph
5221 string tail that are overwritten by tail. The background of
5222 these strings has to be drawn because tail's foreground draws
5223 over it. */
5224 i = x_right_overwritten (tail);
5225 if (i >= 0)
5226 {
5227 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5228 DRAW_NORMAL_TEXT, x, last_x,
5229 overlaps_p);
5230 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5231 x_append_glyph_string_lists (&head, &tail, h, t);
5232 }
5233
5234 /* Append glyph strings for glyphs following the last glyph
5235 string tail that overwrite tail. The foreground of such
5236 glyphs has to be drawn because it writes into the background
5237 of tail. The background must not be drawn because it could
5238 paint over the foreground of following glyphs. */
5239 i = x_right_overwriting (tail);
5240 if (i >= 0)
5241 {
5242 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
5243 DRAW_NORMAL_TEXT, x, last_x,
5244 overlaps_p);
5245 for (s = h; s; s = s->next)
5246 s->background_filled_p = 1;
5247 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5248 x_append_glyph_string_lists (&head, &tail, h, t);
5249 }
5250 }
5251
5252 /* Draw all strings. */
5253 for (s = head; s; s = s->next)
5254 x_draw_glyph_string (s);
5255
5256 if (area == TEXT_AREA
5257 && !row->full_width_p
5258 /* When drawing overlapping rows, only the glyph strings'
5259 foreground is drawn, which doesn't erase a cursor
5260 completely. */
5261 && !overlaps_p)
5262 {
5263 int x0 = head ? head->x : x;
5264 int x1 = tail ? tail->x + tail->background_width : x;
5265
5266 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5267 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5268
5269 if (XFASTINT (w->left_margin_width) != 0)
5270 {
5271 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5272 x0 -= left_area_width;
5273 x1 -= left_area_width;
5274 }
5275
5276 notice_overwritten_cursor (w, area, x0, x1,
5277 row->y, MATRIX_ROW_BOTTOM_Y (row));
5278 }
5279
5280 /* Value is the x-position up to which drawn, relative to AREA of W.
5281 This doesn't include parts drawn because of overhangs. */
5282 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5283 if (!row->full_width_p)
5284 {
5285 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
5286 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5287 if (area > TEXT_AREA)
5288 x_reached -= window_box_width (w, TEXT_AREA);
5289 }
5290
5291 return x_reached;
5292 }
5293
5294
5295 /* Fix the display of area AREA of overlapping row ROW in window W. */
5296
5297 static void
5298 x_fix_overlapping_area (w, row, area)
5299 struct window *w;
5300 struct glyph_row *row;
5301 enum glyph_row_area area;
5302 {
5303 int i, x;
5304
5305 BLOCK_INPUT;
5306
5307 if (area == LEFT_MARGIN_AREA)
5308 x = 0;
5309 else if (area == TEXT_AREA)
5310 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5311 else
5312 x = (window_box_width (w, LEFT_MARGIN_AREA)
5313 + window_box_width (w, TEXT_AREA));
5314
5315 for (i = 0; i < row->used[area];)
5316 {
5317 if (row->glyphs[area][i].overlaps_vertically_p)
5318 {
5319 int start = i, start_x = x;
5320
5321 do
5322 {
5323 x += row->glyphs[area][i].pixel_width;
5324 ++i;
5325 }
5326 while (i < row->used[area]
5327 && row->glyphs[area][i].overlaps_vertically_p);
5328
5329 x_draw_glyphs (w, start_x, row, area, start, i,
5330 DRAW_NORMAL_TEXT, 1);
5331 }
5332 else
5333 {
5334 x += row->glyphs[area][i].pixel_width;
5335 ++i;
5336 }
5337 }
5338
5339 UNBLOCK_INPUT;
5340 }
5341
5342
5343 /* Output LEN glyphs starting at START at the nominal cursor position.
5344 Advance the nominal cursor over the text. The global variable
5345 updated_window contains the window being updated, updated_row is
5346 the glyph row being updated, and updated_area is the area of that
5347 row being updated. */
5348
5349 static void
5350 x_write_glyphs (start, len)
5351 struct glyph *start;
5352 int len;
5353 {
5354 int x, hpos;
5355
5356 xassert (updated_window && updated_row);
5357 BLOCK_INPUT;
5358
5359 /* Write glyphs. */
5360
5361 hpos = start - updated_row->glyphs[updated_area];
5362 x = x_draw_glyphs (updated_window, output_cursor.x,
5363 updated_row, updated_area,
5364 hpos, hpos + len,
5365 DRAW_NORMAL_TEXT, 0);
5366
5367 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
5368 if (updated_area == TEXT_AREA
5369 && updated_window->phys_cursor_on_p
5370 && updated_window->phys_cursor.vpos == output_cursor.vpos
5371 && updated_window->phys_cursor.hpos >= hpos
5372 && updated_window->phys_cursor.hpos < hpos + len)
5373 updated_window->phys_cursor_on_p = 0;
5374
5375 UNBLOCK_INPUT;
5376
5377 /* Advance the output cursor. */
5378 output_cursor.hpos += len;
5379 output_cursor.x = x;
5380 }
5381
5382
5383 /* Insert LEN glyphs from START at the nominal cursor position. */
5384
5385 static void
5386 x_insert_glyphs (start, len)
5387 struct glyph *start;
5388 register int len;
5389 {
5390 struct frame *f;
5391 struct window *w;
5392 int line_height, shift_by_width, shifted_region_width;
5393 struct glyph_row *row;
5394 struct glyph *glyph;
5395 int frame_x, frame_y, hpos;
5396
5397 xassert (updated_window && updated_row);
5398 BLOCK_INPUT;
5399 w = updated_window;
5400 f = XFRAME (WINDOW_FRAME (w));
5401
5402 /* Get the height of the line we are in. */
5403 row = updated_row;
5404 line_height = row->height;
5405
5406 /* Get the width of the glyphs to insert. */
5407 shift_by_width = 0;
5408 for (glyph = start; glyph < start + len; ++glyph)
5409 shift_by_width += glyph->pixel_width;
5410
5411 /* Get the width of the region to shift right. */
5412 shifted_region_width = (window_box_width (w, updated_area)
5413 - output_cursor.x
5414 - shift_by_width);
5415
5416 /* Shift right. */
5417 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5418 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5419 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5420 f->output_data.x->normal_gc,
5421 frame_x, frame_y,
5422 shifted_region_width, line_height,
5423 frame_x + shift_by_width, frame_y);
5424
5425 /* Write the glyphs. */
5426 hpos = start - row->glyphs[updated_area];
5427 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5428 DRAW_NORMAL_TEXT, 0);
5429
5430 /* Advance the output cursor. */
5431 output_cursor.hpos += len;
5432 output_cursor.x += shift_by_width;
5433 UNBLOCK_INPUT;
5434 }
5435
5436
5437 /* Delete N glyphs at the nominal cursor position. Not implemented
5438 for X frames. */
5439
5440 static void
5441 x_delete_glyphs (n)
5442 register int n;
5443 {
5444 abort ();
5445 }
5446
5447
5448 /* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5449 If they are <= 0, this is probably an error. */
5450
5451 void
5452 x_clear_area (dpy, window, x, y, width, height, exposures)
5453 Display *dpy;
5454 Window window;
5455 int x, y;
5456 int width, height;
5457 int exposures;
5458 {
5459 xassert (width > 0 && height > 0);
5460 XClearArea (dpy, window, x, y, width, height, exposures);
5461 }
5462
5463
5464 /* Erase the current text line from the nominal cursor position
5465 (inclusive) to pixel column TO_X (exclusive). The idea is that
5466 everything from TO_X onward is already erased.
5467
5468 TO_X is a pixel position relative to updated_area of
5469 updated_window. TO_X == -1 means clear to the end of this area. */
5470
5471 static void
5472 x_clear_end_of_line (to_x)
5473 int to_x;
5474 {
5475 struct frame *f;
5476 struct window *w = updated_window;
5477 int max_x, min_y, max_y;
5478 int from_x, from_y, to_y;
5479
5480 xassert (updated_window && updated_row);
5481 f = XFRAME (w->frame);
5482
5483 if (updated_row->full_width_p)
5484 {
5485 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5486 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5487 && !w->pseudo_window_p)
5488 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5489 }
5490 else
5491 max_x = window_box_width (w, updated_area);
5492 max_y = window_text_bottom_y (w);
5493
5494 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5495 of window. For TO_X > 0, truncate to end of drawing area. */
5496 if (to_x == 0)
5497 return;
5498 else if (to_x < 0)
5499 to_x = max_x;
5500 else
5501 to_x = min (to_x, max_x);
5502
5503 to_y = min (max_y, output_cursor.y + updated_row->height);
5504
5505 /* Notice if the cursor will be cleared by this operation. */
5506 if (!updated_row->full_width_p)
5507 notice_overwritten_cursor (w, updated_area,
5508 output_cursor.x, -1,
5509 updated_row->y,
5510 MATRIX_ROW_BOTTOM_Y (updated_row));
5511
5512 from_x = output_cursor.x;
5513
5514 /* Translate to frame coordinates. */
5515 if (updated_row->full_width_p)
5516 {
5517 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5518 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5519 }
5520 else
5521 {
5522 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5523 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5524 }
5525
5526 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5527 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5528 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5529
5530 /* Prevent inadvertently clearing to end of the X window. */
5531 if (to_x > from_x && to_y > from_y)
5532 {
5533 BLOCK_INPUT;
5534 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5535 from_x, from_y, to_x - from_x, to_y - from_y,
5536 False);
5537 UNBLOCK_INPUT;
5538 }
5539 }
5540
5541
5542 /* Clear entire frame. If updating_frame is non-null, clear that
5543 frame. Otherwise clear the selected frame. */
5544
5545 static void
5546 x_clear_frame ()
5547 {
5548 struct frame *f;
5549
5550 if (updating_frame)
5551 f = updating_frame;
5552 else
5553 f = SELECTED_FRAME ();
5554
5555 /* Clearing the frame will erase any cursor, so mark them all as no
5556 longer visible. */
5557 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5558 output_cursor.hpos = output_cursor.vpos = 0;
5559 output_cursor.x = -1;
5560
5561 /* We don't set the output cursor here because there will always
5562 follow an explicit cursor_to. */
5563 BLOCK_INPUT;
5564 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5565
5566 /* We have to clear the scroll bars, too. If we have changed
5567 colors or something like that, then they should be notified. */
5568 x_scroll_bar_clear (f);
5569
5570 XFlush (FRAME_X_DISPLAY (f));
5571 UNBLOCK_INPUT;
5572 }
5573
5574
5575 \f
5576 /* Invert the middle quarter of the frame for .15 sec. */
5577
5578 /* We use the select system call to do the waiting, so we have to make
5579 sure it's available. If it isn't, we just won't do visual bells. */
5580
5581 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5582
5583
5584 /* Subtract the `struct timeval' values X and Y, storing the result in
5585 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5586
5587 static int
5588 timeval_subtract (result, x, y)
5589 struct timeval *result, x, y;
5590 {
5591 /* Perform the carry for the later subtraction by updating y. This
5592 is safer because on some systems the tv_sec member is unsigned. */
5593 if (x.tv_usec < y.tv_usec)
5594 {
5595 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5596 y.tv_usec -= 1000000 * nsec;
5597 y.tv_sec += nsec;
5598 }
5599
5600 if (x.tv_usec - y.tv_usec > 1000000)
5601 {
5602 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5603 y.tv_usec += 1000000 * nsec;
5604 y.tv_sec -= nsec;
5605 }
5606
5607 /* Compute the time remaining to wait. tv_usec is certainly
5608 positive. */
5609 result->tv_sec = x.tv_sec - y.tv_sec;
5610 result->tv_usec = x.tv_usec - y.tv_usec;
5611
5612 /* Return indication of whether the result should be considered
5613 negative. */
5614 return x.tv_sec < y.tv_sec;
5615 }
5616
5617 void
5618 XTflash (f)
5619 struct frame *f;
5620 {
5621 BLOCK_INPUT;
5622
5623 {
5624 GC gc;
5625
5626 /* Create a GC that will use the GXxor function to flip foreground
5627 pixels into background pixels. */
5628 {
5629 XGCValues values;
5630
5631 values.function = GXxor;
5632 values.foreground = (f->output_data.x->foreground_pixel
5633 ^ f->output_data.x->background_pixel);
5634
5635 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5636 GCFunction | GCForeground, &values);
5637 }
5638
5639 {
5640 /* Get the height not including a menu bar widget. */
5641 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5642 /* Height of each line to flash. */
5643 int flash_height = FRAME_LINE_HEIGHT (f);
5644 /* These will be the left and right margins of the rectangles. */
5645 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5646 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5647
5648 int width;
5649
5650 /* Don't flash the area between a scroll bar and the frame
5651 edge it is next to. */
5652 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5653 {
5654 case vertical_scroll_bar_left:
5655 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5656 break;
5657
5658 case vertical_scroll_bar_right:
5659 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5660 break;
5661
5662 default:
5663 break;
5664 }
5665
5666 width = flash_right - flash_left;
5667
5668 /* If window is tall, flash top and bottom line. */
5669 if (height > 3 * FRAME_LINE_HEIGHT (f))
5670 {
5671 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5672 flash_left,
5673 (FRAME_INTERNAL_BORDER_WIDTH (f)
5674 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5675 width, flash_height);
5676 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5677 flash_left,
5678 (height - flash_height
5679 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5680 width, flash_height);
5681 }
5682 else
5683 /* If it is short, flash it all. */
5684 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5685 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5686 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5687
5688 x_flush (f);
5689
5690 {
5691 struct timeval wakeup;
5692
5693 EMACS_GET_TIME (wakeup);
5694
5695 /* Compute time to wait until, propagating carry from usecs. */
5696 wakeup.tv_usec += 150000;
5697 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5698 wakeup.tv_usec %= 1000000;
5699
5700 /* Keep waiting until past the time wakeup or any input gets
5701 available. */
5702 while (! detect_input_pending ())
5703 {
5704 struct timeval current;
5705 struct timeval timeout;
5706
5707 EMACS_GET_TIME (current);
5708
5709 /* Break if result would be negative. */
5710 if (timeval_subtract (&current, wakeup, current))
5711 break;
5712
5713 /* How long `select' should wait. */
5714 timeout.tv_sec = 0;
5715 timeout.tv_usec = 10000;
5716
5717 /* Try to wait that long--but we might wake up sooner. */
5718 select (0, NULL, NULL, NULL, &timeout);
5719 }
5720 }
5721
5722 /* If window is tall, flash top and bottom line. */
5723 if (height > 3 * FRAME_LINE_HEIGHT (f))
5724 {
5725 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5726 flash_left,
5727 (FRAME_INTERNAL_BORDER_WIDTH (f)
5728 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5729 width, flash_height);
5730 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5731 flash_left,
5732 (height - flash_height
5733 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5734 width, flash_height);
5735 }
5736 else
5737 /* If it is short, flash it all. */
5738 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5739 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5740 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5741
5742 XFreeGC (FRAME_X_DISPLAY (f), gc);
5743 x_flush (f);
5744 }
5745 }
5746
5747 UNBLOCK_INPUT;
5748 }
5749
5750 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5751
5752
5753 /* Make audible bell. */
5754
5755 void
5756 XTring_bell ()
5757 {
5758 struct frame *f = SELECTED_FRAME ();
5759
5760 if (FRAME_X_DISPLAY (f))
5761 {
5762 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5763 if (visible_bell)
5764 XTflash (f);
5765 else
5766 #endif
5767 {
5768 BLOCK_INPUT;
5769 XBell (FRAME_X_DISPLAY (f), 0);
5770 XFlush (FRAME_X_DISPLAY (f));
5771 UNBLOCK_INPUT;
5772 }
5773 }
5774 }
5775
5776 \f
5777 /* Specify how many text lines, from the top of the window,
5778 should be affected by insert-lines and delete-lines operations.
5779 This, and those operations, are used only within an update
5780 that is bounded by calls to x_update_begin and x_update_end. */
5781
5782 static void
5783 XTset_terminal_window (n)
5784 register int n;
5785 {
5786 /* This function intentionally left blank. */
5787 }
5788
5789
5790 \f
5791 /***********************************************************************
5792 Line Dance
5793 ***********************************************************************/
5794
5795 /* Perform an insert-lines or delete-lines operation, inserting N
5796 lines or deleting -N lines at vertical position VPOS. */
5797
5798 static void
5799 x_ins_del_lines (vpos, n)
5800 int vpos, n;
5801 {
5802 abort ();
5803 }
5804
5805
5806 /* Scroll part of the display as described by RUN. */
5807
5808 static void
5809 x_scroll_run (w, run)
5810 struct window *w;
5811 struct run *run;
5812 {
5813 struct frame *f = XFRAME (w->frame);
5814 int x, y, width, height, from_y, to_y, bottom_y;
5815
5816 /* Get frame-relative bounding box of the text display area of W,
5817 without mode lines. Include in this box the left and right
5818 fringe of W. */
5819 window_box (w, -1, &x, &y, &width, &height);
5820 width += FRAME_X_FRINGE_WIDTH (f);
5821 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5822
5823 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5824 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5825 bottom_y = y + height;
5826
5827 if (to_y < from_y)
5828 {
5829 /* Scrolling up. Make sure we don't copy part of the mode
5830 line at the bottom. */
5831 if (from_y + run->height > bottom_y)
5832 height = bottom_y - from_y;
5833 else
5834 height = run->height;
5835 }
5836 else
5837 {
5838 /* Scolling down. Make sure we don't copy over the mode line.
5839 at the bottom. */
5840 if (to_y + run->height > bottom_y)
5841 height = bottom_y - to_y;
5842 else
5843 height = run->height;
5844 }
5845
5846 BLOCK_INPUT;
5847
5848 /* Cursor off. Will be switched on again in x_update_window_end. */
5849 updated_window = w;
5850 x_clear_cursor (w);
5851
5852 XCopyArea (FRAME_X_DISPLAY (f),
5853 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5854 f->output_data.x->normal_gc,
5855 x, from_y,
5856 width, height,
5857 x, to_y);
5858
5859 UNBLOCK_INPUT;
5860 }
5861
5862
5863 \f
5864 /***********************************************************************
5865 Exposure Events
5866 ***********************************************************************/
5867
5868 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5869 corner of the exposed rectangle. W and H are width and height of
5870 the exposed area. All are pixel values. W or H zero means redraw
5871 the entire frame. */
5872
5873 static void
5874 expose_frame (f, x, y, w, h)
5875 struct frame *f;
5876 int x, y, w, h;
5877 {
5878 XRectangle r;
5879 int mouse_face_overwritten_p = 0;
5880
5881 TRACE ((stderr, "expose_frame "));
5882
5883 /* No need to redraw if frame will be redrawn soon. */
5884 if (FRAME_GARBAGED_P (f))
5885 {
5886 TRACE ((stderr, " garbaged\n"));
5887 return;
5888 }
5889
5890 /* If basic faces haven't been realized yet, there is no point in
5891 trying to redraw anything. This can happen when we get an expose
5892 event while Emacs is starting, e.g. by moving another window. */
5893 if (FRAME_FACE_CACHE (f) == NULL
5894 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5895 {
5896 TRACE ((stderr, " no faces\n"));
5897 return;
5898 }
5899
5900 if (w == 0 || h == 0)
5901 {
5902 r.x = r.y = 0;
5903 r.width = CANON_X_UNIT (f) * f->width;
5904 r.height = CANON_Y_UNIT (f) * f->height;
5905 }
5906 else
5907 {
5908 r.x = x;
5909 r.y = y;
5910 r.width = w;
5911 r.height = h;
5912 }
5913
5914 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5915 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5916
5917 if (WINDOWP (f->tool_bar_window))
5918 mouse_face_overwritten_p
5919 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5920
5921 #ifndef USE_X_TOOLKIT
5922 if (WINDOWP (f->menu_bar_window))
5923 mouse_face_overwritten_p
5924 |= expose_window (XWINDOW (f->menu_bar_window), &r);
5925 #endif /* not USE_X_TOOLKIT */
5926
5927 /* Some window managers support a focus-follows-mouse style with
5928 delayed raising of frames. Imagine a partially obscured frame,
5929 and moving the mouse into partially obscured mouse-face on that
5930 frame. The visible part of the mouse-face will be highlighted,
5931 then the WM raises the obscured frame. With at least one WM, KDE
5932 2.1, Emacs is not getting any event for the raising of the frame
5933 (even tried with SubstructureRedirectMask), only Expose events.
5934 These expose events will draw text normally, i.e. not
5935 highlighted. Which means we must redo the highlight here.
5936 Subsume it under ``we love X''. --gerd 2001-08-15 */
5937 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5938 {
5939 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5940 if (f == dpyinfo->mouse_face_mouse_frame)
5941 {
5942 int x = dpyinfo->mouse_face_mouse_x;
5943 int y = dpyinfo->mouse_face_mouse_y;
5944 clear_mouse_face (dpyinfo);
5945 note_mouse_highlight (f, x, y);
5946 }
5947 }
5948 }
5949
5950
5951 /* Redraw (parts) of all windows in the window tree rooted at W that
5952 intersect R. R contains frame pixel coordinates. Value is
5953 non-zero if the exposure overwrites mouse-face. */
5954
5955 static int
5956 expose_window_tree (w, r)
5957 struct window *w;
5958 XRectangle *r;
5959 {
5960 struct frame *f = XFRAME (w->frame);
5961 int mouse_face_overwritten_p = 0;
5962
5963 while (w && !FRAME_GARBAGED_P (f))
5964 {
5965 if (!NILP (w->hchild))
5966 mouse_face_overwritten_p
5967 |= expose_window_tree (XWINDOW (w->hchild), r);
5968 else if (!NILP (w->vchild))
5969 mouse_face_overwritten_p
5970 |= expose_window_tree (XWINDOW (w->vchild), r);
5971 else
5972 mouse_face_overwritten_p |= expose_window (w, r);
5973
5974 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5975 }
5976
5977 return mouse_face_overwritten_p;
5978 }
5979
5980
5981 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5982 which intersects rectangle R. R is in window-relative coordinates. */
5983
5984 static void
5985 expose_area (w, row, r, area)
5986 struct window *w;
5987 struct glyph_row *row;
5988 XRectangle *r;
5989 enum glyph_row_area area;
5990 {
5991 struct glyph *first = row->glyphs[area];
5992 struct glyph *end = row->glyphs[area] + row->used[area];
5993 struct glyph *last;
5994 int first_x, start_x, x;
5995
5996 if (area == TEXT_AREA && row->fill_line_p)
5997 /* If row extends face to end of line write the whole line. */
5998 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
5999 DRAW_NORMAL_TEXT, 0);
6000 else
6001 {
6002 /* Set START_X to the window-relative start position for drawing glyphs of
6003 AREA. The first glyph of the text area can be partially visible.
6004 The first glyphs of other areas cannot. */
6005 if (area == LEFT_MARGIN_AREA)
6006 start_x = 0;
6007 else if (area == TEXT_AREA)
6008 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
6009 else
6010 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
6011 + window_box_width (w, TEXT_AREA));
6012 x = start_x;
6013
6014 /* Find the first glyph that must be redrawn. */
6015 while (first < end
6016 && x + first->pixel_width < r->x)
6017 {
6018 x += first->pixel_width;
6019 ++first;
6020 }
6021
6022 /* Find the last one. */
6023 last = first;
6024 first_x = x;
6025 while (last < end
6026 && x < r->x + r->width)
6027 {
6028 x += last->pixel_width;
6029 ++last;
6030 }
6031
6032 /* Repaint. */
6033 if (last > first)
6034 x_draw_glyphs (w, first_x - start_x, row, area,
6035 first - row->glyphs[area],
6036 last - row->glyphs[area],
6037 DRAW_NORMAL_TEXT, 0);
6038 }
6039 }
6040
6041
6042 /* Redraw the parts of the glyph row ROW on window W intersecting
6043 rectangle R. R is in window-relative coordinates. Value is
6044 non-zero if mouse-face was overwritten. */
6045
6046 static int
6047 expose_line (w, row, r)
6048 struct window *w;
6049 struct glyph_row *row;
6050 XRectangle *r;
6051 {
6052 xassert (row->enabled_p);
6053
6054 if (row->mode_line_p || w->pseudo_window_p)
6055 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
6056 DRAW_NORMAL_TEXT, 0);
6057 else
6058 {
6059 if (row->used[LEFT_MARGIN_AREA])
6060 expose_area (w, row, r, LEFT_MARGIN_AREA);
6061 if (row->used[TEXT_AREA])
6062 expose_area (w, row, r, TEXT_AREA);
6063 if (row->used[RIGHT_MARGIN_AREA])
6064 expose_area (w, row, r, RIGHT_MARGIN_AREA);
6065 x_draw_row_fringe_bitmaps (w, row);
6066 }
6067
6068 return row->mouse_face_p;
6069 }
6070
6071
6072 /* Return non-zero if W's cursor intersects rectangle R. */
6073
6074 static int
6075 x_phys_cursor_in_rect_p (w, r)
6076 struct window *w;
6077 XRectangle *r;
6078 {
6079 XRectangle cr, result;
6080 struct glyph *cursor_glyph;
6081
6082 cursor_glyph = get_phys_cursor_glyph (w);
6083 if (cursor_glyph)
6084 {
6085 cr.x = w->phys_cursor.x;
6086 cr.y = w->phys_cursor.y;
6087 cr.width = cursor_glyph->pixel_width;
6088 cr.height = w->phys_cursor_height;
6089 return x_intersect_rectangles (&cr, r, &result);
6090 }
6091 else
6092 return 0;
6093 }
6094
6095
6096 /* Redraw those parts of glyphs rows during expose event handling that
6097 overlap other rows. Redrawing of an exposed line writes over parts
6098 of lines overlapping that exposed line; this function fixes that.
6099
6100 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
6101 row in W's current matrix that is exposed and overlaps other rows.
6102 LAST_OVERLAPPING_ROW is the last such row. */
6103
6104 static void
6105 expose_overlaps (w, first_overlapping_row, last_overlapping_row)
6106 struct window *w;
6107 struct glyph_row *first_overlapping_row;
6108 struct glyph_row *last_overlapping_row;
6109 {
6110 struct glyph_row *row;
6111
6112 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
6113 if (row->overlapping_p)
6114 {
6115 xassert (row->enabled_p && !row->mode_line_p);
6116
6117 if (row->used[LEFT_MARGIN_AREA])
6118 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
6119
6120 if (row->used[TEXT_AREA])
6121 x_fix_overlapping_area (w, row, TEXT_AREA);
6122
6123 if (row->used[RIGHT_MARGIN_AREA])
6124 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
6125 }
6126 }
6127
6128
6129 /* Redraw the part of window W intersection rectangle FR. Pixel
6130 coordinates in FR are frame-relative. Call this function with
6131 input blocked. Value is non-zero if the exposure overwrites
6132 mouse-face. */
6133
6134 static int
6135 expose_window (w, fr)
6136 struct window *w;
6137 XRectangle *fr;
6138 {
6139 struct frame *f = XFRAME (w->frame);
6140 XRectangle wr, r;
6141 int mouse_face_overwritten_p = 0;
6142
6143 /* If window is not yet fully initialized, do nothing. This can
6144 happen when toolkit scroll bars are used and a window is split.
6145 Reconfiguring the scroll bar will generate an expose for a newly
6146 created window. */
6147 if (w->current_matrix == NULL)
6148 return 0;
6149
6150 /* When we're currently updating the window, display and current
6151 matrix usually don't agree. Arrange for a thorough display
6152 later. */
6153 if (w == updated_window)
6154 {
6155 SET_FRAME_GARBAGED (f);
6156 return 0;
6157 }
6158
6159 /* Frame-relative pixel rectangle of W. */
6160 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6161 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6162 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6163 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6164
6165 if (x_intersect_rectangles (fr, &wr, &r))
6166 {
6167 int yb = window_text_bottom_y (w);
6168 struct glyph_row *row;
6169 int cursor_cleared_p;
6170 struct glyph_row *first_overlapping_row, *last_overlapping_row;
6171
6172 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6173 r.x, r.y, r.width, r.height));
6174
6175 /* Convert to window coordinates. */
6176 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6177 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
6178
6179 /* Turn off the cursor. */
6180 if (!w->pseudo_window_p
6181 && x_phys_cursor_in_rect_p (w, &r))
6182 {
6183 x_clear_cursor (w);
6184 cursor_cleared_p = 1;
6185 }
6186 else
6187 cursor_cleared_p = 0;
6188
6189 /* Update lines intersecting rectangle R. */
6190 first_overlapping_row = last_overlapping_row = NULL;
6191 for (row = w->current_matrix->rows;
6192 row->enabled_p;
6193 ++row)
6194 {
6195 int y0 = row->y;
6196 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6197
6198 if ((y0 >= r.y && y0 < r.y + r.height)
6199 || (y1 > r.y && y1 < r.y + r.height)
6200 || (r.y >= y0 && r.y < y1)
6201 || (r.y + r.height > y0 && r.y + r.height < y1))
6202 {
6203 if (row->overlapping_p)
6204 {
6205 if (first_overlapping_row == NULL)
6206 first_overlapping_row = row;
6207 last_overlapping_row = row;
6208 }
6209
6210 if (expose_line (w, row, &r))
6211 mouse_face_overwritten_p = 1;
6212 }
6213
6214 if (y1 >= yb)
6215 break;
6216 }
6217
6218 /* Display the mode line if there is one. */
6219 if (WINDOW_WANTS_MODELINE_P (w)
6220 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6221 row->enabled_p)
6222 && row->y < r.y + r.height)
6223 {
6224 if (expose_line (w, row, &r))
6225 mouse_face_overwritten_p = 1;
6226 }
6227
6228 if (!w->pseudo_window_p)
6229 {
6230 /* Fix the display of overlapping rows. */
6231 if (first_overlapping_row)
6232 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
6233
6234 /* Draw border between windows. */
6235 x_draw_vertical_border (w);
6236
6237 /* Turn the cursor on again. */
6238 if (cursor_cleared_p)
6239 x_update_window_cursor (w, 1);
6240 }
6241 }
6242
6243 return mouse_face_overwritten_p;
6244 }
6245
6246
6247 /* Determine the intersection of two rectangles R1 and R2. Return
6248 the intersection in *RESULT. Value is non-zero if RESULT is not
6249 empty. */
6250
6251 static int
6252 x_intersect_rectangles (r1, r2, result)
6253 XRectangle *r1, *r2, *result;
6254 {
6255 XRectangle *left, *right;
6256 XRectangle *upper, *lower;
6257 int intersection_p = 0;
6258
6259 /* Rearrange so that R1 is the left-most rectangle. */
6260 if (r1->x < r2->x)
6261 left = r1, right = r2;
6262 else
6263 left = r2, right = r1;
6264
6265 /* X0 of the intersection is right.x0, if this is inside R1,
6266 otherwise there is no intersection. */
6267 if (right->x <= left->x + left->width)
6268 {
6269 result->x = right->x;
6270
6271 /* The right end of the intersection is the minimum of the
6272 the right ends of left and right. */
6273 result->width = (min (left->x + left->width, right->x + right->width)
6274 - result->x);
6275
6276 /* Same game for Y. */
6277 if (r1->y < r2->y)
6278 upper = r1, lower = r2;
6279 else
6280 upper = r2, lower = r1;
6281
6282 /* The upper end of the intersection is lower.y0, if this is inside
6283 of upper. Otherwise, there is no intersection. */
6284 if (lower->y <= upper->y + upper->height)
6285 {
6286 result->y = lower->y;
6287
6288 /* The lower end of the intersection is the minimum of the lower
6289 ends of upper and lower. */
6290 result->height = (min (lower->y + lower->height,
6291 upper->y + upper->height)
6292 - result->y);
6293 intersection_p = 1;
6294 }
6295 }
6296
6297 return intersection_p;
6298 }
6299
6300
6301
6302
6303 \f
6304 static void
6305 frame_highlight (f)
6306 struct frame *f;
6307 {
6308 /* We used to only do this if Vx_no_window_manager was non-nil, but
6309 the ICCCM (section 4.1.6) says that the window's border pixmap
6310 and border pixel are window attributes which are "private to the
6311 client", so we can always change it to whatever we want. */
6312 BLOCK_INPUT;
6313 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6314 f->output_data.x->border_pixel);
6315 UNBLOCK_INPUT;
6316 x_update_cursor (f, 1);
6317 }
6318
6319 static void
6320 frame_unhighlight (f)
6321 struct frame *f;
6322 {
6323 /* We used to only do this if Vx_no_window_manager was non-nil, but
6324 the ICCCM (section 4.1.6) says that the window's border pixmap
6325 and border pixel are window attributes which are "private to the
6326 client", so we can always change it to whatever we want. */
6327 BLOCK_INPUT;
6328 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6329 f->output_data.x->border_tile);
6330 UNBLOCK_INPUT;
6331 x_update_cursor (f, 1);
6332 }
6333
6334 /* The focus has changed. Update the frames as necessary to reflect
6335 the new situation. Note that we can't change the selected frame
6336 here, because the Lisp code we are interrupting might become confused.
6337 Each event gets marked with the frame in which it occurred, so the
6338 Lisp code can tell when the switch took place by examining the events. */
6339
6340 static void
6341 x_new_focus_frame (dpyinfo, frame)
6342 struct x_display_info *dpyinfo;
6343 struct frame *frame;
6344 {
6345 struct frame *old_focus = dpyinfo->x_focus_frame;
6346
6347 if (frame != dpyinfo->x_focus_frame)
6348 {
6349 /* Set this before calling other routines, so that they see
6350 the correct value of x_focus_frame. */
6351 dpyinfo->x_focus_frame = frame;
6352
6353 if (old_focus && old_focus->auto_lower)
6354 x_lower_frame (old_focus);
6355
6356 #if 0
6357 selected_frame = frame;
6358 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6359 selected_frame);
6360 Fselect_window (selected_frame->selected_window);
6361 choose_minibuf_frame ();
6362 #endif /* ! 0 */
6363
6364 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6365 pending_autoraise_frame = dpyinfo->x_focus_frame;
6366 else
6367 pending_autoraise_frame = 0;
6368 }
6369
6370 x_frame_rehighlight (dpyinfo);
6371 }
6372
6373 /* Handle FocusIn and FocusOut state changes for FRAME.
6374 If FRAME has focus and there exists more than one frame, puts
6375 a FOCUS_IN_EVENT into BUFP.
6376 Returns number of events inserted into BUFP. */
6377
6378 static int
6379 x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
6380 int type;
6381 int state;
6382 struct x_display_info *dpyinfo;
6383 struct frame *frame;
6384 struct input_event *bufp;
6385 int numchars;
6386 {
6387 int nr_events = 0;
6388
6389 if (type == FocusIn)
6390 {
6391 if (dpyinfo->x_focus_event_frame != frame)
6392 {
6393 x_new_focus_frame (dpyinfo, frame);
6394 dpyinfo->x_focus_event_frame = frame;
6395
6396 /* Don't stop displaying the initial startup message
6397 for a switch-frame event we don't need. */
6398 if (numchars > 0
6399 && GC_NILP (Vterminal_frame)
6400 && GC_CONSP (Vframe_list)
6401 && !GC_NILP (XCDR (Vframe_list)))
6402 {
6403 bufp->kind = FOCUS_IN_EVENT;
6404 XSETFRAME (bufp->frame_or_window, frame);
6405 bufp->arg = Qnil;
6406 ++bufp;
6407 numchars--;
6408 ++nr_events;
6409 }
6410 }
6411
6412 frame->output_data.x->focus_state |= state;
6413
6414 #ifdef HAVE_X_I18N
6415 if (FRAME_XIC (frame))
6416 XSetICFocus (FRAME_XIC (frame));
6417 #endif
6418 }
6419 else if (type == FocusOut)
6420 {
6421 frame->output_data.x->focus_state &= ~state;
6422
6423 if (dpyinfo->x_focus_event_frame == frame)
6424 {
6425 dpyinfo->x_focus_event_frame = 0;
6426 x_new_focus_frame (dpyinfo, 0);
6427 }
6428
6429 #ifdef HAVE_X_I18N
6430 if (FRAME_XIC (frame))
6431 XUnsetICFocus (FRAME_XIC (frame));
6432 #endif
6433 }
6434
6435 return nr_events;
6436 }
6437
6438 /* The focus may have changed. Figure out if it is a real focus change,
6439 by checking both FocusIn/Out and Enter/LeaveNotify events.
6440
6441 Returns number of events inserted into BUFP. */
6442
6443 static int
6444 x_detect_focus_change (dpyinfo, event, bufp, numchars)
6445 struct x_display_info *dpyinfo;
6446 XEvent *event;
6447 struct input_event *bufp;
6448 int numchars;
6449 {
6450 struct frame *frame;
6451 int nr_events = 0;
6452
6453 frame = x_top_window_to_frame (dpyinfo, event->xany.window);
6454 if (! frame) return nr_events;
6455
6456 switch (event->type)
6457 {
6458 case EnterNotify:
6459 case LeaveNotify:
6460 if (event->xcrossing.detail != NotifyInferior
6461 && event->xcrossing.focus
6462 && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
6463 nr_events = x_focus_changed ((event->type == EnterNotify
6464 ? FocusIn : FocusOut),
6465 FOCUS_IMPLICIT,
6466 dpyinfo,
6467 frame,
6468 bufp,
6469 numchars);
6470 break;
6471
6472 case FocusIn:
6473 case FocusOut:
6474 nr_events = x_focus_changed (event->type,
6475 (event->xfocus.detail == NotifyPointer
6476 ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
6477 dpyinfo,
6478 frame,
6479 bufp,
6480 numchars);
6481 break;
6482 }
6483
6484 return nr_events;
6485 }
6486
6487
6488 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6489
6490 void
6491 x_mouse_leave (dpyinfo)
6492 struct x_display_info *dpyinfo;
6493 {
6494 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6495 }
6496
6497 /* The focus has changed, or we have redirected a frame's focus to
6498 another frame (this happens when a frame uses a surrogate
6499 mini-buffer frame). Shift the highlight as appropriate.
6500
6501 The FRAME argument doesn't necessarily have anything to do with which
6502 frame is being highlighted or un-highlighted; we only use it to find
6503 the appropriate X display info. */
6504
6505 static void
6506 XTframe_rehighlight (frame)
6507 struct frame *frame;
6508 {
6509 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6510 }
6511
6512 static void
6513 x_frame_rehighlight (dpyinfo)
6514 struct x_display_info *dpyinfo;
6515 {
6516 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6517
6518 if (dpyinfo->x_focus_frame)
6519 {
6520 dpyinfo->x_highlight_frame
6521 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6522 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6523 : dpyinfo->x_focus_frame);
6524 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6525 {
6526 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6527 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6528 }
6529 }
6530 else
6531 dpyinfo->x_highlight_frame = 0;
6532
6533 if (dpyinfo->x_highlight_frame != old_highlight)
6534 {
6535 if (old_highlight)
6536 frame_unhighlight (old_highlight);
6537 if (dpyinfo->x_highlight_frame)
6538 frame_highlight (dpyinfo->x_highlight_frame);
6539 }
6540 }
6541
6542
6543 \f
6544 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6545
6546 /* Initialize mode_switch_bit and modifier_meaning. */
6547 static void
6548 x_find_modifier_meanings (dpyinfo)
6549 struct x_display_info *dpyinfo;
6550 {
6551 int min_code, max_code;
6552 KeySym *syms;
6553 int syms_per_code;
6554 XModifierKeymap *mods;
6555
6556 dpyinfo->meta_mod_mask = 0;
6557 dpyinfo->shift_lock_mask = 0;
6558 dpyinfo->alt_mod_mask = 0;
6559 dpyinfo->super_mod_mask = 0;
6560 dpyinfo->hyper_mod_mask = 0;
6561
6562 #ifdef HAVE_X11R4
6563 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6564 #else
6565 min_code = dpyinfo->display->min_keycode;
6566 max_code = dpyinfo->display->max_keycode;
6567 #endif
6568
6569 syms = XGetKeyboardMapping (dpyinfo->display,
6570 min_code, max_code - min_code + 1,
6571 &syms_per_code);
6572 mods = XGetModifierMapping (dpyinfo->display);
6573
6574 /* Scan the modifier table to see which modifier bits the Meta and
6575 Alt keysyms are on. */
6576 {
6577 int row, col; /* The row and column in the modifier table. */
6578
6579 for (row = 3; row < 8; row++)
6580 for (col = 0; col < mods->max_keypermod; col++)
6581 {
6582 KeyCode code
6583 = mods->modifiermap[(row * mods->max_keypermod) + col];
6584
6585 /* Zeroes are used for filler. Skip them. */
6586 if (code == 0)
6587 continue;
6588
6589 /* Are any of this keycode's keysyms a meta key? */
6590 {
6591 int code_col;
6592
6593 for (code_col = 0; code_col < syms_per_code; code_col++)
6594 {
6595 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6596
6597 switch (sym)
6598 {
6599 case XK_Meta_L:
6600 case XK_Meta_R:
6601 dpyinfo->meta_mod_mask |= (1 << row);
6602 break;
6603
6604 case XK_Alt_L:
6605 case XK_Alt_R:
6606 dpyinfo->alt_mod_mask |= (1 << row);
6607 break;
6608
6609 case XK_Hyper_L:
6610 case XK_Hyper_R:
6611 dpyinfo->hyper_mod_mask |= (1 << row);
6612 break;
6613
6614 case XK_Super_L:
6615 case XK_Super_R:
6616 dpyinfo->super_mod_mask |= (1 << row);
6617 break;
6618
6619 case XK_Shift_Lock:
6620 /* Ignore this if it's not on the lock modifier. */
6621 if ((1 << row) == LockMask)
6622 dpyinfo->shift_lock_mask = LockMask;
6623 break;
6624 }
6625 }
6626 }
6627 }
6628 }
6629
6630 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6631 if (! dpyinfo->meta_mod_mask)
6632 {
6633 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6634 dpyinfo->alt_mod_mask = 0;
6635 }
6636
6637 /* If some keys are both alt and meta,
6638 make them just meta, not alt. */
6639 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6640 {
6641 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6642 }
6643
6644 XFree ((char *) syms);
6645 XFreeModifiermap (mods);
6646 }
6647
6648 /* Convert between the modifier bits X uses and the modifier bits
6649 Emacs uses. */
6650
6651 static unsigned int
6652 x_x_to_emacs_modifiers (dpyinfo, state)
6653 struct x_display_info *dpyinfo;
6654 unsigned int state;
6655 {
6656 EMACS_UINT mod_meta = meta_modifier;
6657 EMACS_UINT mod_alt = alt_modifier;
6658 EMACS_UINT mod_hyper = hyper_modifier;
6659 EMACS_UINT mod_super = super_modifier;
6660 Lisp_Object tem;
6661
6662 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6663 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6664 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6665 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6666 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6667 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6668 tem = Fget (Vx_super_keysym, Qmodifier_value);
6669 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6670
6671
6672 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6673 | ((state & ControlMask) ? ctrl_modifier : 0)
6674 | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
6675 | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
6676 | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
6677 | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
6678 }
6679
6680 static unsigned int
6681 x_emacs_to_x_modifiers (dpyinfo, state)
6682 struct x_display_info *dpyinfo;
6683 unsigned int state;
6684 {
6685 EMACS_UINT mod_meta = meta_modifier;
6686 EMACS_UINT mod_alt = alt_modifier;
6687 EMACS_UINT mod_hyper = hyper_modifier;
6688 EMACS_UINT mod_super = super_modifier;
6689
6690 Lisp_Object tem;
6691
6692 tem = Fget (Vx_alt_keysym, Qmodifier_value);
6693 if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
6694 tem = Fget (Vx_meta_keysym, Qmodifier_value);
6695 if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
6696 tem = Fget (Vx_hyper_keysym, Qmodifier_value);
6697 if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
6698 tem = Fget (Vx_super_keysym, Qmodifier_value);
6699 if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
6700
6701
6702 return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
6703 | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
6704 | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
6705 | ((state & shift_modifier) ? ShiftMask : 0)
6706 | ((state & ctrl_modifier) ? ControlMask : 0)
6707 | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
6708 }
6709
6710 /* Convert a keysym to its name. */
6711
6712 char *
6713 x_get_keysym_name (keysym)
6714 KeySym keysym;
6715 {
6716 char *value;
6717
6718 BLOCK_INPUT;
6719 value = XKeysymToString (keysym);
6720 UNBLOCK_INPUT;
6721
6722 return value;
6723 }
6724
6725
6726 \f
6727 /* Mouse clicks and mouse movement. Rah. */
6728
6729 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6730 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6731 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6732 not force the value into range. */
6733
6734 void
6735 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6736 FRAME_PTR f;
6737 register int pix_x, pix_y;
6738 register int *x, *y;
6739 XRectangle *bounds;
6740 int noclip;
6741 {
6742 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6743 even for negative values. */
6744 if (pix_x < 0)
6745 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6746 if (pix_y < 0)
6747 pix_y -= (f)->output_data.x->line_height - 1;
6748
6749 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6750 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6751
6752 if (bounds)
6753 {
6754 bounds->width = FONT_WIDTH (f->output_data.x->font);
6755 bounds->height = f->output_data.x->line_height;
6756 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6757 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6758 }
6759
6760 if (!noclip)
6761 {
6762 if (pix_x < 0)
6763 pix_x = 0;
6764 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6765 pix_x = FRAME_WINDOW_WIDTH (f);
6766
6767 if (pix_y < 0)
6768 pix_y = 0;
6769 else if (pix_y > f->height)
6770 pix_y = f->height;
6771 }
6772
6773 *x = pix_x;
6774 *y = pix_y;
6775 }
6776
6777
6778 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6779 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6780 can't tell the positions because W's display is not up to date,
6781 return 0. */
6782
6783 int
6784 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6785 struct window *w;
6786 int hpos, vpos;
6787 int *frame_x, *frame_y;
6788 {
6789 int success_p;
6790
6791 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6792 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6793
6794 if (display_completed)
6795 {
6796 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6797 struct glyph *glyph = row->glyphs[TEXT_AREA];
6798 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6799
6800 *frame_y = row->y;
6801 *frame_x = row->x;
6802 while (glyph < end)
6803 {
6804 *frame_x += glyph->pixel_width;
6805 ++glyph;
6806 }
6807
6808 success_p = 1;
6809 }
6810 else
6811 {
6812 *frame_y = *frame_x = 0;
6813 success_p = 0;
6814 }
6815
6816 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6817 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6818 return success_p;
6819 }
6820
6821
6822 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6823
6824 If the event is a button press, then note that we have grabbed
6825 the mouse. */
6826
6827 static Lisp_Object
6828 construct_mouse_click (result, event, f)
6829 struct input_event *result;
6830 XButtonEvent *event;
6831 struct frame *f;
6832 {
6833 /* Make the event type NO_EVENT; we'll change that when we decide
6834 otherwise. */
6835 result->kind = MOUSE_CLICK_EVENT;
6836 result->code = event->button - Button1;
6837 result->timestamp = event->time;
6838 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6839 event->state)
6840 | (event->type == ButtonRelease
6841 ? up_modifier
6842 : down_modifier));
6843
6844 XSETINT (result->x, event->x);
6845 XSETINT (result->y, event->y);
6846 XSETFRAME (result->frame_or_window, f);
6847 result->arg = Qnil;
6848 return Qnil;
6849 }
6850
6851 \f
6852 /* Function to report a mouse movement to the mainstream Emacs code.
6853 The input handler calls this.
6854
6855 We have received a mouse movement event, which is given in *event.
6856 If the mouse is over a different glyph than it was last time, tell
6857 the mainstream emacs code by setting mouse_moved. If not, ask for
6858 another motion event, so we can check again the next time it moves. */
6859
6860 static XMotionEvent last_mouse_motion_event;
6861 static Lisp_Object last_mouse_motion_frame;
6862
6863 static void
6864 note_mouse_movement (frame, event)
6865 FRAME_PTR frame;
6866 XMotionEvent *event;
6867 {
6868 last_mouse_movement_time = event->time;
6869 last_mouse_motion_event = *event;
6870 XSETFRAME (last_mouse_motion_frame, frame);
6871
6872 if (event->window != FRAME_X_WINDOW (frame))
6873 {
6874 frame->mouse_moved = 1;
6875 last_mouse_scroll_bar = Qnil;
6876 note_mouse_highlight (frame, -1, -1);
6877 }
6878
6879 /* Has the mouse moved off the glyph it was on at the last sighting? */
6880 else if (event->x < last_mouse_glyph.x
6881 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6882 || event->y < last_mouse_glyph.y
6883 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6884 {
6885 frame->mouse_moved = 1;
6886 last_mouse_scroll_bar = Qnil;
6887 note_mouse_highlight (frame, event->x, event->y);
6888 }
6889 }
6890
6891 \f
6892 /************************************************************************
6893 Mouse Face
6894 ************************************************************************/
6895
6896 /* Find the glyph under window-relative coordinates X/Y in window W.
6897 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6898 strings. Return in *HPOS and *VPOS the row and column number of
6899 the glyph found. Return in *AREA the glyph area containing X.
6900 Value is a pointer to the glyph found or null if X/Y is not on
6901 text, or we can't tell because W's current matrix is not up to
6902 date. */
6903
6904 static struct glyph *
6905 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6906 struct window *w;
6907 int x, y;
6908 int *hpos, *vpos, *area;
6909 int buffer_only_p;
6910 {
6911 struct glyph *glyph, *end;
6912 struct glyph_row *row = NULL;
6913 int x0, i, left_area_width;
6914
6915 /* Find row containing Y. Give up if some row is not enabled. */
6916 for (i = 0; i < w->current_matrix->nrows; ++i)
6917 {
6918 row = MATRIX_ROW (w->current_matrix, i);
6919 if (!row->enabled_p)
6920 return NULL;
6921 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6922 break;
6923 }
6924
6925 *vpos = i;
6926 *hpos = 0;
6927
6928 /* Give up if Y is not in the window. */
6929 if (i == w->current_matrix->nrows)
6930 return NULL;
6931
6932 /* Get the glyph area containing X. */
6933 if (w->pseudo_window_p)
6934 {
6935 *area = TEXT_AREA;
6936 x0 = 0;
6937 }
6938 else
6939 {
6940 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6941 if (x < left_area_width)
6942 {
6943 *area = LEFT_MARGIN_AREA;
6944 x0 = 0;
6945 }
6946 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6947 {
6948 *area = TEXT_AREA;
6949 x0 = row->x + left_area_width;
6950 }
6951 else
6952 {
6953 *area = RIGHT_MARGIN_AREA;
6954 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6955 }
6956 }
6957
6958 /* Find glyph containing X. */
6959 glyph = row->glyphs[*area];
6960 end = glyph + row->used[*area];
6961 while (glyph < end)
6962 {
6963 if (x < x0 + glyph->pixel_width)
6964 {
6965 if (w->pseudo_window_p)
6966 break;
6967 else if (!buffer_only_p || BUFFERP (glyph->object))
6968 break;
6969 }
6970
6971 x0 += glyph->pixel_width;
6972 ++glyph;
6973 }
6974
6975 if (glyph == end)
6976 return NULL;
6977
6978 *hpos = glyph - row->glyphs[*area];
6979 return glyph;
6980 }
6981
6982
6983 /* Convert frame-relative x/y to coordinates relative to window W.
6984 Takes pseudo-windows into account. */
6985
6986 static void
6987 frame_to_window_pixel_xy (w, x, y)
6988 struct window *w;
6989 int *x, *y;
6990 {
6991 if (w->pseudo_window_p)
6992 {
6993 /* A pseudo-window is always full-width, and starts at the
6994 left edge of the frame, plus a frame border. */
6995 struct frame *f = XFRAME (w->frame);
6996 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6997 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6998 }
6999 else
7000 {
7001 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
7002 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
7003 }
7004 }
7005
7006
7007 /* Take proper action when mouse has moved to the mode or header line
7008 or marginal area of window W, x-position X and y-position Y. Area
7009 is 1, 3, 6 or 7 for the mode line, header line, left and right
7010 marginal area respectively. X is relative to the start of the text
7011 display area of W, so the width of bitmap areas and scroll bars
7012 must be subtracted to get a position relative to the start of the
7013 mode line. */
7014
7015 static void
7016 note_mode_line_or_margin_highlight (w, x, y, portion)
7017 struct window *w;
7018 int x, y, portion;
7019 {
7020 struct frame *f = XFRAME (w->frame);
7021 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7022 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
7023 int charpos;
7024 Lisp_Object string, help, map, pos;
7025
7026 if (portion == 1 || portion == 3)
7027 string = mode_line_string (w, x, y, portion == 1, &charpos);
7028 else
7029 string = marginal_area_string (w, x, y, portion, &charpos);
7030
7031 if (STRINGP (string))
7032 {
7033 pos = make_number (charpos);
7034
7035 /* If we're on a string with `help-echo' text property, arrange
7036 for the help to be displayed. This is done by setting the
7037 global variable help_echo to the help string. */
7038 help = Fget_text_property (pos, Qhelp_echo, string);
7039 if (!NILP (help))
7040 {
7041 help_echo = help;
7042 XSETWINDOW (help_echo_window, w);
7043 help_echo_object = string;
7044 help_echo_pos = charpos;
7045 }
7046
7047 /* Change the mouse pointer according to what is under X/Y. */
7048 map = Fget_text_property (pos, Qlocal_map, string);
7049 if (!KEYMAPP (map))
7050 map = Fget_text_property (pos, Qkeymap, string);
7051 if (KEYMAPP (map))
7052 cursor = f->output_data.x->nontext_cursor;
7053 }
7054
7055 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7056 }
7057
7058
7059 /* Take proper action when the mouse has moved to position X, Y on
7060 frame F as regards highlighting characters that have mouse-face
7061 properties. Also de-highlighting chars where the mouse was before.
7062 X and Y can be negative or out of range. */
7063
7064 static void
7065 note_mouse_highlight (f, x, y)
7066 struct frame *f;
7067 int x, y;
7068 {
7069 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7070 int portion;
7071 Lisp_Object window;
7072 struct window *w;
7073 Cursor cursor = None;
7074 struct buffer *b;
7075
7076 /* When a menu is active, don't highlight because this looks odd. */
7077 #ifdef USE_X_TOOLKIT
7078 if (popup_activated ())
7079 return;
7080 #endif
7081
7082 if (NILP (Vmouse_highlight)
7083 || !f->glyphs_initialized_p)
7084 return;
7085
7086 dpyinfo->mouse_face_mouse_x = x;
7087 dpyinfo->mouse_face_mouse_y = y;
7088 dpyinfo->mouse_face_mouse_frame = f;
7089
7090 if (dpyinfo->mouse_face_defer)
7091 return;
7092
7093 if (gc_in_progress)
7094 {
7095 dpyinfo->mouse_face_deferred_gc = 1;
7096 return;
7097 }
7098
7099 /* Which window is that in? */
7100 window = window_from_coordinates (f, x, y, &portion, 1);
7101
7102 /* If we were displaying active text in another window, clear that. */
7103 if (! EQ (window, dpyinfo->mouse_face_window))
7104 clear_mouse_face (dpyinfo);
7105
7106 /* Not on a window -> return. */
7107 if (!WINDOWP (window))
7108 return;
7109
7110 /* Convert to window-relative pixel coordinates. */
7111 w = XWINDOW (window);
7112 frame_to_window_pixel_xy (w, &x, &y);
7113
7114 /* Handle tool-bar window differently since it doesn't display a
7115 buffer. */
7116 if (EQ (window, f->tool_bar_window))
7117 {
7118 note_tool_bar_highlight (f, x, y);
7119 return;
7120 }
7121
7122 /* Mouse is on the mode, header line or margin? */
7123 if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
7124 {
7125 note_mode_line_or_margin_highlight (w, x, y, portion);
7126 return;
7127 }
7128
7129 if (portion == 2)
7130 cursor = f->output_data.x->horizontal_drag_cursor;
7131 else
7132 cursor = f->output_data.x->text_cursor;
7133
7134 /* Are we in a window whose display is up to date?
7135 And verify the buffer's text has not changed. */
7136 b = XBUFFER (w->buffer);
7137 if (/* Within text portion of the window. */
7138 portion == 0
7139 && EQ (w->window_end_valid, w->buffer)
7140 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
7141 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
7142 {
7143 int hpos, vpos, pos, i, area;
7144 struct glyph *glyph;
7145 Lisp_Object object;
7146 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
7147 Lisp_Object *overlay_vec = NULL;
7148 int len, noverlays;
7149 struct buffer *obuf;
7150 int obegv, ozv, same_region;
7151
7152 /* Find the glyph under X/Y. */
7153 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
7154
7155 /* Clear mouse face if X/Y not over text. */
7156 if (glyph == NULL
7157 || area != TEXT_AREA
7158 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
7159 {
7160 if (clear_mouse_face (dpyinfo))
7161 cursor = None;
7162 goto set_cursor;
7163 }
7164
7165 pos = glyph->charpos;
7166 object = glyph->object;
7167 if (!STRINGP (object) && !BUFFERP (object))
7168 goto set_cursor;
7169
7170 /* If we get an out-of-range value, return now; avoid an error. */
7171 if (BUFFERP (object) && pos > BUF_Z (b))
7172 goto set_cursor;
7173
7174 /* Make the window's buffer temporarily current for
7175 overlays_at and compute_char_face. */
7176 obuf = current_buffer;
7177 current_buffer = b;
7178 obegv = BEGV;
7179 ozv = ZV;
7180 BEGV = BEG;
7181 ZV = Z;
7182
7183 /* Is this char mouse-active or does it have help-echo? */
7184 position = make_number (pos);
7185
7186 if (BUFFERP (object))
7187 {
7188 /* Put all the overlays we want in a vector in overlay_vec.
7189 Store the length in len. If there are more than 10, make
7190 enough space for all, and try again. */
7191 len = 10;
7192 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7193 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
7194 if (noverlays > len)
7195 {
7196 len = noverlays;
7197 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
7198 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
7199 }
7200
7201 /* Sort overlays into increasing priority order. */
7202 noverlays = sort_overlays (overlay_vec, noverlays, w);
7203 }
7204 else
7205 noverlays = 0;
7206
7207 same_region = (EQ (window, dpyinfo->mouse_face_window)
7208 && vpos >= dpyinfo->mouse_face_beg_row
7209 && vpos <= dpyinfo->mouse_face_end_row
7210 && (vpos > dpyinfo->mouse_face_beg_row
7211 || hpos >= dpyinfo->mouse_face_beg_col)
7212 && (vpos < dpyinfo->mouse_face_end_row
7213 || hpos < dpyinfo->mouse_face_end_col
7214 || dpyinfo->mouse_face_past_end));
7215
7216 if (same_region)
7217 cursor = None;
7218
7219 /* Check mouse-face highlighting. */
7220 if (! same_region
7221 /* If there exists an overlay with mouse-face overlapping
7222 the one we are currently highlighting, we have to
7223 check if we enter the overlapping overlay, and then
7224 highlight only that. */
7225 || (OVERLAYP (dpyinfo->mouse_face_overlay)
7226 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
7227 {
7228 /* Find the highest priority overlay that has a mouse-face
7229 property. */
7230 overlay = Qnil;
7231 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
7232 {
7233 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
7234 if (!NILP (mouse_face))
7235 overlay = overlay_vec[i];
7236 }
7237
7238 /* If we're actually highlighting the same overlay as
7239 before, there's no need to do that again. */
7240 if (!NILP (overlay)
7241 && EQ (overlay, dpyinfo->mouse_face_overlay))
7242 goto check_help_echo;
7243
7244 dpyinfo->mouse_face_overlay = overlay;
7245
7246 /* Clear the display of the old active region, if any. */
7247 if (clear_mouse_face (dpyinfo))
7248 cursor = None;
7249
7250 /* If no overlay applies, get a text property. */
7251 if (NILP (overlay))
7252 mouse_face = Fget_text_property (position, Qmouse_face, object);
7253
7254 /* Handle the overlay case. */
7255 if (!NILP (overlay))
7256 {
7257 /* Find the range of text around this char that
7258 should be active. */
7259 Lisp_Object before, after;
7260 int ignore;
7261
7262 before = Foverlay_start (overlay);
7263 after = Foverlay_end (overlay);
7264 /* Record this as the current active region. */
7265 fast_find_position (w, XFASTINT (before),
7266 &dpyinfo->mouse_face_beg_col,
7267 &dpyinfo->mouse_face_beg_row,
7268 &dpyinfo->mouse_face_beg_x,
7269 &dpyinfo->mouse_face_beg_y, Qnil);
7270
7271 dpyinfo->mouse_face_past_end
7272 = !fast_find_position (w, XFASTINT (after),
7273 &dpyinfo->mouse_face_end_col,
7274 &dpyinfo->mouse_face_end_row,
7275 &dpyinfo->mouse_face_end_x,
7276 &dpyinfo->mouse_face_end_y, Qnil);
7277 dpyinfo->mouse_face_window = window;
7278 dpyinfo->mouse_face_face_id
7279 = face_at_buffer_position (w, pos, 0, 0,
7280 &ignore, pos + 1,
7281 !dpyinfo->mouse_face_hidden);
7282
7283 /* Display it as active. */
7284 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7285 cursor = None;
7286 }
7287 /* Handle the text property case. */
7288 else if (!NILP (mouse_face) && BUFFERP (object))
7289 {
7290 /* Find the range of text around this char that
7291 should be active. */
7292 Lisp_Object before, after, beginning, end;
7293 int ignore;
7294
7295 beginning = Fmarker_position (w->start);
7296 end = make_number (BUF_Z (XBUFFER (object))
7297 - XFASTINT (w->window_end_pos));
7298 before
7299 = Fprevious_single_property_change (make_number (pos + 1),
7300 Qmouse_face,
7301 object, beginning);
7302 after
7303 = Fnext_single_property_change (position, Qmouse_face,
7304 object, end);
7305
7306 /* Record this as the current active region. */
7307 fast_find_position (w, XFASTINT (before),
7308 &dpyinfo->mouse_face_beg_col,
7309 &dpyinfo->mouse_face_beg_row,
7310 &dpyinfo->mouse_face_beg_x,
7311 &dpyinfo->mouse_face_beg_y, Qnil);
7312 dpyinfo->mouse_face_past_end
7313 = !fast_find_position (w, XFASTINT (after),
7314 &dpyinfo->mouse_face_end_col,
7315 &dpyinfo->mouse_face_end_row,
7316 &dpyinfo->mouse_face_end_x,
7317 &dpyinfo->mouse_face_end_y, Qnil);
7318 dpyinfo->mouse_face_window = window;
7319
7320 if (BUFFERP (object))
7321 dpyinfo->mouse_face_face_id
7322 = face_at_buffer_position (w, pos, 0, 0,
7323 &ignore, pos + 1,
7324 !dpyinfo->mouse_face_hidden);
7325
7326 /* Display it as active. */
7327 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7328 cursor = None;
7329 }
7330 else if (!NILP (mouse_face) && STRINGP (object))
7331 {
7332 Lisp_Object b, e;
7333 int ignore;
7334
7335 b = Fprevious_single_property_change (make_number (pos + 1),
7336 Qmouse_face,
7337 object, Qnil);
7338 e = Fnext_single_property_change (position, Qmouse_face,
7339 object, Qnil);
7340 if (NILP (b))
7341 b = make_number (0);
7342 if (NILP (e))
7343 e = make_number (SCHARS (object) - 1);
7344 fast_find_string_pos (w, XINT (b), object,
7345 &dpyinfo->mouse_face_beg_col,
7346 &dpyinfo->mouse_face_beg_row,
7347 &dpyinfo->mouse_face_beg_x,
7348 &dpyinfo->mouse_face_beg_y, 0);
7349 fast_find_string_pos (w, XINT (e), object,
7350 &dpyinfo->mouse_face_end_col,
7351 &dpyinfo->mouse_face_end_row,
7352 &dpyinfo->mouse_face_end_x,
7353 &dpyinfo->mouse_face_end_y, 1);
7354 dpyinfo->mouse_face_past_end = 0;
7355 dpyinfo->mouse_face_window = window;
7356 dpyinfo->mouse_face_face_id
7357 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7358 glyph->face_id, 1);
7359 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7360 cursor = None;
7361 }
7362 else if (STRINGP (object) && NILP (mouse_face))
7363 {
7364 /* A string which doesn't have mouse-face, but
7365 the text ``under'' it might have. */
7366 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7367 int start = MATRIX_ROW_START_CHARPOS (r);
7368
7369 pos = string_buffer_position (w, object, start);
7370 if (pos > 0)
7371 mouse_face = get_char_property_and_overlay (make_number (pos),
7372 Qmouse_face,
7373 w->buffer,
7374 &overlay);
7375 if (!NILP (mouse_face) && !NILP (overlay))
7376 {
7377 Lisp_Object before = Foverlay_start (overlay);
7378 Lisp_Object after = Foverlay_end (overlay);
7379 int ignore;
7380
7381 /* Note that we might not be able to find position
7382 BEFORE in the glyph matrix if the overlay is
7383 entirely covered by a `display' property. In
7384 this case, we overshoot. So let's stop in
7385 the glyph matrix before glyphs for OBJECT. */
7386 fast_find_position (w, XFASTINT (before),
7387 &dpyinfo->mouse_face_beg_col,
7388 &dpyinfo->mouse_face_beg_row,
7389 &dpyinfo->mouse_face_beg_x,
7390 &dpyinfo->mouse_face_beg_y,
7391 object);
7392
7393 dpyinfo->mouse_face_past_end
7394 = !fast_find_position (w, XFASTINT (after),
7395 &dpyinfo->mouse_face_end_col,
7396 &dpyinfo->mouse_face_end_row,
7397 &dpyinfo->mouse_face_end_x,
7398 &dpyinfo->mouse_face_end_y,
7399 Qnil);
7400 dpyinfo->mouse_face_window = window;
7401 dpyinfo->mouse_face_face_id
7402 = face_at_buffer_position (w, pos, 0, 0,
7403 &ignore, pos + 1,
7404 !dpyinfo->mouse_face_hidden);
7405
7406 /* Display it as active. */
7407 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7408 cursor = None;
7409 }
7410 }
7411 }
7412
7413 check_help_echo:
7414
7415 /* Look for a `help-echo' property. */
7416 {
7417 Lisp_Object help, overlay;
7418
7419 /* Check overlays first. */
7420 help = overlay = Qnil;
7421 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7422 {
7423 overlay = overlay_vec[i];
7424 help = Foverlay_get (overlay, Qhelp_echo);
7425 }
7426
7427 if (!NILP (help))
7428 {
7429 help_echo = help;
7430 help_echo_window = window;
7431 help_echo_object = overlay;
7432 help_echo_pos = pos;
7433 }
7434 else
7435 {
7436 Lisp_Object object = glyph->object;
7437 int charpos = glyph->charpos;
7438
7439 /* Try text properties. */
7440 if (STRINGP (object)
7441 && charpos >= 0
7442 && charpos < SCHARS (object))
7443 {
7444 help = Fget_text_property (make_number (charpos),
7445 Qhelp_echo, object);
7446 if (NILP (help))
7447 {
7448 /* If the string itself doesn't specify a help-echo,
7449 see if the buffer text ``under'' it does. */
7450 struct glyph_row *r
7451 = MATRIX_ROW (w->current_matrix, vpos);
7452 int start = MATRIX_ROW_START_CHARPOS (r);
7453 int pos = string_buffer_position (w, object, start);
7454 if (pos > 0)
7455 {
7456 help = Fget_char_property (make_number (pos),
7457 Qhelp_echo, w->buffer);
7458 if (!NILP (help))
7459 {
7460 charpos = pos;
7461 object = w->buffer;
7462 }
7463 }
7464 }
7465 }
7466 else if (BUFFERP (object)
7467 && charpos >= BEGV
7468 && charpos < ZV)
7469 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7470 object);
7471
7472 if (!NILP (help))
7473 {
7474 help_echo = help;
7475 help_echo_window = window;
7476 help_echo_object = object;
7477 help_echo_pos = charpos;
7478 }
7479 }
7480 }
7481
7482 BEGV = obegv;
7483 ZV = ozv;
7484 current_buffer = obuf;
7485 }
7486
7487 set_cursor:
7488
7489 if (cursor != None)
7490 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
7491 }
7492
7493 static void
7494 redo_mouse_highlight ()
7495 {
7496 if (!NILP (last_mouse_motion_frame)
7497 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7498 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7499 last_mouse_motion_event.x,
7500 last_mouse_motion_event.y);
7501 }
7502
7503
7504 \f
7505 /***********************************************************************
7506 Tool-bars
7507 ***********************************************************************/
7508
7509 static int x_tool_bar_item P_ ((struct frame *, int, int,
7510 struct glyph **, int *, int *, int *));
7511
7512 /* Tool-bar item index of the item on which a mouse button was pressed
7513 or -1. */
7514
7515 static int last_tool_bar_item;
7516
7517
7518 /* Get information about the tool-bar item at position X/Y on frame F.
7519 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7520 the current matrix of the tool-bar window of F, or NULL if not
7521 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
7522 item in F->tool_bar_items. Value is
7523
7524 -1 if X/Y is not on a tool-bar item
7525 0 if X/Y is on the same item that was highlighted before.
7526 1 otherwise. */
7527
7528 static int
7529 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
7530 struct frame *f;
7531 int x, y;
7532 struct glyph **glyph;
7533 int *hpos, *vpos, *prop_idx;
7534 {
7535 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7536 struct window *w = XWINDOW (f->tool_bar_window);
7537 int area;
7538
7539 /* Find the glyph under X/Y. */
7540 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
7541 if (*glyph == NULL)
7542 return -1;
7543
7544 /* Get the start of this tool-bar item's properties in
7545 f->tool_bar_items. */
7546 if (!tool_bar_item_info (f, *glyph, prop_idx))
7547 return -1;
7548
7549 /* Is mouse on the highlighted item? */
7550 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
7551 && *vpos >= dpyinfo->mouse_face_beg_row
7552 && *vpos <= dpyinfo->mouse_face_end_row
7553 && (*vpos > dpyinfo->mouse_face_beg_row
7554 || *hpos >= dpyinfo->mouse_face_beg_col)
7555 && (*vpos < dpyinfo->mouse_face_end_row
7556 || *hpos < dpyinfo->mouse_face_end_col
7557 || dpyinfo->mouse_face_past_end))
7558 return 0;
7559
7560 return 1;
7561 }
7562
7563
7564 /* Handle mouse button event on the tool-bar of frame F, at
7565 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
7566 or ButtonRelase. */
7567
7568 static void
7569 x_handle_tool_bar_click (f, button_event)
7570 struct frame *f;
7571 XButtonEvent *button_event;
7572 {
7573 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7574 struct window *w = XWINDOW (f->tool_bar_window);
7575 int hpos, vpos, prop_idx;
7576 struct glyph *glyph;
7577 Lisp_Object enabled_p;
7578 int x = button_event->x;
7579 int y = button_event->y;
7580
7581 /* If not on the highlighted tool-bar item, return. */
7582 frame_to_window_pixel_xy (w, &x, &y);
7583 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
7584 return;
7585
7586 /* If item is disabled, do nothing. */
7587 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7588 if (NILP (enabled_p))
7589 return;
7590
7591 if (button_event->type == ButtonPress)
7592 {
7593 /* Show item in pressed state. */
7594 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7595 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7596 last_tool_bar_item = prop_idx;
7597 }
7598 else
7599 {
7600 Lisp_Object key, frame;
7601 struct input_event event;
7602
7603 /* Show item in released state. */
7604 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7605 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7606
7607 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7608
7609 XSETFRAME (frame, f);
7610 event.kind = TOOL_BAR_EVENT;
7611 event.frame_or_window = frame;
7612 event.arg = frame;
7613 kbd_buffer_store_event (&event);
7614
7615 event.kind = TOOL_BAR_EVENT;
7616 event.frame_or_window = frame;
7617 event.arg = key;
7618 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7619 button_event->state);
7620 kbd_buffer_store_event (&event);
7621 last_tool_bar_item = -1;
7622 }
7623 }
7624
7625
7626 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7627 tool-bar window-relative coordinates X/Y. Called from
7628 note_mouse_highlight. */
7629
7630 static void
7631 note_tool_bar_highlight (f, x, y)
7632 struct frame *f;
7633 int x, y;
7634 {
7635 Lisp_Object window = f->tool_bar_window;
7636 struct window *w = XWINDOW (window);
7637 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7638 int hpos, vpos;
7639 struct glyph *glyph;
7640 struct glyph_row *row;
7641 int i;
7642 Lisp_Object enabled_p;
7643 int prop_idx;
7644 enum draw_glyphs_face draw;
7645 int mouse_down_p, rc;
7646
7647 /* Function note_mouse_highlight is called with negative x(y
7648 values when mouse moves outside of the frame. */
7649 if (x <= 0 || y <= 0)
7650 {
7651 clear_mouse_face (dpyinfo);
7652 return;
7653 }
7654
7655 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7656 if (rc < 0)
7657 {
7658 /* Not on tool-bar item. */
7659 clear_mouse_face (dpyinfo);
7660 return;
7661 }
7662 else if (rc == 0)
7663 goto set_help_echo;
7664
7665 clear_mouse_face (dpyinfo);
7666
7667 /* Mouse is down, but on different tool-bar item? */
7668 mouse_down_p = (dpyinfo->grabbed
7669 && f == last_mouse_frame
7670 && FRAME_LIVE_P (f));
7671 if (mouse_down_p
7672 && last_tool_bar_item != prop_idx)
7673 return;
7674
7675 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7676 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7677
7678 /* If tool-bar item is not enabled, don't highlight it. */
7679 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7680 if (!NILP (enabled_p))
7681 {
7682 /* Compute the x-position of the glyph. In front and past the
7683 image is a space. We include this is the highlighted area. */
7684 row = MATRIX_ROW (w->current_matrix, vpos);
7685 for (i = x = 0; i < hpos; ++i)
7686 x += row->glyphs[TEXT_AREA][i].pixel_width;
7687
7688 /* Record this as the current active region. */
7689 dpyinfo->mouse_face_beg_col = hpos;
7690 dpyinfo->mouse_face_beg_row = vpos;
7691 dpyinfo->mouse_face_beg_x = x;
7692 dpyinfo->mouse_face_beg_y = row->y;
7693 dpyinfo->mouse_face_past_end = 0;
7694
7695 dpyinfo->mouse_face_end_col = hpos + 1;
7696 dpyinfo->mouse_face_end_row = vpos;
7697 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7698 dpyinfo->mouse_face_end_y = row->y;
7699 dpyinfo->mouse_face_window = window;
7700 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7701
7702 /* Display it as active. */
7703 show_mouse_face (dpyinfo, draw);
7704 dpyinfo->mouse_face_image_state = draw;
7705 }
7706
7707 set_help_echo:
7708
7709 /* Set help_echo to a help string to display for this tool-bar item.
7710 XTread_socket does the rest. */
7711 help_echo_object = help_echo_window = Qnil;
7712 help_echo_pos = -1;
7713 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7714 if (NILP (help_echo))
7715 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7716 }
7717
7718
7719 \f
7720 /* Find the glyph matrix position of buffer position CHARPOS in window
7721 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7722 current glyphs must be up to date. If CHARPOS is above window
7723 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7724 of last line in W. In the row containing CHARPOS, stop before glyphs
7725 having STOP as object. */
7726
7727 #if 0 /* This is a version of fast_find_position that's more correct
7728 in the presence of hscrolling, for example. I didn't install
7729 it right away because the problem fixed is minor, it failed
7730 in 20.x as well, and I think it's too risky to install
7731 so near the release of 21.1. 2001-09-25 gerd. */
7732
7733 static int
7734 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7735 struct window *w;
7736 int charpos;
7737 int *hpos, *vpos, *x, *y;
7738 Lisp_Object stop;
7739 {
7740 struct glyph_row *row, *first;
7741 struct glyph *glyph, *end;
7742 int i, past_end = 0;
7743
7744 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7745 row = row_containing_pos (w, charpos, first, NULL, 0);
7746 if (row == NULL)
7747 {
7748 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7749 {
7750 *x = *y = *hpos = *vpos = 0;
7751 return 0;
7752 }
7753 else
7754 {
7755 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7756 past_end = 1;
7757 }
7758 }
7759
7760 *x = row->x;
7761 *y = row->y;
7762 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7763
7764 glyph = row->glyphs[TEXT_AREA];
7765 end = glyph + row->used[TEXT_AREA];
7766
7767 /* Skip over glyphs not having an object at the start of the row.
7768 These are special glyphs like truncation marks on terminal
7769 frames. */
7770 if (row->displays_text_p)
7771 while (glyph < end
7772 && INTEGERP (glyph->object)
7773 && !EQ (stop, glyph->object)
7774 && glyph->charpos < 0)
7775 {
7776 *x += glyph->pixel_width;
7777 ++glyph;
7778 }
7779
7780 while (glyph < end
7781 && !INTEGERP (glyph->object)
7782 && !EQ (stop, glyph->object)
7783 && (!BUFFERP (glyph->object)
7784 || glyph->charpos < charpos))
7785 {
7786 *x += glyph->pixel_width;
7787 ++glyph;
7788 }
7789
7790 *hpos = glyph - row->glyphs[TEXT_AREA];
7791 return past_end;
7792 }
7793
7794 #else /* not 0 */
7795
7796 static int
7797 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7798 struct window *w;
7799 int pos;
7800 int *hpos, *vpos, *x, *y;
7801 Lisp_Object stop;
7802 {
7803 int i;
7804 int lastcol;
7805 int maybe_next_line_p = 0;
7806 int line_start_position;
7807 int yb = window_text_bottom_y (w);
7808 struct glyph_row *row, *best_row;
7809 int row_vpos, best_row_vpos;
7810 int current_x;
7811
7812 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7813 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7814
7815 while (row->y < yb)
7816 {
7817 if (row->used[TEXT_AREA])
7818 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7819 else
7820 line_start_position = 0;
7821
7822 if (line_start_position > pos)
7823 break;
7824 /* If the position sought is the end of the buffer,
7825 don't include the blank lines at the bottom of the window. */
7826 else if (line_start_position == pos
7827 && pos == BUF_ZV (XBUFFER (w->buffer)))
7828 {
7829 maybe_next_line_p = 1;
7830 break;
7831 }
7832 else if (line_start_position > 0)
7833 {
7834 best_row = row;
7835 best_row_vpos = row_vpos;
7836 }
7837
7838 if (row->y + row->height >= yb)
7839 break;
7840
7841 ++row;
7842 ++row_vpos;
7843 }
7844
7845 /* Find the right column within BEST_ROW. */
7846 lastcol = 0;
7847 current_x = best_row->x;
7848 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7849 {
7850 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7851 int charpos = glyph->charpos;
7852
7853 if (BUFFERP (glyph->object))
7854 {
7855 if (charpos == pos)
7856 {
7857 *hpos = i;
7858 *vpos = best_row_vpos;
7859 *x = current_x;
7860 *y = best_row->y;
7861 return 1;
7862 }
7863 else if (charpos > pos)
7864 break;
7865 }
7866 else if (EQ (glyph->object, stop))
7867 break;
7868
7869 if (charpos > 0)
7870 lastcol = i;
7871 current_x += glyph->pixel_width;
7872 }
7873
7874 /* If we're looking for the end of the buffer,
7875 and we didn't find it in the line we scanned,
7876 use the start of the following line. */
7877 if (maybe_next_line_p)
7878 {
7879 ++best_row;
7880 ++best_row_vpos;
7881 lastcol = 0;
7882 current_x = best_row->x;
7883 }
7884
7885 *vpos = best_row_vpos;
7886 *hpos = lastcol + 1;
7887 *x = current_x;
7888 *y = best_row->y;
7889 return 0;
7890 }
7891
7892 #endif /* not 0 */
7893
7894
7895 /* Find the position of the glyph for position POS in OBJECT in
7896 window W's current matrix, and return in *X, *Y the pixel
7897 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
7898
7899 RIGHT_P non-zero means return the position of the right edge of the
7900 glyph, RIGHT_P zero means return the left edge position.
7901
7902 If no glyph for POS exists in the matrix, return the position of
7903 the glyph with the next smaller position that is in the matrix, if
7904 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7905 exists in the matrix, return the position of the glyph with the
7906 next larger position in OBJECT.
7907
7908 Value is non-zero if a glyph was found. */
7909
7910 static int
7911 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7912 struct window *w;
7913 int pos;
7914 Lisp_Object object;
7915 int *hpos, *vpos, *x, *y;
7916 int right_p;
7917 {
7918 int yb = window_text_bottom_y (w);
7919 struct glyph_row *r;
7920 struct glyph *best_glyph = NULL;
7921 struct glyph_row *best_row = NULL;
7922 int best_x = 0;
7923
7924 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7925 r->enabled_p && r->y < yb;
7926 ++r)
7927 {
7928 struct glyph *g = r->glyphs[TEXT_AREA];
7929 struct glyph *e = g + r->used[TEXT_AREA];
7930 int gx;
7931
7932 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7933 if (EQ (g->object, object))
7934 {
7935 if (g->charpos == pos)
7936 {
7937 best_glyph = g;
7938 best_x = gx;
7939 best_row = r;
7940 goto found;
7941 }
7942 else if (best_glyph == NULL
7943 || ((abs (g->charpos - pos)
7944 < abs (best_glyph->charpos - pos))
7945 && (right_p
7946 ? g->charpos < pos
7947 : g->charpos > pos)))
7948 {
7949 best_glyph = g;
7950 best_x = gx;
7951 best_row = r;
7952 }
7953 }
7954 }
7955
7956 found:
7957
7958 if (best_glyph)
7959 {
7960 *x = best_x;
7961 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7962
7963 if (right_p)
7964 {
7965 *x += best_glyph->pixel_width;
7966 ++*hpos;
7967 }
7968
7969 *y = best_row->y;
7970 *vpos = best_row - w->current_matrix->rows;
7971 }
7972
7973 return best_glyph != NULL;
7974 }
7975
7976
7977 /* Display the active region described by mouse_face_*
7978 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7979
7980 static void
7981 show_mouse_face (dpyinfo, draw)
7982 struct x_display_info *dpyinfo;
7983 enum draw_glyphs_face draw;
7984 {
7985 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7986 struct frame *f = XFRAME (WINDOW_FRAME (w));
7987
7988 if (/* If window is in the process of being destroyed, don't bother
7989 to do anything. */
7990 w->current_matrix != NULL
7991 /* Don't update mouse highlight if hidden */
7992 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
7993 /* Recognize when we are called to operate on rows that don't exist
7994 anymore. This can happen when a window is split. */
7995 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7996 {
7997 int phys_cursor_on_p = w->phys_cursor_on_p;
7998 struct glyph_row *row, *first, *last;
7999
8000 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
8001 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
8002
8003 for (row = first; row <= last && row->enabled_p; ++row)
8004 {
8005 int start_hpos, end_hpos, start_x;
8006
8007 /* For all but the first row, the highlight starts at column 0. */
8008 if (row == first)
8009 {
8010 start_hpos = dpyinfo->mouse_face_beg_col;
8011 start_x = dpyinfo->mouse_face_beg_x;
8012 }
8013 else
8014 {
8015 start_hpos = 0;
8016 start_x = 0;
8017 }
8018
8019 if (row == last)
8020 end_hpos = dpyinfo->mouse_face_end_col;
8021 else
8022 end_hpos = row->used[TEXT_AREA];
8023
8024 if (end_hpos > start_hpos)
8025 {
8026 x_draw_glyphs (w, start_x, row, TEXT_AREA,
8027 start_hpos, end_hpos, draw, 0);
8028
8029 row->mouse_face_p
8030 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
8031 }
8032 }
8033
8034 /* When we've written over the cursor, arrange for it to
8035 be displayed again. */
8036 if (phys_cursor_on_p && !w->phys_cursor_on_p)
8037 x_display_cursor (w, 1,
8038 w->phys_cursor.hpos, w->phys_cursor.vpos,
8039 w->phys_cursor.x, w->phys_cursor.y);
8040 }
8041
8042 /* Change the mouse cursor. */
8043 if (draw == DRAW_NORMAL_TEXT)
8044 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8045 f->output_data.x->text_cursor);
8046 else if (draw == DRAW_MOUSE_FACE)
8047 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8048 f->output_data.x->cross_cursor);
8049 else
8050 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8051 f->output_data.x->nontext_cursor);
8052 }
8053
8054 /* Clear out the mouse-highlighted active region.
8055 Redraw it un-highlighted first. Value is non-zero if mouse
8056 face was actually drawn unhighlighted. */
8057
8058 static int
8059 clear_mouse_face (dpyinfo)
8060 struct x_display_info *dpyinfo;
8061 {
8062 int cleared = 0;
8063
8064 if (!NILP (dpyinfo->mouse_face_window))
8065 {
8066 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
8067 cleared = 1;
8068 }
8069
8070 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8071 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8072 dpyinfo->mouse_face_window = Qnil;
8073 dpyinfo->mouse_face_overlay = Qnil;
8074 return cleared;
8075 }
8076
8077
8078 /* Clear any mouse-face on window W. This function is part of the
8079 redisplay interface, and is called from try_window_id and similar
8080 functions to ensure the mouse-highlight is off. */
8081
8082 static void
8083 x_clear_mouse_face (w)
8084 struct window *w;
8085 {
8086 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
8087 Lisp_Object window;
8088
8089 BLOCK_INPUT;
8090 XSETWINDOW (window, w);
8091 if (EQ (window, dpyinfo->mouse_face_window))
8092 clear_mouse_face (dpyinfo);
8093 UNBLOCK_INPUT;
8094 }
8095
8096
8097 /* Just discard the mouse face information for frame F, if any.
8098 This is used when the size of F is changed. */
8099
8100 void
8101 cancel_mouse_face (f)
8102 FRAME_PTR f;
8103 {
8104 Lisp_Object window;
8105 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8106
8107 window = dpyinfo->mouse_face_window;
8108 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
8109 {
8110 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8111 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8112 dpyinfo->mouse_face_window = Qnil;
8113 }
8114 }
8115
8116 \f
8117 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
8118
8119
8120 /* Try to determine frame pixel position and size of the glyph under
8121 frame pixel coordinates X/Y on frame F . Return the position and
8122 size in *RECT. Value is non-zero if we could compute these
8123 values. */
8124
8125 static int
8126 glyph_rect (f, x, y, rect)
8127 struct frame *f;
8128 int x, y;
8129 XRectangle *rect;
8130 {
8131 Lisp_Object window;
8132 int part, found = 0;
8133
8134 window = window_from_coordinates (f, x, y, &part, 0);
8135 if (!NILP (window))
8136 {
8137 struct window *w = XWINDOW (window);
8138 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
8139 struct glyph_row *end = r + w->current_matrix->nrows - 1;
8140
8141 frame_to_window_pixel_xy (w, &x, &y);
8142
8143 for (; !found && r < end && r->enabled_p; ++r)
8144 if (r->y >= y)
8145 {
8146 struct glyph *g = r->glyphs[TEXT_AREA];
8147 struct glyph *end = g + r->used[TEXT_AREA];
8148 int gx;
8149
8150 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
8151 if (gx >= x)
8152 {
8153 rect->width = g->pixel_width;
8154 rect->height = r->height;
8155 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
8156 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
8157 found = 1;
8158 }
8159 }
8160 }
8161
8162 return found;
8163 }
8164
8165
8166 /* Return the current position of the mouse.
8167 *FP should be a frame which indicates which display to ask about.
8168
8169 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
8170 and *PART to the frame, window, and scroll bar part that the mouse
8171 is over. Set *X and *Y to the portion and whole of the mouse's
8172 position on the scroll bar.
8173
8174 If the mouse movement started elsewhere, set *FP to the frame the
8175 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
8176 the mouse is over.
8177
8178 Set *TIME to the server time-stamp for the time at which the mouse
8179 was at this position.
8180
8181 Don't store anything if we don't have a valid set of values to report.
8182
8183 This clears the mouse_moved flag, so we can wait for the next mouse
8184 movement. */
8185
8186 static void
8187 XTmouse_position (fp, insist, bar_window, part, x, y, time)
8188 FRAME_PTR *fp;
8189 int insist;
8190 Lisp_Object *bar_window;
8191 enum scroll_bar_part *part;
8192 Lisp_Object *x, *y;
8193 unsigned long *time;
8194 {
8195 FRAME_PTR f1;
8196
8197 BLOCK_INPUT;
8198
8199 if (! NILP (last_mouse_scroll_bar) && insist == 0)
8200 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
8201 else
8202 {
8203 Window root;
8204 int root_x, root_y;
8205
8206 Window dummy_window;
8207 int dummy;
8208
8209 Lisp_Object frame, tail;
8210
8211 /* Clear the mouse-moved flag for every frame on this display. */
8212 FOR_EACH_FRAME (tail, frame)
8213 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
8214 XFRAME (frame)->mouse_moved = 0;
8215
8216 last_mouse_scroll_bar = Qnil;
8217
8218 /* Figure out which root window we're on. */
8219 XQueryPointer (FRAME_X_DISPLAY (*fp),
8220 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
8221
8222 /* The root window which contains the pointer. */
8223 &root,
8224
8225 /* Trash which we can't trust if the pointer is on
8226 a different screen. */
8227 &dummy_window,
8228
8229 /* The position on that root window. */
8230 &root_x, &root_y,
8231
8232 /* More trash we can't trust. */
8233 &dummy, &dummy,
8234
8235 /* Modifier keys and pointer buttons, about which
8236 we don't care. */
8237 (unsigned int *) &dummy);
8238
8239 /* Now we have a position on the root; find the innermost window
8240 containing the pointer. */
8241 {
8242 Window win, child;
8243 int win_x, win_y;
8244 int parent_x = 0, parent_y = 0;
8245 int count;
8246
8247 win = root;
8248
8249 /* XTranslateCoordinates can get errors if the window
8250 structure is changing at the same time this function
8251 is running. So at least we must not crash from them. */
8252
8253 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
8254
8255 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
8256 && FRAME_LIVE_P (last_mouse_frame))
8257 {
8258 /* If mouse was grabbed on a frame, give coords for that frame
8259 even if the mouse is now outside it. */
8260 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8261
8262 /* From-window, to-window. */
8263 root, FRAME_X_WINDOW (last_mouse_frame),
8264
8265 /* From-position, to-position. */
8266 root_x, root_y, &win_x, &win_y,
8267
8268 /* Child of win. */
8269 &child);
8270 f1 = last_mouse_frame;
8271 }
8272 else
8273 {
8274 while (1)
8275 {
8276 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
8277
8278 /* From-window, to-window. */
8279 root, win,
8280
8281 /* From-position, to-position. */
8282 root_x, root_y, &win_x, &win_y,
8283
8284 /* Child of win. */
8285 &child);
8286
8287 if (child == None || child == win)
8288 break;
8289
8290 win = child;
8291 parent_x = win_x;
8292 parent_y = win_y;
8293 }
8294
8295 /* Now we know that:
8296 win is the innermost window containing the pointer
8297 (XTC says it has no child containing the pointer),
8298 win_x and win_y are the pointer's position in it
8299 (XTC did this the last time through), and
8300 parent_x and parent_y are the pointer's position in win's parent.
8301 (They are what win_x and win_y were when win was child.
8302 If win is the root window, it has no parent, and
8303 parent_{x,y} are invalid, but that's okay, because we'll
8304 never use them in that case.) */
8305
8306 /* Is win one of our frames? */
8307 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
8308
8309 #ifdef USE_X_TOOLKIT
8310 /* If we end up with the menu bar window, say it's not
8311 on the frame. */
8312 if (f1 != NULL
8313 && f1->output_data.x->menubar_widget
8314 && win == XtWindow (f1->output_data.x->menubar_widget))
8315 f1 = NULL;
8316 #endif /* USE_X_TOOLKIT */
8317 }
8318
8319 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8320 f1 = 0;
8321
8322 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
8323
8324 /* If not, is it one of our scroll bars? */
8325 if (! f1)
8326 {
8327 struct scroll_bar *bar = x_window_to_scroll_bar (win);
8328
8329 if (bar)
8330 {
8331 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8332 win_x = parent_x;
8333 win_y = parent_y;
8334 }
8335 }
8336
8337 if (f1 == 0 && insist > 0)
8338 f1 = SELECTED_FRAME ();
8339
8340 if (f1)
8341 {
8342 /* Ok, we found a frame. Store all the values.
8343 last_mouse_glyph is a rectangle used to reduce the
8344 generation of mouse events. To not miss any motion
8345 events, we must divide the frame into rectangles of the
8346 size of the smallest character that could be displayed
8347 on it, i.e. into the same rectangles that matrices on
8348 the frame are divided into. */
8349
8350 int width, height, gx, gy;
8351 XRectangle rect;
8352
8353 if (glyph_rect (f1, win_x, win_y, &rect))
8354 last_mouse_glyph = rect;
8355 else
8356 {
8357 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8358 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8359 gx = win_x;
8360 gy = win_y;
8361
8362 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8363 round down even for negative values. */
8364 if (gx < 0)
8365 gx -= width - 1;
8366 if (gy < 0)
8367 gy -= height - 1;
8368 gx = (gx + width - 1) / width * width;
8369 gy = (gy + height - 1) / height * height;
8370
8371 last_mouse_glyph.width = width;
8372 last_mouse_glyph.height = height;
8373 last_mouse_glyph.x = gx;
8374 last_mouse_glyph.y = gy;
8375 }
8376
8377 *bar_window = Qnil;
8378 *part = 0;
8379 *fp = f1;
8380 XSETINT (*x, win_x);
8381 XSETINT (*y, win_y);
8382 *time = last_mouse_movement_time;
8383 }
8384 }
8385 }
8386
8387 UNBLOCK_INPUT;
8388 }
8389
8390
8391 #ifdef USE_X_TOOLKIT
8392
8393 /* Atimer callback function for TIMER. Called every 0.1s to process
8394 Xt timeouts, if needed. We must avoid calling XtAppPending as
8395 much as possible because that function does an implicit XFlush
8396 that slows us down. */
8397
8398 static void
8399 x_process_timeouts (timer)
8400 struct atimer *timer;
8401 {
8402 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8403 {
8404 BLOCK_INPUT;
8405 while (XtAppPending (Xt_app_con) & XtIMTimer)
8406 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8407 UNBLOCK_INPUT;
8408 }
8409 }
8410
8411 #endif /* USE_X_TOOLKIT */
8412
8413 \f
8414 /* Scroll bar support. */
8415
8416 /* Given an X window ID, find the struct scroll_bar which manages it.
8417 This can be called in GC, so we have to make sure to strip off mark
8418 bits. */
8419
8420 static struct scroll_bar *
8421 x_window_to_scroll_bar (window_id)
8422 Window window_id;
8423 {
8424 Lisp_Object tail;
8425
8426 for (tail = Vframe_list;
8427 XGCTYPE (tail) == Lisp_Cons;
8428 tail = XCDR (tail))
8429 {
8430 Lisp_Object frame, bar, condemned;
8431
8432 frame = XCAR (tail);
8433 /* All elements of Vframe_list should be frames. */
8434 if (! GC_FRAMEP (frame))
8435 abort ();
8436
8437 /* Scan this frame's scroll bar list for a scroll bar with the
8438 right window ID. */
8439 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8440 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8441 /* This trick allows us to search both the ordinary and
8442 condemned scroll bar lists with one loop. */
8443 ! GC_NILP (bar) || (bar = condemned,
8444 condemned = Qnil,
8445 ! GC_NILP (bar));
8446 bar = XSCROLL_BAR (bar)->next)
8447 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8448 return XSCROLL_BAR (bar);
8449 }
8450
8451 return 0;
8452 }
8453
8454
8455 #if defined USE_LUCID
8456
8457 /* Return the Lucid menu bar WINDOW is part of. Return null
8458 if WINDOW is not part of a menu bar. */
8459
8460 static Widget
8461 x_window_to_menu_bar (window)
8462 Window window;
8463 {
8464 Lisp_Object tail;
8465
8466 for (tail = Vframe_list;
8467 XGCTYPE (tail) == Lisp_Cons;
8468 tail = XCDR (tail))
8469 {
8470 Lisp_Object frame = XCAR (tail);
8471 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8472
8473 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8474 return menu_bar;
8475 }
8476
8477 return NULL;
8478 }
8479
8480 #endif /* USE_LUCID */
8481
8482 \f
8483 /************************************************************************
8484 Toolkit scroll bars
8485 ************************************************************************/
8486
8487 #ifdef USE_TOOLKIT_SCROLL_BARS
8488
8489 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8490 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8491 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8492 struct scroll_bar *));
8493 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8494 int, int, int));
8495
8496
8497 /* Id of action hook installed for scroll bars. */
8498
8499 static XtActionHookId action_hook_id;
8500
8501 /* Lisp window being scrolled. Set when starting to interact with
8502 a toolkit scroll bar, reset to nil when ending the interaction. */
8503
8504 static Lisp_Object window_being_scrolled;
8505
8506 /* Last scroll bar part sent in xm_scroll_callback. */
8507
8508 static int last_scroll_bar_part;
8509
8510 /* Whether this is an Xaw with arrow-scrollbars. This should imply
8511 that movements of 1/20 of the screen size are mapped to up/down. */
8512
8513 static Boolean xaw3d_arrow_scroll;
8514
8515 /* Whether the drag scrolling maintains the mouse at the top of the
8516 thumb. If not, resizing the thumb needs to be done more carefully
8517 to avoid jerkyness. */
8518
8519 static Boolean xaw3d_pick_top;
8520
8521
8522 /* Action hook installed via XtAppAddActionHook when toolkit scroll
8523 bars are used.. The hook is responsible for detecting when
8524 the user ends an interaction with the scroll bar, and generates
8525 a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so. */
8526
8527 static void
8528 xt_action_hook (widget, client_data, action_name, event, params,
8529 num_params)
8530 Widget widget;
8531 XtPointer client_data;
8532 String action_name;
8533 XEvent *event;
8534 String *params;
8535 Cardinal *num_params;
8536 {
8537 int scroll_bar_p;
8538 char *end_action;
8539
8540 #ifdef USE_MOTIF
8541 scroll_bar_p = XmIsScrollBar (widget);
8542 end_action = "Release";
8543 #else /* !USE_MOTIF i.e. use Xaw */
8544 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8545 end_action = "EndScroll";
8546 #endif /* USE_MOTIF */
8547
8548 if (scroll_bar_p
8549 && strcmp (action_name, end_action) == 0
8550 && WINDOWP (window_being_scrolled))
8551 {
8552 struct window *w;
8553
8554 x_send_scroll_bar_event (window_being_scrolled,
8555 scroll_bar_end_scroll, 0, 0);
8556 w = XWINDOW (window_being_scrolled);
8557 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8558 window_being_scrolled = Qnil;
8559 last_scroll_bar_part = -1;
8560
8561 /* Xt timeouts no longer needed. */
8562 toolkit_scroll_bar_interaction = 0;
8563 }
8564 }
8565
8566 /* A vector of windows used for communication between
8567 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8568
8569 static struct window **scroll_bar_windows;
8570 static int scroll_bar_windows_size;
8571
8572
8573 /* Send a client message with message type Xatom_Scrollbar for a
8574 scroll action to the frame of WINDOW. PART is a value identifying
8575 the part of the scroll bar that was clicked on. PORTION is the
8576 amount to scroll of a whole of WHOLE. */
8577
8578 static void
8579 x_send_scroll_bar_event (window, part, portion, whole)
8580 Lisp_Object window;
8581 int part, portion, whole;
8582 {
8583 XEvent event;
8584 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
8585 struct window *w = XWINDOW (window);
8586 struct frame *f = XFRAME (w->frame);
8587 int i;
8588
8589 BLOCK_INPUT;
8590
8591 /* Construct a ClientMessage event to send to the frame. */
8592 ev->type = ClientMessage;
8593 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8594 ev->display = FRAME_X_DISPLAY (f);
8595 ev->window = FRAME_X_WINDOW (f);
8596 ev->format = 32;
8597
8598 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8599 not enough to store a pointer or Lisp_Object on a 64 bit system.
8600 So, store the window in scroll_bar_windows and pass the index
8601 into that array in the event. */
8602 for (i = 0; i < scroll_bar_windows_size; ++i)
8603 if (scroll_bar_windows[i] == NULL)
8604 break;
8605
8606 if (i == scroll_bar_windows_size)
8607 {
8608 int new_size = max (10, 2 * scroll_bar_windows_size);
8609 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8610 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8611
8612 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8613 nbytes);
8614 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8615 scroll_bar_windows_size = new_size;
8616 }
8617
8618 scroll_bar_windows[i] = w;
8619 ev->data.l[0] = (long) i;
8620 ev->data.l[1] = (long) part;
8621 ev->data.l[2] = (long) 0;
8622 ev->data.l[3] = (long) portion;
8623 ev->data.l[4] = (long) whole;
8624
8625 /* Make Xt timeouts work while the scroll bar is active. */
8626 toolkit_scroll_bar_interaction = 1;
8627
8628 /* Setting the event mask to zero means that the message will
8629 be sent to the client that created the window, and if that
8630 window no longer exists, no event will be sent. */
8631 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8632 UNBLOCK_INPUT;
8633 }
8634
8635
8636 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8637 in *IEVENT. */
8638
8639 static void
8640 x_scroll_bar_to_input_event (event, ievent)
8641 XEvent *event;
8642 struct input_event *ievent;
8643 {
8644 XClientMessageEvent *ev = (XClientMessageEvent *) event;
8645 Lisp_Object window;
8646 struct frame *f;
8647 struct window *w;
8648
8649 w = scroll_bar_windows[ev->data.l[0]];
8650 scroll_bar_windows[ev->data.l[0]] = NULL;
8651
8652 XSETWINDOW (window, w);
8653 f = XFRAME (w->frame);
8654
8655 ievent->kind = SCROLL_BAR_CLICK_EVENT;
8656 ievent->frame_or_window = window;
8657 ievent->arg = Qnil;
8658 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8659 ievent->part = ev->data.l[1];
8660 ievent->code = ev->data.l[2];
8661 ievent->x = make_number ((int) ev->data.l[3]);
8662 ievent->y = make_number ((int) ev->data.l[4]);
8663 ievent->modifiers = 0;
8664 }
8665
8666
8667 #ifdef USE_MOTIF
8668
8669 /* Minimum and maximum values used for Motif scroll bars. */
8670
8671 #define XM_SB_MIN 1
8672 #define XM_SB_MAX 10000000
8673 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8674
8675
8676 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8677 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8678 CALL_DATA is a pointer to a XmScrollBarCallbackStruct. */
8679
8680 static void
8681 xm_scroll_callback (widget, client_data, call_data)
8682 Widget widget;
8683 XtPointer client_data, call_data;
8684 {
8685 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8686 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8687 int part = -1, whole = 0, portion = 0;
8688
8689 switch (cs->reason)
8690 {
8691 case XmCR_DECREMENT:
8692 bar->dragging = Qnil;
8693 part = scroll_bar_up_arrow;
8694 break;
8695
8696 case XmCR_INCREMENT:
8697 bar->dragging = Qnil;
8698 part = scroll_bar_down_arrow;
8699 break;
8700
8701 case XmCR_PAGE_DECREMENT:
8702 bar->dragging = Qnil;
8703 part = scroll_bar_above_handle;
8704 break;
8705
8706 case XmCR_PAGE_INCREMENT:
8707 bar->dragging = Qnil;
8708 part = scroll_bar_below_handle;
8709 break;
8710
8711 case XmCR_TO_TOP:
8712 bar->dragging = Qnil;
8713 part = scroll_bar_to_top;
8714 break;
8715
8716 case XmCR_TO_BOTTOM:
8717 bar->dragging = Qnil;
8718 part = scroll_bar_to_bottom;
8719 break;
8720
8721 case XmCR_DRAG:
8722 {
8723 int slider_size;
8724 int dragging_down_p = (INTEGERP (bar->dragging)
8725 && XINT (bar->dragging) <= cs->value);
8726
8727 /* Get the slider size. */
8728 BLOCK_INPUT;
8729 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8730 UNBLOCK_INPUT;
8731
8732 whole = XM_SB_RANGE - slider_size;
8733 portion = min (cs->value - XM_SB_MIN, whole);
8734 part = scroll_bar_handle;
8735 bar->dragging = make_number (cs->value);
8736 }
8737 break;
8738
8739 case XmCR_VALUE_CHANGED:
8740 break;
8741 };
8742
8743 if (part >= 0)
8744 {
8745 window_being_scrolled = bar->window;
8746 last_scroll_bar_part = part;
8747 x_send_scroll_bar_event (bar->window, part, portion, whole);
8748 }
8749 }
8750
8751
8752 #else /* !USE_MOTIF, i.e. Xaw. */
8753
8754
8755 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
8756 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8757 scroll bar struct. CALL_DATA is a pointer to a float saying where
8758 the thumb is. */
8759
8760 static void
8761 xaw_jump_callback (widget, client_data, call_data)
8762 Widget widget;
8763 XtPointer client_data, call_data;
8764 {
8765 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8766 float top = *(float *) call_data;
8767 float shown;
8768 int whole, portion, height;
8769 int part;
8770
8771 /* Get the size of the thumb, a value between 0 and 1. */
8772 BLOCK_INPUT;
8773 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
8774 UNBLOCK_INPUT;
8775
8776 whole = 10000000;
8777 portion = shown < 1 ? top * whole : 0;
8778
8779 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8780 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8781 the bottom, so we force the scrolling whenever we see that we're
8782 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8783 we try to ensure that we always stay two pixels away from the
8784 bottom). */
8785 part = scroll_bar_down_arrow;
8786 else
8787 part = scroll_bar_handle;
8788
8789 window_being_scrolled = bar->window;
8790 bar->dragging = make_number (portion);
8791 last_scroll_bar_part = part;
8792 x_send_scroll_bar_event (bar->window, part, portion, whole);
8793 }
8794
8795
8796 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
8797 i.e. line or page up or down. WIDGET is the Xaw scroll bar
8798 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8799 the scroll bar. CALL_DATA is an integer specifying the action that
8800 has taken place. Its magnitude is in the range 0..height of the
8801 scroll bar. Negative values mean scroll towards buffer start.
8802 Values < height of scroll bar mean line-wise movement. */
8803
8804 static void
8805 xaw_scroll_callback (widget, client_data, call_data)
8806 Widget widget;
8807 XtPointer client_data, call_data;
8808 {
8809 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8810 /* The position really is stored cast to a pointer. */
8811 int position = (long) call_data;
8812 Dimension height;
8813 int part;
8814
8815 /* Get the height of the scroll bar. */
8816 BLOCK_INPUT;
8817 XtVaGetValues (widget, XtNheight, &height, NULL);
8818 UNBLOCK_INPUT;
8819
8820 if (abs (position) >= height)
8821 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8822
8823 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8824 it maps line-movement to call_data = max(5, height/20). */
8825 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8826 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8827 else
8828 part = scroll_bar_move_ratio;
8829
8830 window_being_scrolled = bar->window;
8831 bar->dragging = Qnil;
8832 last_scroll_bar_part = part;
8833 x_send_scroll_bar_event (bar->window, part, position, height);
8834 }
8835
8836
8837 #endif /* not USE_MOTIF */
8838
8839
8840 /* Create the widget for scroll bar BAR on frame F. Record the widget
8841 and X window of the scroll bar in BAR. */
8842
8843 static void
8844 x_create_toolkit_scroll_bar (f, bar)
8845 struct frame *f;
8846 struct scroll_bar *bar;
8847 {
8848 Window xwindow;
8849 Widget widget;
8850 Arg av[20];
8851 int ac = 0;
8852 char *scroll_bar_name = "verticalScrollBar";
8853 unsigned long pixel;
8854
8855 BLOCK_INPUT;
8856
8857 #ifdef USE_MOTIF
8858 /* Set resources. Create the widget. */
8859 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8860 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8861 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8862 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8863 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8864 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8865 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8866
8867 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8868 if (pixel != -1)
8869 {
8870 XtSetArg (av[ac], XmNforeground, pixel);
8871 ++ac;
8872 }
8873
8874 pixel = f->output_data.x->scroll_bar_background_pixel;
8875 if (pixel != -1)
8876 {
8877 XtSetArg (av[ac], XmNbackground, pixel);
8878 ++ac;
8879 }
8880
8881 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8882 scroll_bar_name, av, ac);
8883
8884 /* Add one callback for everything that can happen. */
8885 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8886 (XtPointer) bar);
8887 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8888 (XtPointer) bar);
8889 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8890 (XtPointer) bar);
8891 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8892 (XtPointer) bar);
8893 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8894 (XtPointer) bar);
8895 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8896 (XtPointer) bar);
8897 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8898 (XtPointer) bar);
8899
8900 /* Realize the widget. Only after that is the X window created. */
8901 XtRealizeWidget (widget);
8902
8903 /* Set the cursor to an arrow. I didn't find a resource to do that.
8904 And I'm wondering why it hasn't an arrow cursor by default. */
8905 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8906 f->output_data.x->nontext_cursor);
8907
8908 #else /* !USE_MOTIF i.e. use Xaw */
8909
8910 /* Set resources. Create the widget. The background of the
8911 Xaw3d scroll bar widget is a little bit light for my taste.
8912 We don't alter it here to let users change it according
8913 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8914 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8915 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8916 /* For smoother scrolling with Xaw3d -sm */
8917 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8918
8919 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8920 if (pixel != -1)
8921 {
8922 XtSetArg (av[ac], XtNforeground, pixel);
8923 ++ac;
8924 }
8925
8926 pixel = f->output_data.x->scroll_bar_background_pixel;
8927 if (pixel != -1)
8928 {
8929 XtSetArg (av[ac], XtNbackground, pixel);
8930 ++ac;
8931 }
8932
8933 /* Top/bottom shadow colors. */
8934
8935 /* Allocate them, if necessary. */
8936 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8937 {
8938 pixel = f->output_data.x->scroll_bar_background_pixel;
8939 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8940 &pixel, 1.2, 0x8000))
8941 pixel = -1;
8942 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8943 }
8944 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8945 {
8946 pixel = f->output_data.x->scroll_bar_background_pixel;
8947 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8948 &pixel, 0.6, 0x4000))
8949 pixel = -1;
8950 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8951 }
8952
8953 /* Tell the toolkit about them. */
8954 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8955 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8956 /* We tried to allocate a color for the top/bottom shadow, and
8957 failed, so tell Xaw3d to use dithering instead. */
8958 {
8959 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8960 ++ac;
8961 }
8962 else
8963 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8964 be more consistent with other emacs 3d colors, and since Xaw3d is
8965 not good at dealing with allocation failure. */
8966 {
8967 /* This tells Xaw3d to use real colors instead of dithering for
8968 the shadows. */
8969 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8970 ++ac;
8971
8972 /* Specify the colors. */
8973 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8974 if (pixel != -1)
8975 {
8976 XtSetArg (av[ac], "topShadowPixel", pixel);
8977 ++ac;
8978 }
8979 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8980 if (pixel != -1)
8981 {
8982 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8983 ++ac;
8984 }
8985 }
8986
8987 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8988 f->output_data.x->edit_widget, av, ac);
8989
8990 {
8991 char *initial = "";
8992 char *val = initial;
8993 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8994 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8995 if (val == initial)
8996 { /* ARROW_SCROLL */
8997 xaw3d_arrow_scroll = True;
8998 /* Isn't that just a personal preference ? -sm */
8999 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
9000 }
9001 }
9002
9003 /* Define callbacks. */
9004 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
9005 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
9006 (XtPointer) bar);
9007
9008 /* Realize the widget. Only after that is the X window created. */
9009 XtRealizeWidget (widget);
9010
9011 #endif /* !USE_MOTIF */
9012
9013 /* Install an action hook that lets us detect when the user
9014 finishes interacting with a scroll bar. */
9015 if (action_hook_id == 0)
9016 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
9017
9018 /* Remember X window and widget in the scroll bar vector. */
9019 SET_SCROLL_BAR_X_WIDGET (bar, widget);
9020 xwindow = XtWindow (widget);
9021 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
9022
9023 UNBLOCK_INPUT;
9024 }
9025
9026
9027 /* Set the thumb size and position of scroll bar BAR. We are currently
9028 displaying PORTION out of a whole WHOLE, and our position POSITION. */
9029
9030 static void
9031 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
9032 struct scroll_bar *bar;
9033 int portion, position, whole;
9034 {
9035 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9036 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9037 float top, shown;
9038
9039 BLOCK_INPUT;
9040
9041 #ifdef USE_MOTIF
9042
9043 /* We use an estimate of 30 chars per line rather than the real
9044 `portion' value. This has the disadvantage that the thumb size
9045 is not very representative, but it makes our life a lot easier.
9046 Otherwise, we have to constantly adjust the thumb size, which
9047 we can't always do quickly enough: while dragging, the size of
9048 the thumb might prevent the user from dragging the thumb all the
9049 way to the end. but Motif and some versions of Xaw3d don't allow
9050 updating the thumb size while dragging. Also, even if we can update
9051 its size, the update will often happen too late.
9052 If you don't believe it, check out revision 1.650 of xterm.c to see
9053 what hoops we were going through and the still poor behavior we got. */
9054 portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
9055 /* When the thumb is at the bottom, position == whole.
9056 So we need to increase `whole' to make space for the thumb. */
9057 whole += portion;
9058
9059 if (whole <= 0)
9060 top = 0, shown = 1;
9061 else
9062 {
9063 top = (float) position / whole;
9064 shown = (float) portion / whole;
9065 }
9066
9067 if (NILP (bar->dragging))
9068 {
9069 int size, value;
9070
9071 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
9072 is the scroll bar's maximum and MIN is the scroll bar's minimum
9073 value. */
9074 size = shown * XM_SB_RANGE;
9075 size = min (size, XM_SB_RANGE);
9076 size = max (size, 1);
9077
9078 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
9079 value = top * XM_SB_RANGE;
9080 value = min (value, XM_SB_MAX - size);
9081 value = max (value, XM_SB_MIN);
9082
9083 XmScrollBarSetValues (widget, value, size, 0, 0, False);
9084 }
9085 #else /* !USE_MOTIF i.e. use Xaw */
9086
9087 if (whole == 0)
9088 top = 0, shown = 1;
9089 else
9090 {
9091 top = (float) position / whole;
9092 shown = (float) portion / whole;
9093 }
9094
9095 {
9096 float old_top, old_shown;
9097 Dimension height;
9098 XtVaGetValues (widget,
9099 XtNtopOfThumb, &old_top,
9100 XtNshown, &old_shown,
9101 XtNheight, &height,
9102 NULL);
9103
9104 /* Massage the top+shown values. */
9105 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
9106 top = max (0, min (1, top));
9107 else
9108 top = old_top;
9109 /* Keep two pixels available for moving the thumb down. */
9110 shown = max (0, min (1 - top - (2.0 / height), shown));
9111
9112 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
9113 check that your system's configuration file contains a define
9114 for `NARROWPROTO'. See s/freebsd.h for an example. */
9115 if (top != old_top || shown != old_shown)
9116 {
9117 if (NILP (bar->dragging))
9118 XawScrollbarSetThumb (widget, top, shown);
9119 else
9120 {
9121 #ifdef HAVE_XAW3D
9122 ScrollbarWidget sb = (ScrollbarWidget) widget;
9123 int scroll_mode = 0;
9124
9125 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
9126 if (xaw3d_arrow_scroll)
9127 {
9128 /* Xaw3d stupidly ignores resize requests while dragging
9129 so we have to make it believe it's not in dragging mode. */
9130 scroll_mode = sb->scrollbar.scroll_mode;
9131 if (scroll_mode == 2)
9132 sb->scrollbar.scroll_mode = 0;
9133 }
9134 #endif
9135 /* Try to make the scrolling a tad smoother. */
9136 if (!xaw3d_pick_top)
9137 shown = min (shown, old_shown);
9138
9139 XawScrollbarSetThumb (widget, top, shown);
9140
9141 #ifdef HAVE_XAW3D
9142 if (xaw3d_arrow_scroll && scroll_mode == 2)
9143 sb->scrollbar.scroll_mode = scroll_mode;
9144 #endif
9145 }
9146 }
9147 }
9148 #endif /* !USE_MOTIF */
9149
9150 UNBLOCK_INPUT;
9151 }
9152
9153 #endif /* USE_TOOLKIT_SCROLL_BARS */
9154
9155
9156 \f
9157 /************************************************************************
9158 Scroll bars, general
9159 ************************************************************************/
9160
9161 /* Create a scroll bar and return the scroll bar vector for it. W is
9162 the Emacs window on which to create the scroll bar. TOP, LEFT,
9163 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
9164 scroll bar. */
9165
9166 static struct scroll_bar *
9167 x_scroll_bar_create (w, top, left, width, height)
9168 struct window *w;
9169 int top, left, width, height;
9170 {
9171 struct frame *f = XFRAME (w->frame);
9172 struct scroll_bar *bar
9173 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
9174
9175 BLOCK_INPUT;
9176
9177 #ifdef USE_TOOLKIT_SCROLL_BARS
9178 x_create_toolkit_scroll_bar (f, bar);
9179 #else /* not USE_TOOLKIT_SCROLL_BARS */
9180 {
9181 XSetWindowAttributes a;
9182 unsigned long mask;
9183 Window window;
9184
9185 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
9186 if (a.background_pixel == -1)
9187 a.background_pixel = f->output_data.x->background_pixel;
9188
9189 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9190 | ButtonMotionMask | PointerMotionHintMask
9191 | ExposureMask);
9192 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
9193
9194 mask = (CWBackPixel | CWEventMask | CWCursor);
9195
9196 /* Clear the area of W that will serve as a scroll bar. This is
9197 for the case that a window has been split horizontally. In
9198 this case, no clear_frame is generated to reduce flickering. */
9199 if (width > 0 && height > 0)
9200 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9201 left, top, width,
9202 window_box_height (w), False);
9203
9204 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9205 /* Position and size of scroll bar. */
9206 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9207 top,
9208 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9209 height,
9210 /* Border width, depth, class, and visual. */
9211 0,
9212 CopyFromParent,
9213 CopyFromParent,
9214 CopyFromParent,
9215 /* Attributes. */
9216 mask, &a);
9217 SET_SCROLL_BAR_X_WINDOW (bar, window);
9218 }
9219 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9220
9221 XSETWINDOW (bar->window, w);
9222 XSETINT (bar->top, top);
9223 XSETINT (bar->left, left);
9224 XSETINT (bar->width, width);
9225 XSETINT (bar->height, height);
9226 XSETINT (bar->start, 0);
9227 XSETINT (bar->end, 0);
9228 bar->dragging = Qnil;
9229
9230 /* Add bar to its frame's list of scroll bars. */
9231 bar->next = FRAME_SCROLL_BARS (f);
9232 bar->prev = Qnil;
9233 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9234 if (!NILP (bar->next))
9235 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9236
9237 /* Map the window/widget. */
9238 #ifdef USE_TOOLKIT_SCROLL_BARS
9239 {
9240 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9241 XtConfigureWidget (scroll_bar,
9242 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9243 top,
9244 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9245 max (height, 1), 0);
9246 XtMapWidget (scroll_bar);
9247 }
9248 #else /* not USE_TOOLKIT_SCROLL_BARS */
9249 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9250 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9251
9252 UNBLOCK_INPUT;
9253 return bar;
9254 }
9255
9256
9257 /* Draw BAR's handle in the proper position.
9258
9259 If the handle is already drawn from START to END, don't bother
9260 redrawing it, unless REBUILD is non-zero; in that case, always
9261 redraw it. (REBUILD is handy for drawing the handle after expose
9262 events.)
9263
9264 Normally, we want to constrain the start and end of the handle to
9265 fit inside its rectangle, but if the user is dragging the scroll
9266 bar handle, we want to let them drag it down all the way, so that
9267 the bar's top is as far down as it goes; otherwise, there's no way
9268 to move to the very end of the buffer. */
9269
9270 #ifndef USE_TOOLKIT_SCROLL_BARS
9271
9272 static void
9273 x_scroll_bar_set_handle (bar, start, end, rebuild)
9274 struct scroll_bar *bar;
9275 int start, end;
9276 int rebuild;
9277 {
9278 int dragging = ! NILP (bar->dragging);
9279 Window w = SCROLL_BAR_X_WINDOW (bar);
9280 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9281 GC gc = f->output_data.x->normal_gc;
9282
9283 /* If the display is already accurate, do nothing. */
9284 if (! rebuild
9285 && start == XINT (bar->start)
9286 && end == XINT (bar->end))
9287 return;
9288
9289 BLOCK_INPUT;
9290
9291 {
9292 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9293 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9294 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9295
9296 /* Make sure the values are reasonable, and try to preserve
9297 the distance between start and end. */
9298 {
9299 int length = end - start;
9300
9301 if (start < 0)
9302 start = 0;
9303 else if (start > top_range)
9304 start = top_range;
9305 end = start + length;
9306
9307 if (end < start)
9308 end = start;
9309 else if (end > top_range && ! dragging)
9310 end = top_range;
9311 }
9312
9313 /* Store the adjusted setting in the scroll bar. */
9314 XSETINT (bar->start, start);
9315 XSETINT (bar->end, end);
9316
9317 /* Clip the end position, just for display. */
9318 if (end > top_range)
9319 end = top_range;
9320
9321 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
9322 below top positions, to make sure the handle is always at least
9323 that many pixels tall. */
9324 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
9325
9326 /* Draw the empty space above the handle. Note that we can't clear
9327 zero-height areas; that means "clear to end of window." */
9328 if (0 < start)
9329 x_clear_area (FRAME_X_DISPLAY (f), w,
9330 /* x, y, width, height, and exposures. */
9331 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9332 VERTICAL_SCROLL_BAR_TOP_BORDER,
9333 inside_width, start,
9334 False);
9335
9336 /* Change to proper foreground color if one is specified. */
9337 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9338 XSetForeground (FRAME_X_DISPLAY (f), gc,
9339 f->output_data.x->scroll_bar_foreground_pixel);
9340
9341 /* Draw the handle itself. */
9342 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
9343 /* x, y, width, height */
9344 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9345 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
9346 inside_width, end - start);
9347
9348 /* Restore the foreground color of the GC if we changed it above. */
9349 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9350 XSetForeground (FRAME_X_DISPLAY (f), gc,
9351 f->output_data.x->foreground_pixel);
9352
9353 /* Draw the empty space below the handle. Note that we can't
9354 clear zero-height areas; that means "clear to end of window." */
9355 if (end < inside_height)
9356 x_clear_area (FRAME_X_DISPLAY (f), w,
9357 /* x, y, width, height, and exposures. */
9358 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9359 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9360 inside_width, inside_height - end,
9361 False);
9362
9363 }
9364
9365 UNBLOCK_INPUT;
9366 }
9367
9368 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9369
9370 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9371 nil. */
9372
9373 static void
9374 x_scroll_bar_remove (bar)
9375 struct scroll_bar *bar;
9376 {
9377 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9378 BLOCK_INPUT;
9379
9380 #ifdef USE_TOOLKIT_SCROLL_BARS
9381 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9382 #else
9383 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9384 #endif
9385
9386 /* Disassociate this scroll bar from its window. */
9387 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
9388
9389 UNBLOCK_INPUT;
9390 }
9391
9392
9393 /* Set the handle of the vertical scroll bar for WINDOW to indicate
9394 that we are displaying PORTION characters out of a total of WHOLE
9395 characters, starting at POSITION. If WINDOW has no scroll bar,
9396 create one. */
9397
9398 static void
9399 XTset_vertical_scroll_bar (w, portion, whole, position)
9400 struct window *w;
9401 int portion, whole, position;
9402 {
9403 struct frame *f = XFRAME (w->frame);
9404 struct scroll_bar *bar;
9405 int top, height, left, sb_left, width, sb_width;
9406 int window_x, window_y, window_width, window_height;
9407
9408 /* Get window dimensions. */
9409 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9410 top = window_y;
9411 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9412 height = window_height;
9413
9414 /* Compute the left edge of the scroll bar area. */
9415 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9416 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9417 else
9418 left = XFASTINT (w->left);
9419 left *= CANON_X_UNIT (f);
9420 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9421
9422 /* Compute the width of the scroll bar which might be less than
9423 the width of the area reserved for the scroll bar. */
9424 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9425 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
9426 else
9427 sb_width = width;
9428
9429 /* Compute the left edge of the scroll bar. */
9430 #ifdef USE_TOOLKIT_SCROLL_BARS
9431 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9432 sb_left = left + width - sb_width - (width - sb_width) / 2;
9433 else
9434 sb_left = left + (width - sb_width) / 2;
9435 #else
9436 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9437 sb_left = left + width - sb_width;
9438 else
9439 sb_left = left;
9440 #endif
9441
9442 /* Does the scroll bar exist yet? */
9443 if (NILP (w->vertical_scroll_bar))
9444 {
9445 if (width > 0 && height > 0)
9446 {
9447 BLOCK_INPUT;
9448 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9449 left, top, width, height, False);
9450 UNBLOCK_INPUT;
9451 }
9452
9453 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9454 }
9455 else
9456 {
9457 /* It may just need to be moved and resized. */
9458 unsigned int mask = 0;
9459
9460 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9461
9462 BLOCK_INPUT;
9463
9464 if (sb_left != XINT (bar->left))
9465 mask |= CWX;
9466 if (top != XINT (bar->top))
9467 mask |= CWY;
9468 if (sb_width != XINT (bar->width))
9469 mask |= CWWidth;
9470 if (height != XINT (bar->height))
9471 mask |= CWHeight;
9472
9473 #ifdef USE_TOOLKIT_SCROLL_BARS
9474
9475 /* Since toolkit scroll bars are smaller than the space reserved
9476 for them on the frame, we have to clear "under" them. */
9477 if (width > 0 && height > 0)
9478 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9479 left, top, width, height, False);
9480
9481 /* Move/size the scroll bar widget. */
9482 if (mask)
9483 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
9484 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9485 top,
9486 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9487 max (height, 1), 0);
9488
9489 #else /* not USE_TOOLKIT_SCROLL_BARS */
9490
9491 /* Clear areas not covered by the scroll bar because of
9492 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
9493 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9494 {
9495 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9496 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9497 height, False);
9498 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9499 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9500 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9501 height, False);
9502 }
9503
9504 /* Clear areas not covered by the scroll bar because it's not as
9505 wide as the area reserved for it. This makes sure a
9506 previous mode line display is cleared after C-x 2 C-x 1, for
9507 example. */
9508 {
9509 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9510 int rest = area_width - sb_width;
9511 if (rest > 0 && height > 0)
9512 {
9513 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
9514 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9515 left + area_width - rest, top,
9516 rest, height, False);
9517 else
9518 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9519 left, top, rest, height, False);
9520 }
9521 }
9522
9523 /* Move/size the scroll bar window. */
9524 if (mask)
9525 {
9526 XWindowChanges wc;
9527
9528 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9529 wc.y = top;
9530 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9531 wc.height = height;
9532 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9533 mask, &wc);
9534 }
9535
9536 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9537
9538 /* Remember new settings. */
9539 XSETINT (bar->left, sb_left);
9540 XSETINT (bar->top, top);
9541 XSETINT (bar->width, sb_width);
9542 XSETINT (bar->height, height);
9543
9544 UNBLOCK_INPUT;
9545 }
9546
9547 #ifdef USE_TOOLKIT_SCROLL_BARS
9548 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9549 #else /* not USE_TOOLKIT_SCROLL_BARS */
9550 /* Set the scroll bar's current state, unless we're currently being
9551 dragged. */
9552 if (NILP (bar->dragging))
9553 {
9554 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
9555
9556 if (whole == 0)
9557 x_scroll_bar_set_handle (bar, 0, top_range, 0);
9558 else
9559 {
9560 int start = ((double) position * top_range) / whole;
9561 int end = ((double) (position + portion) * top_range) / whole;
9562 x_scroll_bar_set_handle (bar, start, end, 0);
9563 }
9564 }
9565 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9566
9567 XSETVECTOR (w->vertical_scroll_bar, bar);
9568 }
9569
9570
9571 /* The following three hooks are used when we're doing a thorough
9572 redisplay of the frame. We don't explicitly know which scroll bars
9573 are going to be deleted, because keeping track of when windows go
9574 away is a real pain - "Can you say set-window-configuration, boys
9575 and girls?" Instead, we just assert at the beginning of redisplay
9576 that *all* scroll bars are to be removed, and then save a scroll bar
9577 from the fiery pit when we actually redisplay its window. */
9578
9579 /* Arrange for all scroll bars on FRAME to be removed at the next call
9580 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
9581 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9582
9583 static void
9584 XTcondemn_scroll_bars (frame)
9585 FRAME_PTR frame;
9586 {
9587 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9588 while (! NILP (FRAME_SCROLL_BARS (frame)))
9589 {
9590 Lisp_Object bar;
9591 bar = FRAME_SCROLL_BARS (frame);
9592 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9593 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9594 XSCROLL_BAR (bar)->prev = Qnil;
9595 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9596 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9597 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9598 }
9599 }
9600
9601
9602 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
9603 Note that WINDOW isn't necessarily condemned at all. */
9604
9605 static void
9606 XTredeem_scroll_bar (window)
9607 struct window *window;
9608 {
9609 struct scroll_bar *bar;
9610 struct frame *f;
9611
9612 /* We can't redeem this window's scroll bar if it doesn't have one. */
9613 if (NILP (window->vertical_scroll_bar))
9614 abort ();
9615
9616 bar = XSCROLL_BAR (window->vertical_scroll_bar);
9617
9618 /* Unlink it from the condemned list. */
9619 f = XFRAME (WINDOW_FRAME (window));
9620 if (NILP (bar->prev))
9621 {
9622 /* If the prev pointer is nil, it must be the first in one of
9623 the lists. */
9624 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9625 /* It's not condemned. Everything's fine. */
9626 return;
9627 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9628 window->vertical_scroll_bar))
9629 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9630 else
9631 /* If its prev pointer is nil, it must be at the front of
9632 one or the other! */
9633 abort ();
9634 }
9635 else
9636 XSCROLL_BAR (bar->prev)->next = bar->next;
9637
9638 if (! NILP (bar->next))
9639 XSCROLL_BAR (bar->next)->prev = bar->prev;
9640
9641 bar->next = FRAME_SCROLL_BARS (f);
9642 bar->prev = Qnil;
9643 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9644 if (! NILP (bar->next))
9645 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
9646 }
9647
9648 /* Remove all scroll bars on FRAME that haven't been saved since the
9649 last call to `*condemn_scroll_bars_hook'. */
9650
9651 static void
9652 XTjudge_scroll_bars (f)
9653 FRAME_PTR f;
9654 {
9655 Lisp_Object bar, next;
9656
9657 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
9658
9659 /* Clear out the condemned list now so we won't try to process any
9660 more events on the hapless scroll bars. */
9661 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
9662
9663 for (; ! NILP (bar); bar = next)
9664 {
9665 struct scroll_bar *b = XSCROLL_BAR (bar);
9666
9667 x_scroll_bar_remove (b);
9668
9669 next = b->next;
9670 b->next = b->prev = Qnil;
9671 }
9672
9673 /* Now there should be no references to the condemned scroll bars,
9674 and they should get garbage-collected. */
9675 }
9676
9677
9678 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
9679 is a no-op when using toolkit scroll bars.
9680
9681 This may be called from a signal handler, so we have to ignore GC
9682 mark bits. */
9683
9684 static void
9685 x_scroll_bar_expose (bar, event)
9686 struct scroll_bar *bar;
9687 XEvent *event;
9688 {
9689 #ifndef USE_TOOLKIT_SCROLL_BARS
9690
9691 Window w = SCROLL_BAR_X_WINDOW (bar);
9692 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9693 GC gc = f->output_data.x->normal_gc;
9694 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9695
9696 BLOCK_INPUT;
9697
9698 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
9699
9700 /* Draw a one-pixel border just inside the edges of the scroll bar. */
9701 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
9702
9703 /* x, y, width, height */
9704 0, 0,
9705 XINT (bar->width) - 1 - width_trim - width_trim,
9706 XINT (bar->height) - 1);
9707
9708 UNBLOCK_INPUT;
9709
9710 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9711 }
9712
9713 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9714 is set to something other than NO_EVENT, it is enqueued.
9715
9716 This may be called from a signal handler, so we have to ignore GC
9717 mark bits. */
9718
9719 #ifndef USE_TOOLKIT_SCROLL_BARS
9720
9721 static void
9722 x_scroll_bar_handle_click (bar, event, emacs_event)
9723 struct scroll_bar *bar;
9724 XEvent *event;
9725 struct input_event *emacs_event;
9726 {
9727 if (! GC_WINDOWP (bar->window))
9728 abort ();
9729
9730 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
9731 emacs_event->code = event->xbutton.button - Button1;
9732 emacs_event->modifiers
9733 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9734 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9735 event->xbutton.state)
9736 | (event->type == ButtonRelease
9737 ? up_modifier
9738 : down_modifier));
9739 emacs_event->frame_or_window = bar->window;
9740 emacs_event->arg = Qnil;
9741 emacs_event->timestamp = event->xbutton.time;
9742 {
9743 #if 0
9744 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9745 int internal_height
9746 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9747 #endif
9748 int top_range
9749 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9750 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
9751
9752 if (y < 0) y = 0;
9753 if (y > top_range) y = top_range;
9754
9755 if (y < XINT (bar->start))
9756 emacs_event->part = scroll_bar_above_handle;
9757 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9758 emacs_event->part = scroll_bar_handle;
9759 else
9760 emacs_event->part = scroll_bar_below_handle;
9761
9762 /* Just because the user has clicked on the handle doesn't mean
9763 they want to drag it. Lisp code needs to be able to decide
9764 whether or not we're dragging. */
9765 #if 0
9766 /* If the user has just clicked on the handle, record where they're
9767 holding it. */
9768 if (event->type == ButtonPress
9769 && emacs_event->part == scroll_bar_handle)
9770 XSETINT (bar->dragging, y - XINT (bar->start));
9771 #endif
9772
9773 /* If the user has released the handle, set it to its final position. */
9774 if (event->type == ButtonRelease
9775 && ! NILP (bar->dragging))
9776 {
9777 int new_start = y - XINT (bar->dragging);
9778 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9779
9780 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9781 bar->dragging = Qnil;
9782 }
9783
9784 /* Same deal here as the other #if 0. */
9785 #if 0
9786 /* Clicks on the handle are always reported as occurring at the top of
9787 the handle. */
9788 if (emacs_event->part == scroll_bar_handle)
9789 emacs_event->x = bar->start;
9790 else
9791 XSETINT (emacs_event->x, y);
9792 #else
9793 XSETINT (emacs_event->x, y);
9794 #endif
9795
9796 XSETINT (emacs_event->y, top_range);
9797 }
9798 }
9799
9800 /* Handle some mouse motion while someone is dragging the scroll bar.
9801
9802 This may be called from a signal handler, so we have to ignore GC
9803 mark bits. */
9804
9805 static void
9806 x_scroll_bar_note_movement (bar, event)
9807 struct scroll_bar *bar;
9808 XEvent *event;
9809 {
9810 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9811
9812 last_mouse_movement_time = event->xmotion.time;
9813
9814 f->mouse_moved = 1;
9815 XSETVECTOR (last_mouse_scroll_bar, bar);
9816
9817 /* If we're dragging the bar, display it. */
9818 if (! GC_NILP (bar->dragging))
9819 {
9820 /* Where should the handle be now? */
9821 int new_start = event->xmotion.y - XINT (bar->dragging);
9822
9823 if (new_start != XINT (bar->start))
9824 {
9825 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
9826
9827 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
9828 }
9829 }
9830 }
9831
9832 #endif /* !USE_TOOLKIT_SCROLL_BARS */
9833
9834 /* Return information to the user about the current position of the mouse
9835 on the scroll bar. */
9836
9837 static void
9838 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9839 FRAME_PTR *fp;
9840 Lisp_Object *bar_window;
9841 enum scroll_bar_part *part;
9842 Lisp_Object *x, *y;
9843 unsigned long *time;
9844 {
9845 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
9846 Window w = SCROLL_BAR_X_WINDOW (bar);
9847 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
9848 int win_x, win_y;
9849 Window dummy_window;
9850 int dummy_coord;
9851 unsigned int dummy_mask;
9852
9853 BLOCK_INPUT;
9854
9855 /* Get the mouse's position relative to the scroll bar window, and
9856 report that. */
9857 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
9858
9859 /* Root, child, root x and root y. */
9860 &dummy_window, &dummy_window,
9861 &dummy_coord, &dummy_coord,
9862
9863 /* Position relative to scroll bar. */
9864 &win_x, &win_y,
9865
9866 /* Mouse buttons and modifier keys. */
9867 &dummy_mask))
9868 ;
9869 else
9870 {
9871 #if 0
9872 int inside_height
9873 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9874 #endif
9875 int top_range
9876 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9877
9878 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9879
9880 if (! NILP (bar->dragging))
9881 win_y -= XINT (bar->dragging);
9882
9883 if (win_y < 0)
9884 win_y = 0;
9885 if (win_y > top_range)
9886 win_y = top_range;
9887
9888 *fp = f;
9889 *bar_window = bar->window;
9890
9891 if (! NILP (bar->dragging))
9892 *part = scroll_bar_handle;
9893 else if (win_y < XINT (bar->start))
9894 *part = scroll_bar_above_handle;
9895 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9896 *part = scroll_bar_handle;
9897 else
9898 *part = scroll_bar_below_handle;
9899
9900 XSETINT (*x, win_y);
9901 XSETINT (*y, top_range);
9902
9903 f->mouse_moved = 0;
9904 last_mouse_scroll_bar = Qnil;
9905 }
9906
9907 *time = last_mouse_movement_time;
9908
9909 UNBLOCK_INPUT;
9910 }
9911
9912
9913 /* The screen has been cleared so we may have changed foreground or
9914 background colors, and the scroll bars may need to be redrawn.
9915 Clear out the scroll bars, and ask for expose events, so we can
9916 redraw them. */
9917
9918 void
9919 x_scroll_bar_clear (f)
9920 FRAME_PTR f;
9921 {
9922 #ifndef USE_TOOLKIT_SCROLL_BARS
9923 Lisp_Object bar;
9924
9925 /* We can have scroll bars even if this is 0,
9926 if we just turned off scroll bar mode.
9927 But in that case we should not clear them. */
9928 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9929 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9930 bar = XSCROLL_BAR (bar)->next)
9931 XClearArea (FRAME_X_DISPLAY (f),
9932 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9933 0, 0, 0, 0, True);
9934 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9935 }
9936
9937 /* This processes Expose events from the menu-bar specific X event
9938 loop in xmenu.c. This allows to redisplay the frame if necessary
9939 when handling menu-bar or pop-up items. */
9940
9941 int
9942 process_expose_from_menu (event)
9943 XEvent event;
9944 {
9945 FRAME_PTR f;
9946 struct x_display_info *dpyinfo;
9947 int frame_exposed_p = 0;
9948
9949 BLOCK_INPUT;
9950
9951 dpyinfo = x_display_info_for_display (event.xexpose.display);
9952 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9953 if (f)
9954 {
9955 if (f->async_visible == 0)
9956 {
9957 f->async_visible = 1;
9958 f->async_iconified = 0;
9959 f->output_data.x->has_been_visible = 1;
9960 SET_FRAME_GARBAGED (f);
9961 }
9962 else
9963 {
9964 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9965 event.xexpose.x, event.xexpose.y,
9966 event.xexpose.width, event.xexpose.height);
9967 frame_exposed_p = 1;
9968 }
9969 }
9970 else
9971 {
9972 struct scroll_bar *bar
9973 = x_window_to_scroll_bar (event.xexpose.window);
9974
9975 if (bar)
9976 x_scroll_bar_expose (bar, &event);
9977 }
9978
9979 UNBLOCK_INPUT;
9980 return frame_exposed_p;
9981 }
9982 \f
9983 /* Define a queue to save up SelectionRequest events for later handling. */
9984
9985 struct selection_event_queue
9986 {
9987 XEvent event;
9988 struct selection_event_queue *next;
9989 };
9990
9991 static struct selection_event_queue *queue;
9992
9993 /* Nonzero means queue up certain events--don't process them yet. */
9994
9995 static int x_queue_selection_requests;
9996
9997 /* Queue up an X event *EVENT, to be processed later. */
9998
9999 static void
10000 x_queue_event (f, event)
10001 FRAME_PTR f;
10002 XEvent *event;
10003 {
10004 struct selection_event_queue *queue_tmp
10005 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
10006
10007 if (queue_tmp != NULL)
10008 {
10009 queue_tmp->event = *event;
10010 queue_tmp->next = queue;
10011 queue = queue_tmp;
10012 }
10013 }
10014
10015 /* Take all the queued events and put them back
10016 so that they get processed afresh. */
10017
10018 static void
10019 x_unqueue_events (display)
10020 Display *display;
10021 {
10022 while (queue != NULL)
10023 {
10024 struct selection_event_queue *queue_tmp = queue;
10025 XPutBackEvent (display, &queue_tmp->event);
10026 queue = queue_tmp->next;
10027 xfree ((char *)queue_tmp);
10028 }
10029 }
10030
10031 /* Start queuing SelectionRequest events. */
10032
10033 void
10034 x_start_queuing_selection_requests (display)
10035 Display *display;
10036 {
10037 x_queue_selection_requests++;
10038 }
10039
10040 /* Stop queuing SelectionRequest events. */
10041
10042 void
10043 x_stop_queuing_selection_requests (display)
10044 Display *display;
10045 {
10046 x_queue_selection_requests--;
10047 x_unqueue_events (display);
10048 }
10049 \f
10050 /* The main X event-reading loop - XTread_socket. */
10051
10052 #if 0
10053 /* Time stamp of enter window event. This is only used by XTread_socket,
10054 but we have to put it out here, since static variables within functions
10055 sometimes don't work. */
10056
10057 static Time enter_timestamp;
10058 #endif
10059
10060 /* This holds the state XLookupString needs to implement dead keys
10061 and other tricks known as "compose processing". _X Window System_
10062 says that a portable program can't use this, but Stephen Gildea assures
10063 me that letting the compiler initialize it to zeros will work okay.
10064
10065 This must be defined outside of XTread_socket, for the same reasons
10066 given for enter_timestamp, above. */
10067
10068 static XComposeStatus compose_status;
10069
10070 /* Record the last 100 characters stored
10071 to help debug the loss-of-chars-during-GC problem. */
10072
10073 static int temp_index;
10074 static short temp_buffer[100];
10075
10076 /* Set this to nonzero to fake an "X I/O error"
10077 on a particular display. */
10078
10079 struct x_display_info *XTread_socket_fake_io_error;
10080
10081 /* When we find no input here, we occasionally do a no-op command
10082 to verify that the X server is still running and we can still talk with it.
10083 We try all the open displays, one by one.
10084 This variable is used for cycling thru the displays. */
10085
10086 static struct x_display_info *next_noop_dpyinfo;
10087
10088 #define SET_SAVED_MENU_EVENT(size) \
10089 do \
10090 { \
10091 if (f->output_data.x->saved_menu_event == 0) \
10092 f->output_data.x->saved_menu_event \
10093 = (XEvent *) xmalloc (sizeof (XEvent)); \
10094 bcopy (&event, f->output_data.x->saved_menu_event, size); \
10095 if (numchars >= 1) \
10096 { \
10097 bufp->kind = MENU_BAR_ACTIVATE_EVENT; \
10098 XSETFRAME (bufp->frame_or_window, f); \
10099 bufp->arg = Qnil; \
10100 bufp++; \
10101 count++; \
10102 numchars--; \
10103 } \
10104 } \
10105 while (0)
10106
10107 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
10108 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
10109
10110 /* Read events coming from the X server.
10111 This routine is called by the SIGIO handler.
10112 We return as soon as there are no more events to be read.
10113
10114 Events representing keys are stored in buffer BUFP,
10115 which can hold up to NUMCHARS characters.
10116 We return the number of characters stored into the buffer,
10117 thus pretending to be `read'.
10118
10119 EXPECTED is nonzero if the caller knows input is available. */
10120
10121 static int
10122 XTread_socket (sd, bufp, numchars, expected)
10123 register int sd;
10124 /* register */ struct input_event *bufp;
10125 /* register */ int numchars;
10126 int expected;
10127 {
10128 int count = 0;
10129 int nbytes = 0;
10130 XEvent event;
10131 struct frame *f;
10132 int event_found = 0;
10133 struct x_display_info *dpyinfo;
10134 struct coding_system coding;
10135
10136 if (interrupt_input_blocked)
10137 {
10138 interrupt_input_pending = 1;
10139 return -1;
10140 }
10141
10142 interrupt_input_pending = 0;
10143 BLOCK_INPUT;
10144
10145 /* So people can tell when we have read the available input. */
10146 input_signal_count++;
10147
10148 if (numchars <= 0)
10149 abort (); /* Don't think this happens. */
10150
10151 ++handling_signal;
10152
10153 /* Find the display we are supposed to read input for.
10154 It's the one communicating on descriptor SD. */
10155 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
10156 {
10157 #if 0 /* This ought to be unnecessary; let's verify it. */
10158 #ifdef FIOSNBIO
10159 /* If available, Xlib uses FIOSNBIO to make the socket
10160 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
10161 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
10162 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
10163 fcntl (dpyinfo->connection, F_SETFL, 0);
10164 #endif /* ! defined (FIOSNBIO) */
10165 #endif
10166
10167 #if 0 /* This code can't be made to work, with multiple displays,
10168 and appears not to be used on any system any more.
10169 Also keyboard.c doesn't turn O_NDELAY on and off
10170 for X connections. */
10171 #ifndef SIGIO
10172 #ifndef HAVE_SELECT
10173 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
10174 {
10175 extern int read_alarm_should_throw;
10176 read_alarm_should_throw = 1;
10177 XPeekEvent (dpyinfo->display, &event);
10178 read_alarm_should_throw = 0;
10179 }
10180 #endif /* HAVE_SELECT */
10181 #endif /* SIGIO */
10182 #endif
10183
10184 /* For debugging, this gives a way to fake an I/O error. */
10185 if (dpyinfo == XTread_socket_fake_io_error)
10186 {
10187 XTread_socket_fake_io_error = 0;
10188 x_io_error_quitter (dpyinfo->display);
10189 }
10190
10191 #ifdef HAVE_X_SM
10192 BLOCK_INPUT;
10193 count += x_session_check_input (bufp, &numchars);
10194 UNBLOCK_INPUT;
10195 #endif
10196
10197 while (XPending (dpyinfo->display))
10198 {
10199 XNextEvent (dpyinfo->display, &event);
10200
10201 #ifdef HAVE_X_I18N
10202 {
10203 /* Filter events for the current X input method.
10204 XFilterEvent returns non-zero if the input method has
10205 consumed the event. We pass the frame's X window to
10206 XFilterEvent because that's the one for which the IC
10207 was created. */
10208 struct frame *f1 = x_any_window_to_frame (dpyinfo,
10209 event.xclient.window);
10210 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
10211 break;
10212 }
10213 #endif
10214 event_found = 1;
10215
10216 switch (event.type)
10217 {
10218 case ClientMessage:
10219 {
10220 if (event.xclient.message_type
10221 == dpyinfo->Xatom_wm_protocols
10222 && event.xclient.format == 32)
10223 {
10224 if (event.xclient.data.l[0]
10225 == dpyinfo->Xatom_wm_take_focus)
10226 {
10227 /* Use x_any_window_to_frame because this
10228 could be the shell widget window
10229 if the frame has no title bar. */
10230 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
10231 #ifdef HAVE_X_I18N
10232 /* Not quite sure this is needed -pd */
10233 if (f && FRAME_XIC (f))
10234 XSetICFocus (FRAME_XIC (f));
10235 #endif
10236 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10237 instructs the WM to set the input focus automatically for
10238 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10239 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10240 it has set the focus. So, XSetInputFocus below is not
10241 needed.
10242
10243 The call to XSetInputFocus below has also caused trouble. In
10244 cases where the XSetInputFocus done by the WM and the one
10245 below are temporally close (on a fast machine), the call
10246 below can generate additional FocusIn events which confuse
10247 Emacs. */
10248
10249 /* Since we set WM_TAKE_FOCUS, we must call
10250 XSetInputFocus explicitly. But not if f is null,
10251 since that might be an event for a deleted frame. */
10252 if (f)
10253 {
10254 Display *d = event.xclient.display;
10255 /* Catch and ignore errors, in case window has been
10256 iconified by a window manager such as GWM. */
10257 int count = x_catch_errors (d);
10258 XSetInputFocus (d, event.xclient.window,
10259 /* The ICCCM says this is
10260 the only valid choice. */
10261 RevertToParent,
10262 event.xclient.data.l[1]);
10263 /* This is needed to detect the error
10264 if there is an error. */
10265 XSync (d, False);
10266 x_uncatch_errors (d, count);
10267 }
10268 /* Not certain about handling scroll bars here */
10269 #endif /* 0 */
10270 }
10271 else if (event.xclient.data.l[0]
10272 == dpyinfo->Xatom_wm_save_yourself)
10273 {
10274 /* Save state modify the WM_COMMAND property to
10275 something which can reinstate us. This notifies
10276 the session manager, who's looking for such a
10277 PropertyNotify. Can restart processing when
10278 a keyboard or mouse event arrives. */
10279 /* If we have a session manager, don't set this.
10280 KDE will then start two Emacsen, one for the
10281 session manager and one for this. */
10282 if (numchars > 0
10283 #ifdef HAVE_X_SM
10284 && ! x_session_have_connection ()
10285 #endif
10286 )
10287 {
10288 f = x_top_window_to_frame (dpyinfo,
10289 event.xclient.window);
10290 /* This is just so we only give real data once
10291 for a single Emacs process. */
10292 if (f == SELECTED_FRAME ())
10293 XSetCommand (FRAME_X_DISPLAY (f),
10294 event.xclient.window,
10295 initial_argv, initial_argc);
10296 else if (f)
10297 XSetCommand (FRAME_X_DISPLAY (f),
10298 event.xclient.window,
10299 0, 0);
10300 }
10301 }
10302 else if (event.xclient.data.l[0]
10303 == dpyinfo->Xatom_wm_delete_window)
10304 {
10305 struct frame *f
10306 = x_any_window_to_frame (dpyinfo,
10307 event.xclient.window);
10308
10309 if (f)
10310 {
10311 if (numchars == 0)
10312 abort ();
10313
10314 bufp->kind = DELETE_WINDOW_EVENT;
10315 XSETFRAME (bufp->frame_or_window, f);
10316 bufp->arg = Qnil;
10317 bufp++;
10318
10319 count += 1;
10320 numchars -= 1;
10321 }
10322 }
10323 }
10324 else if (event.xclient.message_type
10325 == dpyinfo->Xatom_wm_configure_denied)
10326 {
10327 }
10328 else if (event.xclient.message_type
10329 == dpyinfo->Xatom_wm_window_moved)
10330 {
10331 int new_x, new_y;
10332 struct frame *f
10333 = x_window_to_frame (dpyinfo, event.xclient.window);
10334
10335 new_x = event.xclient.data.s[0];
10336 new_y = event.xclient.data.s[1];
10337
10338 if (f)
10339 {
10340 f->output_data.x->left_pos = new_x;
10341 f->output_data.x->top_pos = new_y;
10342 }
10343 }
10344 #ifdef HACK_EDITRES
10345 else if (event.xclient.message_type
10346 == dpyinfo->Xatom_editres)
10347 {
10348 struct frame *f
10349 = x_any_window_to_frame (dpyinfo, event.xclient.window);
10350 _XEditResCheckMessages (f->output_data.x->widget, NULL,
10351 &event, NULL);
10352 }
10353 #endif /* HACK_EDITRES */
10354 else if ((event.xclient.message_type
10355 == dpyinfo->Xatom_DONE)
10356 || (event.xclient.message_type
10357 == dpyinfo->Xatom_PAGE))
10358 {
10359 /* Ghostview job completed. Kill it. We could
10360 reply with "Next" if we received "Page", but we
10361 currently never do because we are interested in
10362 images, only, which should have 1 page. */
10363 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10364 struct frame *f
10365 = x_window_to_frame (dpyinfo, event.xclient.window);
10366 x_kill_gs_process (pixmap, f);
10367 expose_frame (f, 0, 0, 0, 0);
10368 }
10369 #ifdef USE_TOOLKIT_SCROLL_BARS
10370 /* Scroll bar callbacks send a ClientMessage from which
10371 we construct an input_event. */
10372 else if (event.xclient.message_type
10373 == dpyinfo->Xatom_Scrollbar)
10374 {
10375 x_scroll_bar_to_input_event (&event, bufp);
10376 ++bufp, ++count, --numchars;
10377 goto out;
10378 }
10379 #endif /* USE_TOOLKIT_SCROLL_BARS */
10380 else
10381 goto OTHER;
10382 }
10383 break;
10384
10385 case SelectionNotify:
10386 #ifdef USE_X_TOOLKIT
10387 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
10388 goto OTHER;
10389 #endif /* not USE_X_TOOLKIT */
10390 x_handle_selection_notify (&event.xselection);
10391 break;
10392
10393 case SelectionClear: /* Someone has grabbed ownership. */
10394 #ifdef USE_X_TOOLKIT
10395 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
10396 goto OTHER;
10397 #endif /* USE_X_TOOLKIT */
10398 {
10399 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
10400
10401 if (numchars == 0)
10402 abort ();
10403
10404 bufp->kind = SELECTION_CLEAR_EVENT;
10405 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10406 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10407 SELECTION_EVENT_TIME (bufp) = eventp->time;
10408 bufp->frame_or_window = Qnil;
10409 bufp->arg = Qnil;
10410 bufp++;
10411
10412 count += 1;
10413 numchars -= 1;
10414 }
10415 break;
10416
10417 case SelectionRequest: /* Someone wants our selection. */
10418 #ifdef USE_X_TOOLKIT
10419 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
10420 goto OTHER;
10421 #endif /* USE_X_TOOLKIT */
10422 if (x_queue_selection_requests)
10423 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
10424 &event);
10425 else
10426 {
10427 XSelectionRequestEvent *eventp
10428 = (XSelectionRequestEvent *) &event;
10429
10430 if (numchars == 0)
10431 abort ();
10432
10433 bufp->kind = SELECTION_REQUEST_EVENT;
10434 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10435 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10436 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10437 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10438 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10439 SELECTION_EVENT_TIME (bufp) = eventp->time;
10440 bufp->frame_or_window = Qnil;
10441 bufp->arg = Qnil;
10442 bufp++;
10443
10444 count += 1;
10445 numchars -= 1;
10446 }
10447 break;
10448
10449 case PropertyNotify:
10450 #if 0 /* This is plain wrong. In the case that we are waiting for a
10451 PropertyNotify used as an ACK in incremental selection
10452 transfer, the property will be on the receiver's window. */
10453 #if defined USE_X_TOOLKIT
10454 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
10455 goto OTHER;
10456 #endif
10457 #endif
10458 x_handle_property_notify (&event.xproperty);
10459 goto OTHER;
10460
10461 case ReparentNotify:
10462 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
10463 if (f)
10464 {
10465 int x, y;
10466 f->output_data.x->parent_desc = event.xreparent.parent;
10467 x_real_positions (f, &x, &y);
10468 f->output_data.x->left_pos = x;
10469 f->output_data.x->top_pos = y;
10470 goto OTHER;
10471 }
10472 break;
10473
10474 case Expose:
10475 f = x_window_to_frame (dpyinfo, event.xexpose.window);
10476 if (f)
10477 {
10478 x_check_fullscreen (f);
10479
10480 if (f->async_visible == 0)
10481 {
10482 f->async_visible = 1;
10483 f->async_iconified = 0;
10484 f->output_data.x->has_been_visible = 1;
10485 SET_FRAME_GARBAGED (f);
10486 }
10487 else
10488 expose_frame (x_window_to_frame (dpyinfo,
10489 event.xexpose.window),
10490 event.xexpose.x, event.xexpose.y,
10491 event.xexpose.width, event.xexpose.height);
10492 }
10493 else
10494 {
10495 #ifndef USE_TOOLKIT_SCROLL_BARS
10496 struct scroll_bar *bar;
10497 #endif
10498 #if defined USE_LUCID
10499 /* Submenus of the Lucid menu bar aren't widgets
10500 themselves, so there's no way to dispatch events
10501 to them. Recognize this case separately. */
10502 {
10503 Widget widget
10504 = x_window_to_menu_bar (event.xexpose.window);
10505 if (widget)
10506 xlwmenu_redisplay (widget);
10507 }
10508 #endif /* USE_LUCID */
10509
10510 #ifdef USE_TOOLKIT_SCROLL_BARS
10511 /* Dispatch event to the widget. */
10512 goto OTHER;
10513 #else /* not USE_TOOLKIT_SCROLL_BARS */
10514 bar = x_window_to_scroll_bar (event.xexpose.window);
10515
10516 if (bar)
10517 x_scroll_bar_expose (bar, &event);
10518 #ifdef USE_X_TOOLKIT
10519 else
10520 goto OTHER;
10521 #endif /* USE_X_TOOLKIT */
10522 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10523 }
10524 break;
10525
10526 case GraphicsExpose: /* This occurs when an XCopyArea's
10527 source area was obscured or not
10528 available. */
10529 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
10530 if (f)
10531 {
10532 expose_frame (f,
10533 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10534 event.xgraphicsexpose.width,
10535 event.xgraphicsexpose.height);
10536 }
10537 #ifdef USE_X_TOOLKIT
10538 else
10539 goto OTHER;
10540 #endif /* USE_X_TOOLKIT */
10541 break;
10542
10543 case NoExpose: /* This occurs when an XCopyArea's
10544 source area was completely
10545 available. */
10546 break;
10547
10548 case UnmapNotify:
10549 /* Redo the mouse-highlight after the tooltip has gone. */
10550 if (event.xmap.window == tip_window)
10551 {
10552 tip_window = 0;
10553 redo_mouse_highlight ();
10554 }
10555
10556 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
10557 if (f) /* F may no longer exist if
10558 the frame was deleted. */
10559 {
10560 /* While a frame is unmapped, display generation is
10561 disabled; you don't want to spend time updating a
10562 display that won't ever be seen. */
10563 f->async_visible = 0;
10564 /* We can't distinguish, from the event, whether the window
10565 has become iconified or invisible. So assume, if it
10566 was previously visible, than now it is iconified.
10567 But x_make_frame_invisible clears both
10568 the visible flag and the iconified flag;
10569 and that way, we know the window is not iconified now. */
10570 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
10571 {
10572 f->async_iconified = 1;
10573
10574 bufp->kind = ICONIFY_EVENT;
10575 XSETFRAME (bufp->frame_or_window, f);
10576 bufp->arg = Qnil;
10577 bufp++;
10578 count++;
10579 numchars--;
10580 }
10581 }
10582 goto OTHER;
10583
10584 case MapNotify:
10585 if (event.xmap.window == tip_window)
10586 /* The tooltip has been drawn already. Avoid
10587 the SET_FRAME_GARBAGED below. */
10588 goto OTHER;
10589
10590 /* We use x_top_window_to_frame because map events can
10591 come for sub-windows and they don't mean that the
10592 frame is visible. */
10593 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
10594 if (f)
10595 {
10596 f->async_visible = 1;
10597 f->async_iconified = 0;
10598 f->output_data.x->has_been_visible = 1;
10599
10600 /* wait_reading_process_input will notice this and update
10601 the frame's display structures. */
10602 SET_FRAME_GARBAGED (f);
10603
10604 if (f->iconified)
10605 {
10606 bufp->kind = DEICONIFY_EVENT;
10607 XSETFRAME (bufp->frame_or_window, f);
10608 bufp->arg = Qnil;
10609 bufp++;
10610 count++;
10611 numchars--;
10612 }
10613 else if (! NILP (Vframe_list)
10614 && ! NILP (XCDR (Vframe_list)))
10615 /* Force a redisplay sooner or later
10616 to update the frame titles
10617 in case this is the second frame. */
10618 record_asynch_buffer_change ();
10619 }
10620 goto OTHER;
10621
10622 case KeyPress:
10623
10624 /* Dispatch KeyPress events when in menu. */
10625 if (popup_activated_flag)
10626 goto OTHER;
10627
10628 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
10629
10630 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10631 {
10632 dpyinfo->mouse_face_hidden = 1;
10633 clear_mouse_face (dpyinfo);
10634 }
10635
10636 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
10637 if (f == 0)
10638 {
10639 /* Scroll bars consume key events, but we want
10640 the keys to go to the scroll bar's frame. */
10641 Widget widget = XtWindowToWidget (dpyinfo->display,
10642 event.xkey.window);
10643 if (widget && XmIsScrollBar (widget))
10644 {
10645 widget = XtParent (widget);
10646 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10647 }
10648 }
10649 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
10650
10651 if (f != 0)
10652 {
10653 KeySym keysym, orig_keysym;
10654 /* al%imercury@uunet.uu.net says that making this 81
10655 instead of 80 fixed a bug whereby meta chars made
10656 his Emacs hang.
10657
10658 It seems that some version of XmbLookupString has
10659 a bug of not returning XBufferOverflow in
10660 status_return even if the input is too long to
10661 fit in 81 bytes. So, we must prepare sufficient
10662 bytes for copy_buffer. 513 bytes (256 chars for
10663 two-byte character set) seems to be a fairly good
10664 approximation. -- 2000.8.10 handa@etl.go.jp */
10665 unsigned char copy_buffer[513];
10666 unsigned char *copy_bufptr = copy_buffer;
10667 int copy_bufsiz = sizeof (copy_buffer);
10668 int modifiers;
10669 Lisp_Object coding_system = Qlatin_1;
10670
10671 event.xkey.state
10672 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10673 extra_keyboard_modifiers);
10674 modifiers = event.xkey.state;
10675
10676 /* This will have to go some day... */
10677
10678 /* make_lispy_event turns chars into control chars.
10679 Don't do it here because XLookupString is too eager. */
10680 event.xkey.state &= ~ControlMask;
10681 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10682 | dpyinfo->super_mod_mask
10683 | dpyinfo->hyper_mod_mask
10684 | dpyinfo->alt_mod_mask);
10685
10686 /* In case Meta is ComposeCharacter,
10687 clear its status. According to Markus Ehrnsperger
10688 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10689 this enables ComposeCharacter to work whether or
10690 not it is combined with Meta. */
10691 if (modifiers & dpyinfo->meta_mod_mask)
10692 bzero (&compose_status, sizeof (compose_status));
10693
10694 #ifdef HAVE_X_I18N
10695 if (FRAME_XIC (f))
10696 {
10697 Status status_return;
10698
10699 coding_system = Vlocale_coding_system;
10700 nbytes = XmbLookupString (FRAME_XIC (f),
10701 &event.xkey, copy_bufptr,
10702 copy_bufsiz, &keysym,
10703 &status_return);
10704 if (status_return == XBufferOverflow)
10705 {
10706 copy_bufsiz = nbytes + 1;
10707 copy_bufptr = (char *) alloca (copy_bufsiz);
10708 nbytes = XmbLookupString (FRAME_XIC (f),
10709 &event.xkey, copy_bufptr,
10710 copy_bufsiz, &keysym,
10711 &status_return);
10712 }
10713 /* Xutf8LookupString is a new but already deprecated interface. -stef */
10714 #if 0 && defined X_HAVE_UTF8_STRING
10715 else if (status_return == XLookupKeySym)
10716 { /* Try again but with utf-8. */
10717 coding_system = Qutf_8;
10718 nbytes = Xutf8LookupString (FRAME_XIC (f),
10719 &event.xkey, copy_bufptr,
10720 copy_bufsiz, &keysym,
10721 &status_return);
10722 if (status_return == XBufferOverflow)
10723 {
10724 copy_bufsiz = nbytes + 1;
10725 copy_bufptr = (char *) alloca (copy_bufsiz);
10726 nbytes = Xutf8LookupString (FRAME_XIC (f),
10727 &event.xkey,
10728 copy_bufptr,
10729 copy_bufsiz, &keysym,
10730 &status_return);
10731 }
10732 }
10733 #endif
10734
10735 if (status_return == XLookupNone)
10736 break;
10737 else if (status_return == XLookupChars)
10738 {
10739 keysym = NoSymbol;
10740 modifiers = 0;
10741 }
10742 else if (status_return != XLookupKeySym
10743 && status_return != XLookupBoth)
10744 abort ();
10745 }
10746 else
10747 nbytes = XLookupString (&event.xkey, copy_bufptr,
10748 copy_bufsiz, &keysym,
10749 &compose_status);
10750 #else
10751 nbytes = XLookupString (&event.xkey, copy_bufptr,
10752 copy_bufsiz, &keysym,
10753 &compose_status);
10754 #endif
10755
10756 orig_keysym = keysym;
10757
10758 if (numchars > 1)
10759 {
10760 Lisp_Object c;
10761
10762 /* First deal with keysyms which have defined
10763 translations to characters. */
10764 if (keysym >= 32 && keysym < 128)
10765 /* Avoid explicitly decoding each ASCII character. */
10766 {
10767 bufp->kind = ASCII_KEYSTROKE_EVENT;
10768 bufp->code = keysym;
10769 XSETFRAME (bufp->frame_or_window, f);
10770 bufp->arg = Qnil;
10771 bufp->modifiers
10772 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10773 modifiers);
10774 bufp->timestamp = event.xkey.time;
10775 bufp++;
10776 count++;
10777 numchars--;
10778 }
10779 /* Now non-ASCII. */
10780 else if (HASH_TABLE_P (Vx_keysym_table)
10781 && (NATNUMP (c = Fgethash (make_number (keysym),
10782 Vx_keysym_table,
10783 Qnil))))
10784 {
10785 bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
10786 ? ASCII_KEYSTROKE_EVENT
10787 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10788 bufp->code = XFASTINT (c);
10789 XSETFRAME (bufp->frame_or_window, f);
10790 bufp->arg = Qnil;
10791 bufp->modifiers
10792 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10793 modifiers);
10794 bufp->timestamp = event.xkey.time;
10795 bufp++;
10796 count++;
10797 numchars--;
10798 }
10799 /* Random non-modifier sorts of keysyms. */
10800 else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10801 || keysym == XK_Delete
10802 #ifdef XK_ISO_Left_Tab
10803 || (keysym >= XK_ISO_Left_Tab
10804 && keysym <= XK_ISO_Enter)
10805 #endif
10806 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10807 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
10808 #ifdef HPUX
10809 /* This recognizes the "extended function
10810 keys". It seems there's no cleaner way.
10811 Test IsModifierKey to avoid handling
10812 mode_switch incorrectly. */
10813 || ((unsigned) (keysym) >= XK_Select
10814 && (unsigned)(keysym) < XK_KP_Space)
10815 #endif
10816 #ifdef XK_dead_circumflex
10817 || orig_keysym == XK_dead_circumflex
10818 #endif
10819 #ifdef XK_dead_grave
10820 || orig_keysym == XK_dead_grave
10821 #endif
10822 #ifdef XK_dead_tilde
10823 || orig_keysym == XK_dead_tilde
10824 #endif
10825 #ifdef XK_dead_diaeresis
10826 || orig_keysym == XK_dead_diaeresis
10827 #endif
10828 #ifdef XK_dead_macron
10829 || orig_keysym == XK_dead_macron
10830 #endif
10831 #ifdef XK_dead_degree
10832 || orig_keysym == XK_dead_degree
10833 #endif
10834 #ifdef XK_dead_acute
10835 || orig_keysym == XK_dead_acute
10836 #endif
10837 #ifdef XK_dead_cedilla
10838 || orig_keysym == XK_dead_cedilla
10839 #endif
10840 #ifdef XK_dead_breve
10841 || orig_keysym == XK_dead_breve
10842 #endif
10843 #ifdef XK_dead_ogonek
10844 || orig_keysym == XK_dead_ogonek
10845 #endif
10846 #ifdef XK_dead_caron
10847 || orig_keysym == XK_dead_caron
10848 #endif
10849 #ifdef XK_dead_doubleacute
10850 || orig_keysym == XK_dead_doubleacute
10851 #endif
10852 #ifdef XK_dead_abovedot
10853 || orig_keysym == XK_dead_abovedot
10854 #endif
10855 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10856 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10857 /* Any "vendor-specific" key is ok. */
10858 || (orig_keysym & (1 << 28))
10859 || (keysym != NoSymbol && nbytes == 0))
10860 && ! (IsModifierKey (orig_keysym)
10861 #ifndef HAVE_X11R5
10862 #ifdef XK_Mode_switch
10863 || ((unsigned)(orig_keysym) == XK_Mode_switch)
10864 #endif
10865 #ifdef XK_Num_Lock
10866 || ((unsigned)(orig_keysym) == XK_Num_Lock)
10867 #endif
10868 #endif /* not HAVE_X11R5 */
10869 /* The symbols from XK_ISO_Lock
10870 to XK_ISO_Last_Group_Lock
10871 don't have real modifiers but
10872 should be treated similarly to
10873 Mode_switch by Emacs. */
10874 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
10875 || ((unsigned)(orig_keysym)
10876 >= XK_ISO_Lock
10877 && (unsigned)(orig_keysym)
10878 <= XK_ISO_Last_Group_Lock)
10879 #endif
10880 ))
10881 {
10882 if (temp_index == sizeof temp_buffer / sizeof (short))
10883 temp_index = 0;
10884 temp_buffer[temp_index++] = keysym;
10885 /* make_lispy_event will convert this to a symbolic
10886 key. */
10887 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
10888 bufp->code = keysym;
10889 XSETFRAME (bufp->frame_or_window, f);
10890 bufp->arg = Qnil;
10891 bufp->modifiers
10892 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10893 modifiers);
10894 bufp->timestamp = event.xkey.time;
10895 bufp++;
10896 count++;
10897 numchars--;
10898 }
10899 else if (numchars > nbytes)
10900 { /* Raw bytes, not keysym. */
10901 register int i;
10902 register int c;
10903 int nchars, len;
10904
10905 /* The input should be decoded with `coding_system'
10906 which depends on which X*LookupString function
10907 we used just above and the locale. */
10908 setup_coding_system (coding_system, &coding);
10909 coding.src_multibyte = 0;
10910 coding.dst_multibyte = 1;
10911 /* The input is converted to events, thus we can't
10912 handle composition. Anyway, there's no XIM that
10913 gives us composition information. */
10914 coding.composing = COMPOSITION_DISABLED;
10915
10916 for (i = 0; i < nbytes; i++)
10917 {
10918 if (temp_index == (sizeof temp_buffer
10919 / sizeof (short)))
10920 temp_index = 0;
10921 temp_buffer[temp_index++] = copy_bufptr[i];
10922 }
10923
10924 {
10925 /* Decode the input data. */
10926 int require;
10927 unsigned char *p;
10928
10929 require = decoding_buffer_size (&coding, nbytes);
10930 p = (unsigned char *) alloca (require);
10931 coding.mode |= CODING_MODE_LAST_BLOCK;
10932 /* We explicitely disable composition
10933 handling because key data should
10934 not contain any composition
10935 sequence. */
10936 coding.composing = COMPOSITION_DISABLED;
10937 decode_coding (&coding, copy_bufptr, p,
10938 nbytes, require);
10939 nbytes = coding.produced;
10940 nchars = coding.produced_char;
10941 copy_bufptr = p;
10942 }
10943
10944 /* Convert the input data to a sequence of
10945 character events. */
10946 for (i = 0; i < nbytes; i += len)
10947 {
10948 if (nchars == nbytes)
10949 c = copy_bufptr[i], len = 1;
10950 else
10951 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10952 nbytes - i, len);
10953
10954 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10955 ? ASCII_KEYSTROKE_EVENT
10956 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
10957 bufp->code = c;
10958 XSETFRAME (bufp->frame_or_window, f);
10959 bufp->arg = Qnil;
10960 bufp->modifiers
10961 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10962 modifiers);
10963 bufp->timestamp = event.xkey.time;
10964 bufp++;
10965 }
10966
10967 count += nchars;
10968 numchars -= nchars;
10969
10970 if (keysym == NoSymbol)
10971 break;
10972 }
10973 else
10974 abort ();
10975 }
10976 else
10977 abort ();
10978 }
10979 #ifdef HAVE_X_I18N
10980 /* Don't dispatch this event since XtDispatchEvent calls
10981 XFilterEvent, and two calls in a row may freeze the
10982 client. */
10983 break;
10984 #else
10985 goto OTHER;
10986 #endif
10987
10988 case KeyRelease:
10989 #ifdef HAVE_X_I18N
10990 /* Don't dispatch this event since XtDispatchEvent calls
10991 XFilterEvent, and two calls in a row may freeze the
10992 client. */
10993 break;
10994 #else
10995 goto OTHER;
10996 #endif
10997
10998 case EnterNotify:
10999 {
11000 int n;
11001
11002 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11003 if (n > 0)
11004 {
11005 bufp += n, count += n, numchars -= n;
11006 }
11007
11008 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
11009
11010 #if 0
11011 if (event.xcrossing.focus)
11012 {
11013 /* Avoid nasty pop/raise loops. */
11014 if (f && (!(f->auto_raise)
11015 || !(f->auto_lower)
11016 || (event.xcrossing.time - enter_timestamp) > 500))
11017 {
11018 x_new_focus_frame (dpyinfo, f);
11019 enter_timestamp = event.xcrossing.time;
11020 }
11021 }
11022 else if (f == dpyinfo->x_focus_frame)
11023 x_new_focus_frame (dpyinfo, 0);
11024 #endif
11025
11026 /* EnterNotify counts as mouse movement,
11027 so update things that depend on mouse position. */
11028 if (f && !f->output_data.x->hourglass_p)
11029 note_mouse_movement (f, &event.xmotion);
11030 goto OTHER;
11031 }
11032
11033 case FocusIn:
11034 {
11035 int n;
11036
11037 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11038 if (n > 0)
11039 {
11040 bufp += n, count += n, numchars -= n;
11041 }
11042 }
11043
11044 goto OTHER;
11045
11046 case LeaveNotify:
11047 {
11048 int n;
11049
11050 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11051 if (n > 0)
11052 {
11053 bufp += n, count += n, numchars -= n;
11054 }
11055 }
11056
11057 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
11058 if (f)
11059 {
11060 if (f == dpyinfo->mouse_face_mouse_frame)
11061 {
11062 /* If we move outside the frame, then we're
11063 certainly no longer on any text in the frame. */
11064 clear_mouse_face (dpyinfo);
11065 dpyinfo->mouse_face_mouse_frame = 0;
11066 }
11067
11068 /* Generate a nil HELP_EVENT to cancel a help-echo.
11069 Do it only if there's something to cancel.
11070 Otherwise, the startup message is cleared when
11071 the mouse leaves the frame. */
11072 if (any_help_event_p)
11073 {
11074 Lisp_Object frame;
11075 int n;
11076
11077 XSETFRAME (frame, f);
11078 help_echo = Qnil;
11079 n = gen_help_event (bufp, numchars,
11080 Qnil, frame, Qnil, Qnil, 0);
11081 bufp += n, count += n, numchars -= n;
11082 }
11083
11084 }
11085 goto OTHER;
11086
11087 case FocusOut:
11088 {
11089 int n;
11090
11091 n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
11092 if (n > 0)
11093 {
11094 bufp += n, count += n, numchars -= n;
11095 }
11096 }
11097
11098 goto OTHER;
11099
11100 case MotionNotify:
11101 {
11102 previous_help_echo = help_echo;
11103 help_echo = help_echo_object = help_echo_window = Qnil;
11104 help_echo_pos = -1;
11105
11106 if (dpyinfo->grabbed && last_mouse_frame
11107 && FRAME_LIVE_P (last_mouse_frame))
11108 f = last_mouse_frame;
11109 else
11110 f = x_window_to_frame (dpyinfo, event.xmotion.window);
11111
11112 if (dpyinfo->mouse_face_hidden)
11113 {
11114 dpyinfo->mouse_face_hidden = 0;
11115 clear_mouse_face (dpyinfo);
11116 }
11117
11118 if (f)
11119 {
11120
11121 /* Generate SELECT_WINDOW_EVENTs when needed. */
11122 if (mouse_autoselect_window)
11123 {
11124 Lisp_Object window;
11125 int area;
11126
11127 window = window_from_coordinates (f,
11128 event.xmotion.x, event.xmotion.y,
11129 &area, 0);
11130
11131 /* Window will be selected only when it is not selected now and
11132 last mouse movement event was not in it. Minibuffer window
11133 will be selected iff it is active. */
11134 if (WINDOWP(window)
11135 && !EQ (window, last_window)
11136 && !EQ (window, selected_window)
11137 && numchars > 0)
11138 {
11139 bufp->kind = SELECT_WINDOW_EVENT;
11140 bufp->frame_or_window = window;
11141 bufp->arg = Qnil;
11142 ++bufp, ++count, --numchars;
11143 }
11144
11145 last_window=window;
11146 }
11147 note_mouse_movement (f, &event.xmotion);
11148 }
11149 else
11150 {
11151 #ifndef USE_TOOLKIT_SCROLL_BARS
11152 struct scroll_bar *bar
11153 = x_window_to_scroll_bar (event.xmotion.window);
11154
11155 if (bar)
11156 x_scroll_bar_note_movement (bar, &event);
11157 #endif /* USE_TOOLKIT_SCROLL_BARS */
11158
11159 /* If we move outside the frame, then we're
11160 certainly no longer on any text in the frame. */
11161 clear_mouse_face (dpyinfo);
11162 }
11163
11164 /* If the contents of the global variable help_echo
11165 has changed, generate a HELP_EVENT. */
11166 if (!NILP (help_echo)
11167 || !NILP (previous_help_echo))
11168 {
11169 Lisp_Object frame;
11170 int n;
11171
11172 if (f)
11173 XSETFRAME (frame, f);
11174 else
11175 frame = Qnil;
11176
11177 any_help_event_p = 1;
11178 n = gen_help_event (bufp, numchars, help_echo, frame,
11179 help_echo_window, help_echo_object,
11180 help_echo_pos);
11181 bufp += n, count += n, numchars -= n;
11182 }
11183
11184 goto OTHER;
11185 }
11186
11187 case ConfigureNotify:
11188 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
11189 if (f)
11190 {
11191 #ifndef USE_X_TOOLKIT
11192 /* If there is a pending resize for fullscreen, don't
11193 do this one, the right one will come later.
11194 The toolkit version doesn't seem to need this, but we
11195 need to reset it below. */
11196 int dont_resize =
11197 ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11198 && FRAME_NEW_WIDTH (f) != 0);
11199 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
11200 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
11201 if (dont_resize)
11202 goto OTHER;
11203
11204 /* In the toolkit version, change_frame_size
11205 is called by the code that handles resizing
11206 of the EmacsFrame widget. */
11207
11208 /* Even if the number of character rows and columns has
11209 not changed, the font size may have changed, so we need
11210 to check the pixel dimensions as well. */
11211 if (columns != f->width
11212 || rows != f->height
11213 || event.xconfigure.width != f->output_data.x->pixel_width
11214 || event.xconfigure.height != f->output_data.x->pixel_height)
11215 {
11216 change_frame_size (f, rows, columns, 0, 1, 0);
11217 SET_FRAME_GARBAGED (f);
11218 cancel_mouse_face (f);
11219 }
11220 #endif
11221
11222 f->output_data.x->pixel_width = event.xconfigure.width;
11223 f->output_data.x->pixel_height = event.xconfigure.height;
11224
11225 /* What we have now is the position of Emacs's own window.
11226 Convert that to the position of the window manager window. */
11227 x_real_positions (f, &f->output_data.x->left_pos,
11228 &f->output_data.x->top_pos);
11229
11230 x_check_fullscreen_move(f);
11231 if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
11232 f->output_data.x->want_fullscreen &=
11233 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
11234 #ifdef HAVE_X_I18N
11235 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
11236 xic_set_statusarea (f);
11237 #endif
11238
11239 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11240 {
11241 /* Since the WM decorations come below top_pos now,
11242 we must put them below top_pos in the future. */
11243 f->output_data.x->win_gravity = NorthWestGravity;
11244 x_wm_set_size_hint (f, (long) 0, 0);
11245 }
11246 }
11247 goto OTHER;
11248
11249 case ButtonPress:
11250 case ButtonRelease:
11251 {
11252 /* If we decide we want to generate an event to be seen
11253 by the rest of Emacs, we put it here. */
11254 struct input_event emacs_event;
11255 int tool_bar_p = 0;
11256
11257 emacs_event.kind = NO_EVENT;
11258 bzero (&compose_status, sizeof (compose_status));
11259
11260 if (dpyinfo->grabbed
11261 && last_mouse_frame
11262 && FRAME_LIVE_P (last_mouse_frame))
11263 f = last_mouse_frame;
11264 else
11265 f = x_window_to_frame (dpyinfo, event.xbutton.window);
11266
11267 if (f)
11268 {
11269 /* Is this in the tool-bar? */
11270 if (WINDOWP (f->tool_bar_window)
11271 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
11272 {
11273 Lisp_Object window;
11274 int p, x, y;
11275
11276 x = event.xbutton.x;
11277 y = event.xbutton.y;
11278
11279 /* Set x and y. */
11280 window = window_from_coordinates (f, x, y, &p, 1);
11281 if (EQ (window, f->tool_bar_window))
11282 {
11283 x_handle_tool_bar_click (f, &event.xbutton);
11284 tool_bar_p = 1;
11285 }
11286 }
11287
11288 if (!tool_bar_p)
11289 if (!dpyinfo->x_focus_frame
11290 || f == dpyinfo->x_focus_frame)
11291 construct_mouse_click (&emacs_event, &event, f);
11292 }
11293 else
11294 {
11295 #ifndef USE_TOOLKIT_SCROLL_BARS
11296 struct scroll_bar *bar
11297 = x_window_to_scroll_bar (event.xbutton.window);
11298
11299 if (bar)
11300 x_scroll_bar_handle_click (bar, &event, &emacs_event);
11301 #endif /* not USE_TOOLKIT_SCROLL_BARS */
11302 }
11303
11304 if (event.type == ButtonPress)
11305 {
11306 dpyinfo->grabbed |= (1 << event.xbutton.button);
11307 last_mouse_frame = f;
11308 /* Ignore any mouse motion that happened
11309 before this event; any subsequent mouse-movement
11310 Emacs events should reflect only motion after
11311 the ButtonPress. */
11312 if (f != 0)
11313 f->mouse_moved = 0;
11314
11315 if (!tool_bar_p)
11316 last_tool_bar_item = -1;
11317 }
11318 else
11319 {
11320 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
11321 }
11322
11323 if (numchars >= 1 && emacs_event.kind != NO_EVENT)
11324 {
11325 bcopy (&emacs_event, bufp, sizeof (struct input_event));
11326 bufp++;
11327 count++;
11328 numchars--;
11329 }
11330
11331 #ifdef USE_X_TOOLKIT
11332 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
11333 /* For a down-event in the menu bar,
11334 don't pass it to Xt right now.
11335 Instead, save it away
11336 and we will pass it to Xt from kbd_buffer_get_event.
11337 That way, we can run some Lisp code first. */
11338 if (f && event.type == ButtonPress
11339 /* Verify the event is really within the menu bar
11340 and not just sent to it due to grabbing. */
11341 && event.xbutton.x >= 0
11342 && event.xbutton.x < f->output_data.x->pixel_width
11343 && event.xbutton.y >= 0
11344 && event.xbutton.y < f->output_data.x->menubar_height
11345 && event.xbutton.same_screen)
11346 {
11347 SET_SAVED_BUTTON_EVENT;
11348 XSETFRAME (last_mouse_press_frame, f);
11349 }
11350 else if (event.type == ButtonPress)
11351 {
11352 last_mouse_press_frame = Qnil;
11353 goto OTHER;
11354 }
11355
11356 #ifdef USE_MOTIF /* This should do not harm for Lucid,
11357 but I am trying to be cautious. */
11358 else if (event.type == ButtonRelease)
11359 {
11360 if (!NILP (last_mouse_press_frame))
11361 {
11362 f = XFRAME (last_mouse_press_frame);
11363 if (f->output_data.x)
11364 SET_SAVED_BUTTON_EVENT;
11365 }
11366 else
11367 goto OTHER;
11368 }
11369 #endif /* USE_MOTIF */
11370 else
11371 goto OTHER;
11372 #endif /* USE_X_TOOLKIT */
11373 }
11374 break;
11375
11376 case CirculateNotify:
11377 goto OTHER;
11378
11379 case CirculateRequest:
11380 goto OTHER;
11381
11382 case VisibilityNotify:
11383 goto OTHER;
11384
11385 case MappingNotify:
11386 /* Someone has changed the keyboard mapping - update the
11387 local cache. */
11388 switch (event.xmapping.request)
11389 {
11390 case MappingModifier:
11391 x_find_modifier_meanings (dpyinfo);
11392 /* This is meant to fall through. */
11393 case MappingKeyboard:
11394 XRefreshKeyboardMapping (&event.xmapping);
11395 }
11396 goto OTHER;
11397
11398 default:
11399 OTHER:
11400 #ifdef USE_X_TOOLKIT
11401 BLOCK_INPUT;
11402 XtDispatchEvent (&event);
11403 UNBLOCK_INPUT;
11404 #endif /* USE_X_TOOLKIT */
11405 break;
11406 }
11407 }
11408 }
11409
11410 out:;
11411
11412 /* On some systems, an X bug causes Emacs to get no more events
11413 when the window is destroyed. Detect that. (1994.) */
11414 if (! event_found)
11415 {
11416 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11417 One XNOOP in 100 loops will make Emacs terminate.
11418 B. Bretthauer, 1994 */
11419 x_noop_count++;
11420 if (x_noop_count >= 100)
11421 {
11422 x_noop_count=0;
11423
11424 if (next_noop_dpyinfo == 0)
11425 next_noop_dpyinfo = x_display_list;
11426
11427 XNoOp (next_noop_dpyinfo->display);
11428
11429 /* Each time we get here, cycle through the displays now open. */
11430 next_noop_dpyinfo = next_noop_dpyinfo->next;
11431 }
11432 }
11433
11434 /* If the focus was just given to an auto-raising frame,
11435 raise it now. */
11436 /* ??? This ought to be able to handle more than one such frame. */
11437 if (pending_autoraise_frame)
11438 {
11439 x_raise_frame (pending_autoraise_frame);
11440 pending_autoraise_frame = 0;
11441 }
11442
11443 UNBLOCK_INPUT;
11444 --handling_signal;
11445 return count;
11446 }
11447
11448
11449
11450 \f
11451 /***********************************************************************
11452 Text Cursor
11453 ***********************************************************************/
11454
11455 /* Notice when the text cursor of window W has been completely
11456 overwritten by a drawing operation that outputs glyphs in AREA
11457 starting at X0 and ending at X1 in the line starting at Y0 and
11458 ending at Y1. X coordinates are area-relative. X1 < 0 means all
11459 the rest of the line after X0 has been written. Y coordinates
11460 are window-relative. */
11461
11462 static void
11463 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
11464 struct window *w;
11465 enum glyph_row_area area;
11466 int x0, y0, x1, y1;
11467 {
11468 if (area == TEXT_AREA && w->phys_cursor_on_p)
11469 {
11470 int cx0 = w->phys_cursor.x;
11471 int cx1 = cx0 + w->phys_cursor_width;
11472 int cy0 = w->phys_cursor.y;
11473 int cy1 = cy0 + w->phys_cursor_height;
11474
11475 if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
11476 {
11477 /* The cursor image will be completely removed from the
11478 screen if the output area intersects the cursor area in
11479 y-direction. When we draw in [y0 y1[, and some part of
11480 the cursor is at y < y0, that part must have been drawn
11481 before. When scrolling, the cursor is erased before
11482 actually scrolling, so we don't come here. When not
11483 scrolling, the rows above the old cursor row must have
11484 changed, and in this case these rows must have written
11485 over the cursor image.
11486
11487 Likewise if part of the cursor is below y1, with the
11488 exception of the cursor being in the first blank row at
11489 the buffer and window end because update_text_area
11490 doesn't draw that row. (Except when it does, but
11491 that's handled in update_text_area.) */
11492
11493 if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
11494 && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
11495 w->phys_cursor_on_p = 0;
11496 }
11497 }
11498 }
11499
11500
11501 /* Set clipping for output in glyph row ROW. W is the window in which
11502 we operate. GC is the graphics context to set clipping in.
11503 WHOLE_LINE_P non-zero means include the areas used for truncation
11504 mark display and alike in the clipping rectangle.
11505
11506 ROW may be a text row or, e.g., a mode line. Text rows must be
11507 clipped to the interior of the window dedicated to text display,
11508 mode lines must be clipped to the whole window. */
11509
11510 static void
11511 x_clip_to_row (w, row, gc, whole_line_p)
11512 struct window *w;
11513 struct glyph_row *row;
11514 GC gc;
11515 int whole_line_p;
11516 {
11517 struct frame *f = XFRAME (WINDOW_FRAME (w));
11518 XRectangle clip_rect;
11519 int window_x, window_y, window_width, window_height;
11520
11521 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
11522
11523 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11524 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11525 clip_rect.y = max (clip_rect.y, window_y);
11526 clip_rect.width = window_width;
11527 clip_rect.height = row->visible_height;
11528
11529 /* If clipping to the whole line, including trunc marks, extend
11530 the rectangle to the left and increase its width. */
11531 if (whole_line_p)
11532 {
11533 clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
11534 clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
11535 }
11536
11537 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
11538 }
11539
11540
11541 /* Draw a hollow box cursor on window W in glyph row ROW. */
11542
11543 static void
11544 x_draw_hollow_cursor (w, row)
11545 struct window *w;
11546 struct glyph_row *row;
11547 {
11548 struct frame *f = XFRAME (WINDOW_FRAME (w));
11549 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11550 Display *dpy = FRAME_X_DISPLAY (f);
11551 int x, y, wd, h;
11552 XGCValues xgcv;
11553 struct glyph *cursor_glyph;
11554 GC gc;
11555
11556 /* Compute frame-relative coordinates from window-relative
11557 coordinates. */
11558 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11559 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11560 + row->ascent - w->phys_cursor_ascent);
11561 h = row->height - 1;
11562
11563 /* Get the glyph the cursor is on. If we can't tell because
11564 the current matrix is invalid or such, give up. */
11565 cursor_glyph = get_phys_cursor_glyph (w);
11566 if (cursor_glyph == NULL)
11567 return;
11568
11569 /* Compute the width of the rectangle to draw. If on a stretch
11570 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11571 rectangle as wide as the glyph, but use a canonical character
11572 width instead. */
11573 wd = cursor_glyph->pixel_width - 1;
11574 if (cursor_glyph->type == STRETCH_GLYPH
11575 && !x_stretch_cursor_p)
11576 wd = min (CANON_X_UNIT (f), wd);
11577 w->phys_cursor_width = wd;
11578
11579 /* The foreground of cursor_gc is typically the same as the normal
11580 background color, which can cause the cursor box to be invisible. */
11581 xgcv.foreground = f->output_data.x->cursor_pixel;
11582 if (dpyinfo->scratch_cursor_gc)
11583 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11584 else
11585 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11586 GCForeground, &xgcv);
11587 gc = dpyinfo->scratch_cursor_gc;
11588
11589 /* Set clipping, draw the rectangle, and reset clipping again. */
11590 x_clip_to_row (w, row, gc, 0);
11591 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11592 XSetClipMask (dpy, gc, None);
11593 }
11594
11595
11596 /* Draw a bar cursor on window W in glyph row ROW.
11597
11598 Implementation note: One would like to draw a bar cursor with an
11599 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11600 Unfortunately, I didn't find a font yet that has this property set.
11601 --gerd. */
11602
11603 static void
11604 x_draw_bar_cursor (w, row, width, kind)
11605 struct window *w;
11606 struct glyph_row *row;
11607 int width;
11608 enum text_cursor_kinds kind;
11609 {
11610 struct frame *f = XFRAME (w->frame);
11611 struct glyph *cursor_glyph;
11612
11613 /* If cursor is out of bounds, don't draw garbage. This can happen
11614 in mini-buffer windows when switching between echo area glyphs
11615 and mini-buffer. */
11616 cursor_glyph = get_phys_cursor_glyph (w);
11617 if (cursor_glyph == NULL)
11618 return;
11619
11620 /* If on an image, draw like a normal cursor. That's usually better
11621 visible than drawing a bar, esp. if the image is large so that
11622 the bar might not be in the window. */
11623 if (cursor_glyph->type == IMAGE_GLYPH)
11624 {
11625 struct glyph_row *row;
11626 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11627 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11628 }
11629 else
11630 {
11631 Display *dpy = FRAME_X_DISPLAY (f);
11632 Window window = FRAME_X_WINDOW (f);
11633 GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
11634 unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
11635 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
11636 XGCValues xgcv;
11637
11638 /* If the glyph's background equals the color we normally draw
11639 the bar cursor in, the bar cursor in its normal color is
11640 invisible. Use the glyph's foreground color instead in this
11641 case, on the assumption that the glyph's colors are chosen so
11642 that the glyph is legible. */
11643 if (face->background == f->output_data.x->cursor_pixel)
11644 xgcv.background = xgcv.foreground = face->foreground;
11645 else
11646 xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
11647 xgcv.graphics_exposures = 0;
11648
11649 if (gc)
11650 XChangeGC (dpy, gc, mask, &xgcv);
11651 else
11652 {
11653 gc = XCreateGC (dpy, window, mask, &xgcv);
11654 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11655 }
11656
11657 if (width < 0)
11658 width = FRAME_CURSOR_WIDTH (f);
11659 width = min (cursor_glyph->pixel_width, width);
11660
11661 w->phys_cursor_width = width;
11662 x_clip_to_row (w, row, gc, 0);
11663
11664 if (kind == BAR_CURSOR)
11665 XFillRectangle (dpy, window, gc,
11666 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11667 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
11668 width, row->height);
11669 else
11670 XFillRectangle (dpy, window, gc,
11671 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
11672 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
11673 row->height - width),
11674 cursor_glyph->pixel_width,
11675 width);
11676
11677 XSetClipMask (dpy, gc, None);
11678 }
11679 }
11680
11681
11682 /* Clear the cursor of window W to background color, and mark the
11683 cursor as not shown. This is used when the text where the cursor
11684 is is about to be rewritten. */
11685
11686 static void
11687 x_clear_cursor (w)
11688 struct window *w;
11689 {
11690 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11691 x_update_window_cursor (w, 0);
11692 }
11693
11694
11695 /* Draw the cursor glyph of window W in glyph row ROW. See the
11696 comment of x_draw_glyphs for the meaning of HL. */
11697
11698 static void
11699 x_draw_phys_cursor_glyph (w, row, hl)
11700 struct window *w;
11701 struct glyph_row *row;
11702 enum draw_glyphs_face hl;
11703 {
11704 /* If cursor hpos is out of bounds, don't draw garbage. This can
11705 happen in mini-buffer windows when switching between echo area
11706 glyphs and mini-buffer. */
11707 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
11708 {
11709 int on_p = w->phys_cursor_on_p;
11710 int x1;
11711
11712 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11713 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
11714 hl, 0);
11715 w->phys_cursor_on_p = on_p;
11716
11717 if (hl == DRAW_CURSOR)
11718 w->phys_cursor_width = x1 - w->phys_cursor.x;
11719
11720 /* When we erase the cursor, and ROW is overlapped by other
11721 rows, make sure that these overlapping parts of other rows
11722 are redrawn. */
11723 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11724 {
11725 if (row > w->current_matrix->rows
11726 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11727 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11728
11729 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11730 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11731 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11732 }
11733 }
11734 }
11735
11736
11737 /* Erase the image of a cursor of window W from the screen. */
11738
11739 static void
11740 x_erase_phys_cursor (w)
11741 struct window *w;
11742 {
11743 struct frame *f = XFRAME (w->frame);
11744 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11745 int hpos = w->phys_cursor.hpos;
11746 int vpos = w->phys_cursor.vpos;
11747 int mouse_face_here_p = 0;
11748 struct glyph_matrix *active_glyphs = w->current_matrix;
11749 struct glyph_row *cursor_row;
11750 struct glyph *cursor_glyph;
11751 enum draw_glyphs_face hl;
11752
11753 /* No cursor displayed or row invalidated => nothing to do on the
11754 screen. */
11755 if (w->phys_cursor_type == NO_CURSOR)
11756 goto mark_cursor_off;
11757
11758 /* VPOS >= active_glyphs->nrows means that window has been resized.
11759 Don't bother to erase the cursor. */
11760 if (vpos >= active_glyphs->nrows)
11761 goto mark_cursor_off;
11762
11763 /* If row containing cursor is marked invalid, there is nothing we
11764 can do. */
11765 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11766 if (!cursor_row->enabled_p)
11767 goto mark_cursor_off;
11768
11769 /* If row is completely invisible, don't attempt to delete a cursor which
11770 isn't there. This can happen if cursor is at top of a window, and
11771 we switch to a buffer with a header line in that window. */
11772 if (cursor_row->visible_height <= 0)
11773 goto mark_cursor_off;
11774
11775 /* This can happen when the new row is shorter than the old one.
11776 In this case, either x_draw_glyphs or clear_end_of_line
11777 should have cleared the cursor. Note that we wouldn't be
11778 able to erase the cursor in this case because we don't have a
11779 cursor glyph at hand. */
11780 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11781 goto mark_cursor_off;
11782
11783 /* If the cursor is in the mouse face area, redisplay that when
11784 we clear the cursor. */
11785 if (! NILP (dpyinfo->mouse_face_window)
11786 && w == XWINDOW (dpyinfo->mouse_face_window)
11787 && (vpos > dpyinfo->mouse_face_beg_row
11788 || (vpos == dpyinfo->mouse_face_beg_row
11789 && hpos >= dpyinfo->mouse_face_beg_col))
11790 && (vpos < dpyinfo->mouse_face_end_row
11791 || (vpos == dpyinfo->mouse_face_end_row
11792 && hpos < dpyinfo->mouse_face_end_col))
11793 /* Don't redraw the cursor's spot in mouse face if it is at the
11794 end of a line (on a newline). The cursor appears there, but
11795 mouse highlighting does not. */
11796 && cursor_row->used[TEXT_AREA] > hpos)
11797 mouse_face_here_p = 1;
11798
11799 /* Maybe clear the display under the cursor. */
11800 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11801 {
11802 int x;
11803 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
11804
11805 cursor_glyph = get_phys_cursor_glyph (w);
11806 if (cursor_glyph == NULL)
11807 goto mark_cursor_off;
11808
11809 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11810
11811 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11812 x,
11813 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11814 cursor_row->y)),
11815 cursor_glyph->pixel_width,
11816 cursor_row->visible_height,
11817 False);
11818 }
11819
11820 /* Erase the cursor by redrawing the character underneath it. */
11821 if (mouse_face_here_p)
11822 hl = DRAW_MOUSE_FACE;
11823 else
11824 hl = DRAW_NORMAL_TEXT;
11825 x_draw_phys_cursor_glyph (w, cursor_row, hl);
11826
11827 mark_cursor_off:
11828 w->phys_cursor_on_p = 0;
11829 w->phys_cursor_type = NO_CURSOR;
11830 }
11831
11832
11833 /* Non-zero if physical cursor of window W is within mouse face. */
11834
11835 static int
11836 cursor_in_mouse_face_p (w)
11837 struct window *w;
11838 {
11839 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11840 int in_mouse_face = 0;
11841
11842 if (WINDOWP (dpyinfo->mouse_face_window)
11843 && XWINDOW (dpyinfo->mouse_face_window) == w)
11844 {
11845 int hpos = w->phys_cursor.hpos;
11846 int vpos = w->phys_cursor.vpos;
11847
11848 if (vpos >= dpyinfo->mouse_face_beg_row
11849 && vpos <= dpyinfo->mouse_face_end_row
11850 && (vpos > dpyinfo->mouse_face_beg_row
11851 || hpos >= dpyinfo->mouse_face_beg_col)
11852 && (vpos < dpyinfo->mouse_face_end_row
11853 || hpos < dpyinfo->mouse_face_end_col
11854 || dpyinfo->mouse_face_past_end))
11855 in_mouse_face = 1;
11856 }
11857
11858 return in_mouse_face;
11859 }
11860
11861
11862 /* Display or clear cursor of window W. If ON is zero, clear the
11863 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11864 where to put the cursor is specified by HPOS, VPOS, X and Y. */
11865
11866 void
11867 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11868 struct window *w;
11869 int on, hpos, vpos, x, y;
11870 {
11871 struct frame *f = XFRAME (w->frame);
11872 int new_cursor_type;
11873 int new_cursor_width;
11874 int active_cursor;
11875 struct glyph_matrix *current_glyphs;
11876 struct glyph_row *glyph_row;
11877 struct glyph *glyph;
11878
11879 /* This is pointless on invisible frames, and dangerous on garbaged
11880 windows and frames; in the latter case, the frame or window may
11881 be in the midst of changing its size, and x and y may be off the
11882 window. */
11883 if (! FRAME_VISIBLE_P (f)
11884 || FRAME_GARBAGED_P (f)
11885 || vpos >= w->current_matrix->nrows
11886 || hpos >= w->current_matrix->matrix_w)
11887 return;
11888
11889 /* If cursor is off and we want it off, return quickly. */
11890 if (!on && !w->phys_cursor_on_p)
11891 return;
11892
11893 current_glyphs = w->current_matrix;
11894 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11895 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11896
11897 /* If cursor row is not enabled, we don't really know where to
11898 display the cursor. */
11899 if (!glyph_row->enabled_p)
11900 {
11901 w->phys_cursor_on_p = 0;
11902 return;
11903 }
11904
11905 xassert (interrupt_input_blocked);
11906
11907 /* Set new_cursor_type to the cursor we want to be displayed. */
11908 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
11909
11910 /* If cursor is currently being shown and we don't want it to be or
11911 it is in the wrong place, or the cursor type is not what we want,
11912 erase it. */
11913 if (w->phys_cursor_on_p
11914 && (!on
11915 || w->phys_cursor.x != x
11916 || w->phys_cursor.y != y
11917 || new_cursor_type != w->phys_cursor_type
11918 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
11919 && new_cursor_width != w->phys_cursor_width)))
11920 x_erase_phys_cursor (w);
11921
11922 /* Don't check phys_cursor_on_p here because that flag is only set
11923 to zero in some cases where we know that the cursor has been
11924 completely erased, to avoid the extra work of erasing the cursor
11925 twice. In other words, phys_cursor_on_p can be 1 and the cursor
11926 still not be visible, or it has only been partly erased. */
11927 if (on)
11928 {
11929 w->phys_cursor_ascent = glyph_row->ascent;
11930 w->phys_cursor_height = glyph_row->height;
11931
11932 /* Set phys_cursor_.* before x_draw_.* is called because some
11933 of them may need the information. */
11934 w->phys_cursor.x = x;
11935 w->phys_cursor.y = glyph_row->y;
11936 w->phys_cursor.hpos = hpos;
11937 w->phys_cursor.vpos = vpos;
11938 w->phys_cursor_type = new_cursor_type;
11939 w->phys_cursor_on_p = 1;
11940
11941 switch (new_cursor_type)
11942 {
11943 case HOLLOW_BOX_CURSOR:
11944 x_draw_hollow_cursor (w, glyph_row);
11945 break;
11946
11947 case FILLED_BOX_CURSOR:
11948 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11949 break;
11950
11951 case BAR_CURSOR:
11952 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
11953 break;
11954
11955 case HBAR_CURSOR:
11956 x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
11957 break;
11958
11959 case NO_CURSOR:
11960 w->phys_cursor_width = 0;
11961 break;
11962
11963 default:
11964 abort ();
11965 }
11966
11967 #ifdef HAVE_X_I18N
11968 if (w == XWINDOW (f->selected_window))
11969 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11970 xic_set_preeditarea (w, x, y);
11971 #endif
11972 }
11973
11974 #ifndef XFlush
11975 if (updating_frame != f)
11976 XFlush (FRAME_X_DISPLAY (f));
11977 #endif
11978 }
11979
11980
11981 /* Display the cursor on window W, or clear it. X and Y are window
11982 relative pixel coordinates. HPOS and VPOS are glyph matrix
11983 positions. If W is not the selected window, display a hollow
11984 cursor. ON non-zero means display the cursor at X, Y which
11985 correspond to HPOS, VPOS, otherwise it is cleared. */
11986
11987 void
11988 x_display_cursor (w, on, hpos, vpos, x, y)
11989 struct window *w;
11990 int on, hpos, vpos, x, y;
11991 {
11992 BLOCK_INPUT;
11993 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
11994 UNBLOCK_INPUT;
11995 }
11996
11997
11998 /* Display the cursor on window W, or clear it, according to ON_P.
11999 Don't change the cursor's position. */
12000
12001 void
12002 x_update_cursor (f, on_p)
12003 struct frame *f;
12004 int on_p;
12005 {
12006 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
12007 }
12008
12009
12010 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
12011 in the window tree rooted at W. */
12012
12013 static void
12014 x_update_cursor_in_window_tree (w, on_p)
12015 struct window *w;
12016 int on_p;
12017 {
12018 while (w)
12019 {
12020 if (!NILP (w->hchild))
12021 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
12022 else if (!NILP (w->vchild))
12023 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
12024 else
12025 x_update_window_cursor (w, on_p);
12026
12027 w = NILP (w->next) ? 0 : XWINDOW (w->next);
12028 }
12029 }
12030
12031
12032 /* Switch the display of W's cursor on or off, according to the value
12033 of ON. */
12034
12035 static void
12036 x_update_window_cursor (w, on)
12037 struct window *w;
12038 int on;
12039 {
12040 /* Don't update cursor in windows whose frame is in the process
12041 of being deleted. */
12042 if (w->current_matrix)
12043 {
12044 BLOCK_INPUT;
12045 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
12046 w->phys_cursor.x, w->phys_cursor.y);
12047 UNBLOCK_INPUT;
12048 }
12049 }
12050
12051
12052
12053 \f
12054 /* Icons. */
12055
12056 /* Make the x-window of frame F use the gnu icon bitmap. */
12057
12058 int
12059 x_bitmap_icon (f, file)
12060 struct frame *f;
12061 Lisp_Object file;
12062 {
12063 int bitmap_id;
12064
12065 if (FRAME_X_WINDOW (f) == 0)
12066 return 1;
12067
12068 /* Free up our existing icon bitmap if any. */
12069 if (f->output_data.x->icon_bitmap > 0)
12070 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12071 f->output_data.x->icon_bitmap = 0;
12072
12073 if (STRINGP (file))
12074 bitmap_id = x_create_bitmap_from_file (f, file);
12075 else
12076 {
12077 /* Create the GNU bitmap if necessary. */
12078 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
12079 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
12080 = x_create_bitmap_from_data (f, gnu_bits,
12081 gnu_width, gnu_height);
12082
12083 /* The first time we create the GNU bitmap,
12084 this increments the ref-count one extra time.
12085 As a result, the GNU bitmap is never freed.
12086 That way, we don't have to worry about allocating it again. */
12087 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
12088
12089 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
12090 }
12091
12092 x_wm_set_icon_pixmap (f, bitmap_id);
12093 f->output_data.x->icon_bitmap = bitmap_id;
12094
12095 return 0;
12096 }
12097
12098
12099 /* Make the x-window of frame F use a rectangle with text.
12100 Use ICON_NAME as the text. */
12101
12102 int
12103 x_text_icon (f, icon_name)
12104 struct frame *f;
12105 char *icon_name;
12106 {
12107 if (FRAME_X_WINDOW (f) == 0)
12108 return 1;
12109
12110 #ifdef HAVE_X11R4
12111 {
12112 XTextProperty text;
12113 text.value = (unsigned char *) icon_name;
12114 text.encoding = XA_STRING;
12115 text.format = 8;
12116 text.nitems = strlen (icon_name);
12117 #ifdef USE_X_TOOLKIT
12118 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
12119 &text);
12120 #else /* not USE_X_TOOLKIT */
12121 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
12122 #endif /* not USE_X_TOOLKIT */
12123 }
12124 #else /* not HAVE_X11R4 */
12125 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
12126 #endif /* not HAVE_X11R4 */
12127
12128 if (f->output_data.x->icon_bitmap > 0)
12129 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
12130 f->output_data.x->icon_bitmap = 0;
12131 x_wm_set_icon_pixmap (f, 0);
12132
12133 return 0;
12134 }
12135 \f
12136 #define X_ERROR_MESSAGE_SIZE 200
12137
12138 /* If non-nil, this should be a string.
12139 It means catch X errors and store the error message in this string. */
12140
12141 static Lisp_Object x_error_message_string;
12142
12143 /* An X error handler which stores the error message in
12144 x_error_message_string. This is called from x_error_handler if
12145 x_catch_errors is in effect. */
12146
12147 static void
12148 x_error_catcher (display, error)
12149 Display *display;
12150 XErrorEvent *error;
12151 {
12152 XGetErrorText (display, error->error_code,
12153 SDATA (x_error_message_string),
12154 X_ERROR_MESSAGE_SIZE);
12155 }
12156
12157 /* Begin trapping X errors for display DPY. Actually we trap X errors
12158 for all displays, but DPY should be the display you are actually
12159 operating on.
12160
12161 After calling this function, X protocol errors no longer cause
12162 Emacs to exit; instead, they are recorded in the string
12163 stored in x_error_message_string.
12164
12165 Calling x_check_errors signals an Emacs error if an X error has
12166 occurred since the last call to x_catch_errors or x_check_errors.
12167
12168 Calling x_uncatch_errors resumes the normal error handling. */
12169
12170 void x_check_errors ();
12171 static Lisp_Object x_catch_errors_unwind ();
12172
12173 int
12174 x_catch_errors (dpy)
12175 Display *dpy;
12176 {
12177 int count = SPECPDL_INDEX ();
12178
12179 /* Make sure any errors from previous requests have been dealt with. */
12180 XSync (dpy, False);
12181
12182 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
12183
12184 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
12185 SSET (x_error_message_string, 0, 0);
12186
12187 return count;
12188 }
12189
12190 /* Unbind the binding that we made to check for X errors. */
12191
12192 static Lisp_Object
12193 x_catch_errors_unwind (old_val)
12194 Lisp_Object old_val;
12195 {
12196 x_error_message_string = old_val;
12197 return Qnil;
12198 }
12199
12200 /* If any X protocol errors have arrived since the last call to
12201 x_catch_errors or x_check_errors, signal an Emacs error using
12202 sprintf (a buffer, FORMAT, the x error message text) as the text. */
12203
12204 void
12205 x_check_errors (dpy, format)
12206 Display *dpy;
12207 char *format;
12208 {
12209 /* Make sure to catch any errors incurred so far. */
12210 XSync (dpy, False);
12211
12212 if (SREF (x_error_message_string, 0))
12213 error (format, SDATA (x_error_message_string));
12214 }
12215
12216 /* Nonzero if we had any X protocol errors
12217 since we did x_catch_errors on DPY. */
12218
12219 int
12220 x_had_errors_p (dpy)
12221 Display *dpy;
12222 {
12223 /* Make sure to catch any errors incurred so far. */
12224 XSync (dpy, False);
12225
12226 return SREF (x_error_message_string, 0) != 0;
12227 }
12228
12229 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
12230
12231 void
12232 x_clear_errors (dpy)
12233 Display *dpy;
12234 {
12235 SSET (x_error_message_string, 0, 0);
12236 }
12237
12238 /* Stop catching X protocol errors and let them make Emacs die.
12239 DPY should be the display that was passed to x_catch_errors.
12240 COUNT should be the value that was returned by
12241 the corresponding call to x_catch_errors. */
12242
12243 void
12244 x_uncatch_errors (dpy, count)
12245 Display *dpy;
12246 int count;
12247 {
12248 unbind_to (count, Qnil);
12249 }
12250
12251 #if 0
12252 static unsigned int x_wire_count;
12253 x_trace_wire ()
12254 {
12255 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
12256 }
12257 #endif /* ! 0 */
12258
12259 \f
12260 /* Handle SIGPIPE, which can happen when the connection to a server
12261 simply goes away. SIGPIPE is handled by x_connection_signal.
12262 Don't need to do anything, because the write which caused the
12263 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
12264 which will do the appropriate cleanup for us. */
12265
12266 static SIGTYPE
12267 x_connection_signal (signalnum) /* If we don't have an argument, */
12268 int signalnum; /* some compilers complain in signal calls. */
12269 {
12270 #ifdef USG
12271 /* USG systems forget handlers when they are used;
12272 must reestablish each time */
12273 signal (signalnum, x_connection_signal);
12274 #endif /* USG */
12275 }
12276
12277 \f
12278 /************************************************************************
12279 Handling X errors
12280 ************************************************************************/
12281
12282 /* Error message passed to x_connection_closed. */
12283
12284 static char *error_msg;
12285
12286 /* Function installed as fatal_error_signal_hook in
12287 x_connection_closed. Print the X error message, and exit normally,
12288 instead of dumping core when XtCloseDisplay fails. */
12289
12290 static void
12291 x_fatal_error_signal ()
12292 {
12293 fprintf (stderr, "%s\n", error_msg);
12294 exit (70);
12295 }
12296
12297 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
12298 the text of an error message that lead to the connection loss. */
12299
12300 static SIGTYPE
12301 x_connection_closed (dpy, error_message)
12302 Display *dpy;
12303 char *error_message;
12304 {
12305 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
12306 Lisp_Object frame, tail;
12307 int count;
12308
12309 error_msg = (char *) alloca (strlen (error_message) + 1);
12310 strcpy (error_msg, error_message);
12311 handling_signal = 0;
12312
12313 /* Prevent being called recursively because of an error condition
12314 below. Otherwise, we might end up with printing ``can't find per
12315 display information'' in the recursive call instead of printing
12316 the original message here. */
12317 count = x_catch_errors (dpy);
12318
12319 /* We have to close the display to inform Xt that it doesn't
12320 exist anymore. If we don't, Xt will continue to wait for
12321 events from the display. As a consequence, a sequence of
12322
12323 M-x make-frame-on-display RET :1 RET
12324 ...kill the new frame, so that we get an IO error...
12325 M-x make-frame-on-display RET :1 RET
12326
12327 will indefinitely wait in Xt for events for display `:1', opened
12328 in the first class to make-frame-on-display.
12329
12330 Closing the display is reported to lead to a bus error on
12331 OpenWindows in certain situations. I suspect that is a bug
12332 in OpenWindows. I don't know how to cicumvent it here. */
12333
12334 #ifdef USE_X_TOOLKIT
12335 /* If DPYINFO is null, this means we didn't open the display
12336 in the first place, so don't try to close it. */
12337 if (dpyinfo)
12338 {
12339 extern void (*fatal_error_signal_hook) P_ ((void));
12340 fatal_error_signal_hook = x_fatal_error_signal;
12341 XtCloseDisplay (dpy);
12342 fatal_error_signal_hook = NULL;
12343 }
12344 #endif
12345
12346 /* Indicate that this display is dead. */
12347 if (dpyinfo)
12348 dpyinfo->display = 0;
12349
12350 /* First delete frames whose mini-buffers are on frames
12351 that are on the dead display. */
12352 FOR_EACH_FRAME (tail, frame)
12353 {
12354 Lisp_Object minibuf_frame;
12355 minibuf_frame
12356 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
12357 if (FRAME_X_P (XFRAME (frame))
12358 && FRAME_X_P (XFRAME (minibuf_frame))
12359 && ! EQ (frame, minibuf_frame)
12360 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
12361 Fdelete_frame (frame, Qt);
12362 }
12363
12364 /* Now delete all remaining frames on the dead display.
12365 We are now sure none of these is used as the mini-buffer
12366 for another frame that we need to delete. */
12367 FOR_EACH_FRAME (tail, frame)
12368 if (FRAME_X_P (XFRAME (frame))
12369 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
12370 {
12371 /* Set this to t so that Fdelete_frame won't get confused
12372 trying to find a replacement. */
12373 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
12374 Fdelete_frame (frame, Qt);
12375 }
12376
12377 if (dpyinfo)
12378 x_delete_display (dpyinfo);
12379
12380 x_uncatch_errors (dpy, count);
12381
12382 if (x_display_list == 0)
12383 {
12384 fprintf (stderr, "%s\n", error_msg);
12385 shut_down_emacs (0, 0, Qnil);
12386 exit (70);
12387 }
12388
12389 /* Ordinary stack unwind doesn't deal with these. */
12390 #ifdef SIGIO
12391 sigunblock (sigmask (SIGIO));
12392 #endif
12393 sigunblock (sigmask (SIGALRM));
12394 TOTALLY_UNBLOCK_INPUT;
12395
12396 clear_waiting_for_input ();
12397 error ("%s", error_msg);
12398 }
12399
12400
12401 /* This is the usual handler for X protocol errors.
12402 It kills all frames on the display that we got the error for.
12403 If that was the only one, it prints an error message and kills Emacs. */
12404
12405 static void
12406 x_error_quitter (display, error)
12407 Display *display;
12408 XErrorEvent *error;
12409 {
12410 char buf[256], buf1[356];
12411
12412 /* Note that there is no real way portable across R3/R4 to get the
12413 original error handler. */
12414
12415 XGetErrorText (display, error->error_code, buf, sizeof (buf));
12416 sprintf (buf1, "X protocol error: %s on protocol request %d",
12417 buf, error->request_code);
12418 x_connection_closed (display, buf1);
12419 }
12420
12421
12422 /* This is the first-level handler for X protocol errors.
12423 It calls x_error_quitter or x_error_catcher. */
12424
12425 static int
12426 x_error_handler (display, error)
12427 Display *display;
12428 XErrorEvent *error;
12429 {
12430 if (! NILP (x_error_message_string))
12431 x_error_catcher (display, error);
12432 else
12433 x_error_quitter (display, error);
12434 return 0;
12435 }
12436
12437 /* This is the handler for X IO errors, always.
12438 It kills all frames on the display that we lost touch with.
12439 If that was the only one, it prints an error message and kills Emacs. */
12440
12441 static int
12442 x_io_error_quitter (display)
12443 Display *display;
12444 {
12445 char buf[256];
12446
12447 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12448 x_connection_closed (display, buf);
12449 return 0;
12450 }
12451 \f
12452 /* Changing the font of the frame. */
12453
12454 /* Give frame F the font named FONTNAME as its default font, and
12455 return the full name of that font. FONTNAME may be a wildcard
12456 pattern; in that case, we choose some font that fits the pattern.
12457 The return value shows which font we chose. */
12458
12459 Lisp_Object
12460 x_new_font (f, fontname)
12461 struct frame *f;
12462 register char *fontname;
12463 {
12464 struct font_info *fontp
12465 = FS_LOAD_FONT (f, 0, fontname, -1);
12466
12467 if (!fontp)
12468 return Qnil;
12469
12470 f->output_data.x->font = (XFontStruct *) (fontp->font);
12471 f->output_data.x->baseline_offset = fontp->baseline_offset;
12472 f->output_data.x->fontset = -1;
12473
12474 x_compute_fringe_widths (f, 1);
12475
12476 /* Compute the scroll bar width in character columns. */
12477 if (f->scroll_bar_pixel_width > 0)
12478 {
12479 int wid = FONT_WIDTH (f->output_data.x->font);
12480 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12481 }
12482 else
12483 {
12484 int wid = FONT_WIDTH (f->output_data.x->font);
12485 f->scroll_bar_cols = (14 + wid - 1) / wid;
12486 }
12487
12488 /* Now make the frame display the given font. */
12489 if (FRAME_X_WINDOW (f) != 0)
12490 {
12491 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12492 f->output_data.x->font->fid);
12493 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12494 f->output_data.x->font->fid);
12495 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12496 f->output_data.x->font->fid);
12497
12498 frame_update_line_height (f);
12499
12500 /* Don't change the size of a tip frame; there's no point in
12501 doing it because it's done in Fx_show_tip, and it leads to
12502 problems because the tip frame has no widget. */
12503 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12504 x_set_window_size (f, 0, f->width, f->height);
12505 }
12506 else
12507 /* If we are setting a new frame's font for the first time,
12508 there are no faces yet, so this font's height is the line height. */
12509 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
12510
12511 return build_string (fontp->full_name);
12512 }
12513
12514 /* Give frame F the fontset named FONTSETNAME as its default font, and
12515 return the full name of that fontset. FONTSETNAME may be a wildcard
12516 pattern; in that case, we choose some fontset that fits the pattern.
12517 The return value shows which fontset we chose. */
12518
12519 Lisp_Object
12520 x_new_fontset (f, fontsetname)
12521 struct frame *f;
12522 char *fontsetname;
12523 {
12524 int fontset = fs_query_fontset (build_string (fontsetname), 0);
12525 Lisp_Object result;
12526
12527 if (fontset < 0)
12528 return Qnil;
12529
12530 if (f->output_data.x->fontset == fontset)
12531 /* This fontset is already set in frame F. There's nothing more
12532 to do. */
12533 return fontset_name (fontset);
12534
12535 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
12536
12537 if (!STRINGP (result))
12538 /* Can't load ASCII font. */
12539 return Qnil;
12540
12541 /* Since x_new_font doesn't update any fontset information, do it now. */
12542 f->output_data.x->fontset = fontset;
12543
12544 #ifdef HAVE_X_I18N
12545 if (FRAME_XIC (f)
12546 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
12547 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
12548 #endif
12549
12550 return build_string (fontsetname);
12551 }
12552
12553 /* Compute actual fringe widths */
12554
12555 void
12556 x_compute_fringe_widths (f, redraw)
12557 struct frame *f;
12558 int redraw;
12559 {
12560 int o_left = f->output_data.x->left_fringe_width;
12561 int o_right = f->output_data.x->right_fringe_width;
12562 int o_cols = f->output_data.x->fringe_cols;
12563
12564 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
12565 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
12566 int left_fringe_width, right_fringe_width;
12567
12568 if (!NILP (left_fringe))
12569 left_fringe = Fcdr (left_fringe);
12570 if (!NILP (right_fringe))
12571 right_fringe = Fcdr (right_fringe);
12572
12573 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
12574 XINT (left_fringe));
12575 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
12576 XINT (right_fringe));
12577
12578 if (left_fringe_width || right_fringe_width)
12579 {
12580 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
12581 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
12582 int conf_wid = left_wid + right_wid;
12583 int font_wid = FONT_WIDTH (f->output_data.x->font);
12584 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
12585 int real_wid = cols * font_wid;
12586 if (left_wid && right_wid)
12587 {
12588 if (left_fringe_width < 0)
12589 {
12590 /* Left fringe width is fixed, adjust right fringe if necessary */
12591 f->output_data.x->left_fringe_width = left_wid;
12592 f->output_data.x->right_fringe_width = real_wid - left_wid;
12593 }
12594 else if (right_fringe_width < 0)
12595 {
12596 /* Right fringe width is fixed, adjust left fringe if necessary */
12597 f->output_data.x->left_fringe_width = real_wid - right_wid;
12598 f->output_data.x->right_fringe_width = right_wid;
12599 }
12600 else
12601 {
12602 /* Adjust both fringes with an equal amount.
12603 Note that we are doing integer arithmetic here, so don't
12604 lose a pixel if the total width is an odd number. */
12605 int fill = real_wid - conf_wid;
12606 f->output_data.x->left_fringe_width = left_wid + fill/2;
12607 f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
12608 }
12609 }
12610 else if (left_fringe_width)
12611 {
12612 f->output_data.x->left_fringe_width = real_wid;
12613 f->output_data.x->right_fringe_width = 0;
12614 }
12615 else
12616 {
12617 f->output_data.x->left_fringe_width = 0;
12618 f->output_data.x->right_fringe_width = real_wid;
12619 }
12620 f->output_data.x->fringe_cols = cols;
12621 f->output_data.x->fringes_extra = real_wid;
12622 }
12623 else
12624 {
12625 f->output_data.x->left_fringe_width = 0;
12626 f->output_data.x->right_fringe_width = 0;
12627 f->output_data.x->fringe_cols = 0;
12628 f->output_data.x->fringes_extra = 0;
12629 }
12630
12631 if (redraw && FRAME_VISIBLE_P (f))
12632 if (o_left != f->output_data.x->left_fringe_width ||
12633 o_right != f->output_data.x->right_fringe_width ||
12634 o_cols != f->output_data.x->fringe_cols)
12635 redraw_frame (f);
12636 }
12637 \f
12638 /***********************************************************************
12639 X Input Methods
12640 ***********************************************************************/
12641
12642 #ifdef HAVE_X_I18N
12643
12644 #ifdef HAVE_X11R6
12645
12646 /* XIM destroy callback function, which is called whenever the
12647 connection to input method XIM dies. CLIENT_DATA contains a
12648 pointer to the x_display_info structure corresponding to XIM. */
12649
12650 static void
12651 xim_destroy_callback (xim, client_data, call_data)
12652 XIM xim;
12653 XPointer client_data;
12654 XPointer call_data;
12655 {
12656 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12657 Lisp_Object frame, tail;
12658
12659 BLOCK_INPUT;
12660
12661 /* No need to call XDestroyIC.. */
12662 FOR_EACH_FRAME (tail, frame)
12663 {
12664 struct frame *f = XFRAME (frame);
12665 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12666 {
12667 FRAME_XIC (f) = NULL;
12668 if (FRAME_XIC_FONTSET (f))
12669 {
12670 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12671 FRAME_XIC_FONTSET (f) = NULL;
12672 }
12673 }
12674 }
12675
12676 /* No need to call XCloseIM. */
12677 dpyinfo->xim = NULL;
12678 XFree (dpyinfo->xim_styles);
12679 UNBLOCK_INPUT;
12680 }
12681
12682 #endif /* HAVE_X11R6 */
12683
12684 #ifdef HAVE_X11R6
12685 /* This isn't prototyped in OSF 5.0 or 5.1a. */
12686 extern char *XSetIMValues P_ ((XIM, ...));
12687 #endif
12688
12689 /* Open the connection to the XIM server on display DPYINFO.
12690 RESOURCE_NAME is the resource name Emacs uses. */
12691
12692 static void
12693 xim_open_dpy (dpyinfo, resource_name)
12694 struct x_display_info *dpyinfo;
12695 char *resource_name;
12696 {
12697 #ifdef USE_XIM
12698 XIM xim;
12699
12700 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12701 dpyinfo->xim = xim;
12702
12703 if (xim)
12704 {
12705 #ifdef HAVE_X11R6
12706 XIMCallback destroy;
12707 #endif
12708
12709 /* Get supported styles and XIM values. */
12710 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12711
12712 #ifdef HAVE_X11R6
12713 destroy.callback = xim_destroy_callback;
12714 destroy.client_data = (XPointer)dpyinfo;
12715 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12716 #endif
12717 }
12718
12719 #else /* not USE_XIM */
12720 dpyinfo->xim = NULL;
12721 #endif /* not USE_XIM */
12722 }
12723
12724
12725 #ifdef HAVE_X11R6_XIM
12726
12727 struct xim_inst_t
12728 {
12729 struct x_display_info *dpyinfo;
12730 char *resource_name;
12731 };
12732
12733 /* XIM instantiate callback function, which is called whenever an XIM
12734 server is available. DISPLAY is teh display of the XIM.
12735 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12736 when the callback was registered. */
12737
12738 static void
12739 xim_instantiate_callback (display, client_data, call_data)
12740 Display *display;
12741 XPointer client_data;
12742 XPointer call_data;
12743 {
12744 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12745 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12746
12747 /* We don't support multiple XIM connections. */
12748 if (dpyinfo->xim)
12749 return;
12750
12751 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12752
12753 /* Create XIC for the existing frames on the same display, as long
12754 as they have no XIC. */
12755 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12756 {
12757 Lisp_Object tail, frame;
12758
12759 BLOCK_INPUT;
12760 FOR_EACH_FRAME (tail, frame)
12761 {
12762 struct frame *f = XFRAME (frame);
12763
12764 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12765 if (FRAME_XIC (f) == NULL)
12766 {
12767 create_frame_xic (f);
12768 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12769 xic_set_statusarea (f);
12770 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12771 {
12772 struct window *w = XWINDOW (f->selected_window);
12773 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12774 }
12775 }
12776 }
12777
12778 UNBLOCK_INPUT;
12779 }
12780 }
12781
12782 #endif /* HAVE_X11R6_XIM */
12783
12784
12785 /* Open a connection to the XIM server on display DPYINFO.
12786 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12787 connection only at the first time. On X11R6, open the connection
12788 in the XIM instantiate callback function. */
12789
12790 static void
12791 xim_initialize (dpyinfo, resource_name)
12792 struct x_display_info *dpyinfo;
12793 char *resource_name;
12794 {
12795 #ifdef USE_XIM
12796 #ifdef HAVE_X11R6_XIM
12797 struct xim_inst_t *xim_inst;
12798 int len;
12799
12800 dpyinfo->xim = NULL;
12801 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12802 xim_inst->dpyinfo = dpyinfo;
12803 len = strlen (resource_name);
12804 xim_inst->resource_name = (char *) xmalloc (len + 1);
12805 bcopy (resource_name, xim_inst->resource_name, len + 1);
12806 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12807 resource_name, EMACS_CLASS,
12808 xim_instantiate_callback,
12809 /* Fixme: This is XPointer in
12810 XFree86 but (XPointer *) on
12811 Tru64, at least. */
12812 (XPointer) xim_inst);
12813 #else /* not HAVE_X11R6_XIM */
12814 dpyinfo->xim = NULL;
12815 xim_open_dpy (dpyinfo, resource_name);
12816 #endif /* not HAVE_X11R6_XIM */
12817
12818 #else /* not USE_XIM */
12819 dpyinfo->xim = NULL;
12820 #endif /* not USE_XIM */
12821 }
12822
12823
12824 /* Close the connection to the XIM server on display DPYINFO. */
12825
12826 static void
12827 xim_close_dpy (dpyinfo)
12828 struct x_display_info *dpyinfo;
12829 {
12830 #ifdef USE_XIM
12831 #ifdef HAVE_X11R6_XIM
12832 if (dpyinfo->display)
12833 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12834 NULL, EMACS_CLASS,
12835 xim_instantiate_callback, NULL);
12836 #endif /* not HAVE_X11R6_XIM */
12837 if (dpyinfo->display)
12838 XCloseIM (dpyinfo->xim);
12839 dpyinfo->xim = NULL;
12840 XFree (dpyinfo->xim_styles);
12841 #endif /* USE_XIM */
12842 }
12843
12844 #endif /* not HAVE_X11R6_XIM */
12845
12846
12847 \f
12848 /* Calculate the absolute position in frame F
12849 from its current recorded position values and gravity. */
12850
12851 void
12852 x_calc_absolute_position (f)
12853 struct frame *f;
12854 {
12855 Window child;
12856 int win_x = 0, win_y = 0;
12857 int flags = f->output_data.x->size_hint_flags;
12858 int this_window;
12859
12860 /* We have nothing to do if the current position
12861 is already for the top-left corner. */
12862 if (! ((flags & XNegative) || (flags & YNegative)))
12863 return;
12864
12865 #ifdef USE_X_TOOLKIT
12866 this_window = XtWindow (f->output_data.x->widget);
12867 #else
12868 this_window = FRAME_X_WINDOW (f);
12869 #endif
12870
12871 /* Find the position of the outside upper-left corner of
12872 the inner window, with respect to the outer window.
12873 But do this only if we will need the results. */
12874 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
12875 {
12876 int count;
12877
12878 BLOCK_INPUT;
12879 count = x_catch_errors (FRAME_X_DISPLAY (f));
12880 while (1)
12881 {
12882 x_clear_errors (FRAME_X_DISPLAY (f));
12883 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12884
12885 /* From-window, to-window. */
12886 this_window,
12887 f->output_data.x->parent_desc,
12888
12889 /* From-position, to-position. */
12890 0, 0, &win_x, &win_y,
12891
12892 /* Child of win. */
12893 &child);
12894 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12895 {
12896 Window newroot, newparent = 0xdeadbeef;
12897 Window *newchildren;
12898 unsigned int nchildren;
12899
12900 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12901 &newparent, &newchildren, &nchildren))
12902 break;
12903
12904 XFree ((char *) newchildren);
12905
12906 f->output_data.x->parent_desc = newparent;
12907 }
12908 else
12909 break;
12910 }
12911
12912 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12913 UNBLOCK_INPUT;
12914 }
12915
12916 /* Treat negative positions as relative to the leftmost bottommost
12917 position that fits on the screen. */
12918 if (flags & XNegative)
12919 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
12920 - 2 * f->output_data.x->border_width - win_x
12921 - PIXEL_WIDTH (f)
12922 + f->output_data.x->left_pos);
12923
12924 {
12925 int height = PIXEL_HEIGHT (f);
12926
12927 #if defined USE_X_TOOLKIT && defined USE_MOTIF
12928 /* Something is fishy here. When using Motif, starting Emacs with
12929 `-g -0-0', the frame appears too low by a few pixels.
12930
12931 This seems to be so because initially, while Emacs is starting,
12932 the column widget's height and the frame's pixel height are
12933 different. The column widget's height is the right one. In
12934 later invocations, when Emacs is up, the frame's pixel height
12935 is right, though.
12936
12937 It's not obvious where the initial small difference comes from.
12938 2000-12-01, gerd. */
12939
12940 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
12941 #endif
12942
12943 if (flags & YNegative)
12944 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12945 - 2 * f->output_data.x->border_width
12946 - win_y
12947 - height
12948 + f->output_data.x->top_pos);
12949 }
12950
12951 /* The left_pos and top_pos
12952 are now relative to the top and left screen edges,
12953 so the flags should correspond. */
12954 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12955 }
12956
12957 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12958 to really change the position, and 0 when calling from
12959 x_make_frame_visible (in that case, XOFF and YOFF are the current
12960 position values). It is -1 when calling from x_set_frame_parameters,
12961 which means, do adjust for borders but don't change the gravity. */
12962
12963 void
12964 x_set_offset (f, xoff, yoff, change_gravity)
12965 struct frame *f;
12966 register int xoff, yoff;
12967 int change_gravity;
12968 {
12969 int modified_top, modified_left;
12970
12971 if (change_gravity > 0)
12972 {
12973 f->output_data.x->top_pos = yoff;
12974 f->output_data.x->left_pos = xoff;
12975 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
12976 if (xoff < 0)
12977 f->output_data.x->size_hint_flags |= XNegative;
12978 if (yoff < 0)
12979 f->output_data.x->size_hint_flags |= YNegative;
12980 f->output_data.x->win_gravity = NorthWestGravity;
12981 }
12982 x_calc_absolute_position (f);
12983
12984 BLOCK_INPUT;
12985 x_wm_set_size_hint (f, (long) 0, 0);
12986
12987 modified_left = f->output_data.x->left_pos;
12988 modified_top = f->output_data.x->top_pos;
12989 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12990 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12991 /* It is a mystery why we need to add the border_width here
12992 when the frame is already visible, but experiment says we do. */
12993 if (change_gravity != 0)
12994 {
12995 modified_left += f->output_data.x->border_width;
12996 modified_top += f->output_data.x->border_width;
12997 }
12998 #endif
12999
13000 #ifdef USE_X_TOOLKIT
13001 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
13002 modified_left, modified_top);
13003 #else /* not USE_X_TOOLKIT */
13004 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13005 modified_left, modified_top);
13006 #endif /* not USE_X_TOOLKIT */
13007 UNBLOCK_INPUT;
13008 }
13009
13010 /* Check if we need to resize the frame due to a fullscreen request.
13011 If so needed, resize the frame. */
13012 static void
13013 x_check_fullscreen (f)
13014 struct frame *f;
13015 {
13016 if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
13017 {
13018 int width, height, ign;
13019
13020 x_real_positions (f, &f->output_data.x->left_pos,
13021 &f->output_data.x->top_pos);
13022
13023 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
13024
13025 /* We do not need to move the window, it shall be taken care of
13026 when setting WM manager hints.
13027 If the frame is visible already, the position is checked by
13028 x_check_fullscreen_move. */
13029 if (f->width != width || f->height != height)
13030 {
13031 change_frame_size (f, height, width, 0, 1, 0);
13032 SET_FRAME_GARBAGED (f);
13033 cancel_mouse_face (f);
13034
13035 /* Wait for the change of frame size to occur */
13036 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
13037
13038 }
13039 }
13040 }
13041
13042 /* If frame parameters are set after the frame is mapped, we need to move
13043 the window. This is done in xfns.c.
13044 Some window managers moves the window to the right position, some
13045 moves the outer window manager window to the specified position.
13046 Here we check that we are in the right spot. If not, make a second
13047 move, assuming we are dealing with the second kind of window manager. */
13048 static void
13049 x_check_fullscreen_move (f)
13050 struct frame *f;
13051 {
13052 if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
13053 {
13054 int expect_top = f->output_data.x->top_pos;
13055 int expect_left = f->output_data.x->left_pos;
13056
13057 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13058 expect_top = 0;
13059 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13060 expect_left = 0;
13061
13062 if (expect_top != f->output_data.x->top_pos
13063 || expect_left != f->output_data.x->left_pos)
13064 x_set_offset (f, expect_left, expect_top, 1);
13065
13066 /* Just do this once */
13067 f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
13068 }
13069 }
13070
13071
13072 /* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
13073 wanted positions of the WM window (not emacs window).
13074 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
13075 window (FRAME_X_WINDOW).
13076 */
13077 void
13078 x_fullscreen_adjust (f, width, height, top_pos, left_pos)
13079 struct frame *f;
13080 int *width;
13081 int *height;
13082 int *top_pos;
13083 int *left_pos;
13084 {
13085 int newwidth = f->width, newheight = f->height;
13086
13087 *top_pos = f->output_data.x->top_pos;
13088 *left_pos = f->output_data.x->left_pos;
13089
13090 if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
13091 {
13092 int ph;
13093
13094 ph = FRAME_X_DISPLAY_INFO (f)->height;
13095 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13096 ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
13097 - f->output_data.x->y_pixels_diff;
13098 newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
13099 *top_pos = 0;
13100 }
13101
13102 if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
13103 {
13104 int pw;
13105
13106 pw = FRAME_X_DISPLAY_INFO (f)->width;
13107 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13108 pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
13109 - f->output_data.x->x_pixels_diff;
13110 newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
13111 *left_pos = 0;
13112 }
13113
13114 *width = newwidth;
13115 *height = newheight;
13116 }
13117
13118
13119 /* Change the size of frame F's X window to COLS/ROWS in the case F
13120 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
13121 top-left-corner window gravity for this size change and subsequent
13122 size changes. Otherwise we leave the window gravity unchanged. */
13123
13124 static void
13125 x_set_window_size_1 (f, change_gravity, cols, rows)
13126 struct frame *f;
13127 int change_gravity;
13128 int cols, rows;
13129 {
13130 int pixelwidth, pixelheight;
13131
13132 check_frame_size (f, &rows, &cols);
13133 f->output_data.x->vertical_scroll_bar_extra
13134 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
13135 ? 0
13136 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
13137 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
13138 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
13139
13140 x_compute_fringe_widths (f, 0);
13141
13142 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
13143 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
13144
13145 f->output_data.x->win_gravity = NorthWestGravity;
13146 x_wm_set_size_hint (f, (long) 0, 0);
13147
13148 XSync (FRAME_X_DISPLAY (f), False);
13149 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13150 pixelwidth, pixelheight);
13151
13152 /* Now, strictly speaking, we can't be sure that this is accurate,
13153 but the window manager will get around to dealing with the size
13154 change request eventually, and we'll hear how it went when the
13155 ConfigureNotify event gets here.
13156
13157 We could just not bother storing any of this information here,
13158 and let the ConfigureNotify event set everything up, but that
13159 might be kind of confusing to the Lisp code, since size changes
13160 wouldn't be reported in the frame parameters until some random
13161 point in the future when the ConfigureNotify event arrives.
13162
13163 We pass 1 for DELAY since we can't run Lisp code inside of
13164 a BLOCK_INPUT. */
13165 change_frame_size (f, rows, cols, 0, 1, 0);
13166 PIXEL_WIDTH (f) = pixelwidth;
13167 PIXEL_HEIGHT (f) = pixelheight;
13168
13169 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
13170 receive in the ConfigureNotify event; if we get what we asked
13171 for, then the event won't cause the screen to become garbaged, so
13172 we have to make sure to do it here. */
13173 SET_FRAME_GARBAGED (f);
13174
13175 XFlush (FRAME_X_DISPLAY (f));
13176 }
13177
13178
13179 /* Call this to change the size of frame F's x-window.
13180 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
13181 for this size change and subsequent size changes.
13182 Otherwise we leave the window gravity unchanged. */
13183
13184 void
13185 x_set_window_size (f, change_gravity, cols, rows)
13186 struct frame *f;
13187 int change_gravity;
13188 int cols, rows;
13189 {
13190 BLOCK_INPUT;
13191
13192 #ifdef USE_X_TOOLKIT
13193
13194 if (f->output_data.x->widget != NULL)
13195 {
13196 /* The x and y position of the widget is clobbered by the
13197 call to XtSetValues within EmacsFrameSetCharSize.
13198 This is a real kludge, but I don't understand Xt so I can't
13199 figure out a correct fix. Can anyone else tell me? -- rms. */
13200 int xpos = f->output_data.x->widget->core.x;
13201 int ypos = f->output_data.x->widget->core.y;
13202 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
13203 f->output_data.x->widget->core.x = xpos;
13204 f->output_data.x->widget->core.y = ypos;
13205 }
13206 else
13207 x_set_window_size_1 (f, change_gravity, cols, rows);
13208
13209 #else /* not USE_X_TOOLKIT */
13210
13211 x_set_window_size_1 (f, change_gravity, cols, rows);
13212
13213 #endif /* not USE_X_TOOLKIT */
13214
13215 /* If cursor was outside the new size, mark it as off. */
13216 mark_window_cursors_off (XWINDOW (f->root_window));
13217
13218 /* Clear out any recollection of where the mouse highlighting was,
13219 since it might be in a place that's outside the new frame size.
13220 Actually checking whether it is outside is a pain in the neck,
13221 so don't try--just let the highlighting be done afresh with new size. */
13222 cancel_mouse_face (f);
13223
13224 UNBLOCK_INPUT;
13225 }
13226 \f
13227 /* Mouse warping. */
13228
13229 void
13230 x_set_mouse_position (f, x, y)
13231 struct frame *f;
13232 int x, y;
13233 {
13234 int pix_x, pix_y;
13235
13236 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
13237 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
13238
13239 if (pix_x < 0) pix_x = 0;
13240 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
13241
13242 if (pix_y < 0) pix_y = 0;
13243 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
13244
13245 BLOCK_INPUT;
13246
13247 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13248 0, 0, 0, 0, pix_x, pix_y);
13249 UNBLOCK_INPUT;
13250 }
13251
13252 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
13253
13254 void
13255 x_set_mouse_pixel_position (f, pix_x, pix_y)
13256 struct frame *f;
13257 int pix_x, pix_y;
13258 {
13259 BLOCK_INPUT;
13260
13261 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
13262 0, 0, 0, 0, pix_x, pix_y);
13263 UNBLOCK_INPUT;
13264 }
13265 \f
13266 /* focus shifting, raising and lowering. */
13267
13268 void
13269 x_focus_on_frame (f)
13270 struct frame *f;
13271 {
13272 #if 0 /* This proves to be unpleasant. */
13273 x_raise_frame (f);
13274 #endif
13275 #if 0
13276 /* I don't think that the ICCCM allows programs to do things like this
13277 without the interaction of the window manager. Whatever you end up
13278 doing with this code, do it to x_unfocus_frame too. */
13279 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
13280 RevertToPointerRoot, CurrentTime);
13281 #endif /* ! 0 */
13282 }
13283
13284 void
13285 x_unfocus_frame (f)
13286 struct frame *f;
13287 {
13288 #if 0
13289 /* Look at the remarks in x_focus_on_frame. */
13290 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
13291 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
13292 RevertToPointerRoot, CurrentTime);
13293 #endif /* ! 0 */
13294 }
13295
13296 /* Raise frame F. */
13297
13298 void
13299 x_raise_frame (f)
13300 struct frame *f;
13301 {
13302 if (f->async_visible)
13303 {
13304 BLOCK_INPUT;
13305 #ifdef USE_X_TOOLKIT
13306 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13307 #else /* not USE_X_TOOLKIT */
13308 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13309 #endif /* not USE_X_TOOLKIT */
13310 XFlush (FRAME_X_DISPLAY (f));
13311 UNBLOCK_INPUT;
13312 }
13313 }
13314
13315 /* Lower frame F. */
13316
13317 void
13318 x_lower_frame (f)
13319 struct frame *f;
13320 {
13321 if (f->async_visible)
13322 {
13323 BLOCK_INPUT;
13324 #ifdef USE_X_TOOLKIT
13325 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
13326 #else /* not USE_X_TOOLKIT */
13327 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13328 #endif /* not USE_X_TOOLKIT */
13329 XFlush (FRAME_X_DISPLAY (f));
13330 UNBLOCK_INPUT;
13331 }
13332 }
13333
13334 static void
13335 XTframe_raise_lower (f, raise_flag)
13336 FRAME_PTR f;
13337 int raise_flag;
13338 {
13339 if (raise_flag)
13340 x_raise_frame (f);
13341 else
13342 x_lower_frame (f);
13343 }
13344 \f
13345 /* Change of visibility. */
13346
13347 /* This tries to wait until the frame is really visible.
13348 However, if the window manager asks the user where to position
13349 the frame, this will return before the user finishes doing that.
13350 The frame will not actually be visible at that time,
13351 but it will become visible later when the window manager
13352 finishes with it. */
13353
13354 void
13355 x_make_frame_visible (f)
13356 struct frame *f;
13357 {
13358 Lisp_Object type;
13359 int original_top, original_left;
13360 int retry_count = 2;
13361
13362 retry:
13363
13364 BLOCK_INPUT;
13365
13366 type = x_icon_type (f);
13367 if (!NILP (type))
13368 x_bitmap_icon (f, type);
13369
13370 if (! FRAME_VISIBLE_P (f))
13371 {
13372 /* We test FRAME_GARBAGED_P here to make sure we don't
13373 call x_set_offset a second time
13374 if we get to x_make_frame_visible a second time
13375 before the window gets really visible. */
13376 if (! FRAME_ICONIFIED_P (f)
13377 && ! f->output_data.x->asked_for_visible)
13378 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13379
13380 f->output_data.x->asked_for_visible = 1;
13381
13382 if (! EQ (Vx_no_window_manager, Qt))
13383 x_wm_set_window_state (f, NormalState);
13384 #ifdef USE_X_TOOLKIT
13385 /* This was XtPopup, but that did nothing for an iconified frame. */
13386 XtMapWidget (f->output_data.x->widget);
13387 #else /* not USE_X_TOOLKIT */
13388 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13389 #endif /* not USE_X_TOOLKIT */
13390 #if 0 /* This seems to bring back scroll bars in the wrong places
13391 if the window configuration has changed. They seem
13392 to come back ok without this. */
13393 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
13394 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13395 #endif
13396 }
13397
13398 XFlush (FRAME_X_DISPLAY (f));
13399
13400 /* Synchronize to ensure Emacs knows the frame is visible
13401 before we do anything else. We do this loop with input not blocked
13402 so that incoming events are handled. */
13403 {
13404 Lisp_Object frame;
13405 int count;
13406 /* This must be before UNBLOCK_INPUT
13407 since events that arrive in response to the actions above
13408 will set it when they are handled. */
13409 int previously_visible = f->output_data.x->has_been_visible;
13410
13411 original_left = f->output_data.x->left_pos;
13412 original_top = f->output_data.x->top_pos;
13413
13414 /* This must come after we set COUNT. */
13415 UNBLOCK_INPUT;
13416
13417 /* We unblock here so that arriving X events are processed. */
13418
13419 /* Now move the window back to where it was "supposed to be".
13420 But don't do it if the gravity is negative.
13421 When the gravity is negative, this uses a position
13422 that is 3 pixels too low. Perhaps that's really the border width.
13423
13424 Don't do this if the window has never been visible before,
13425 because the window manager may choose the position
13426 and we don't want to override it. */
13427
13428 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
13429 && f->output_data.x->win_gravity == NorthWestGravity
13430 && previously_visible)
13431 {
13432 Drawable rootw;
13433 int x, y;
13434 unsigned int width, height, border, depth;
13435
13436 BLOCK_INPUT;
13437
13438 /* On some window managers (such as FVWM) moving an existing
13439 window, even to the same place, causes the window manager
13440 to introduce an offset. This can cause the window to move
13441 to an unexpected location. Check the geometry (a little
13442 slow here) and then verify that the window is in the right
13443 place. If the window is not in the right place, move it
13444 there, and take the potential window manager hit. */
13445 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13446 &rootw, &x, &y, &width, &height, &border, &depth);
13447
13448 if (original_left != x || original_top != y)
13449 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
13450 original_left, original_top);
13451
13452 UNBLOCK_INPUT;
13453 }
13454
13455 XSETFRAME (frame, f);
13456
13457 /* Wait until the frame is visible. Process X events until a
13458 MapNotify event has been seen, or until we think we won't get a
13459 MapNotify at all.. */
13460 for (count = input_signal_count + 10;
13461 input_signal_count < count && !FRAME_VISIBLE_P (f);)
13462 {
13463 /* Force processing of queued events. */
13464 x_sync (f);
13465
13466 /* Machines that do polling rather than SIGIO have been
13467 observed to go into a busy-wait here. So we'll fake an
13468 alarm signal to let the handler know that there's something
13469 to be read. We used to raise a real alarm, but it seems
13470 that the handler isn't always enabled here. This is
13471 probably a bug. */
13472 if (input_polling_used ())
13473 {
13474 /* It could be confusing if a real alarm arrives while
13475 processing the fake one. Turn it off and let the
13476 handler reset it. */
13477 extern void poll_for_input_1 P_ ((void));
13478 int old_poll_suppress_count = poll_suppress_count;
13479 poll_suppress_count = 1;
13480 poll_for_input_1 ();
13481 poll_suppress_count = old_poll_suppress_count;
13482 }
13483
13484 /* See if a MapNotify event has been processed. */
13485 FRAME_SAMPLE_VISIBILITY (f);
13486 }
13487
13488 /* 2000-09-28: In
13489
13490 (let ((f (selected-frame)))
13491 (iconify-frame f)
13492 (raise-frame f))
13493
13494 the frame is not raised with various window managers on
13495 FreeBSD, Linux and Solaris. It turns out that, for some
13496 unknown reason, the call to XtMapWidget is completely ignored.
13497 Mapping the widget a second time works. */
13498
13499 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
13500 goto retry;
13501 }
13502 }
13503
13504 /* Change from mapped state to withdrawn state. */
13505
13506 /* Make the frame visible (mapped and not iconified). */
13507
13508 void
13509 x_make_frame_invisible (f)
13510 struct frame *f;
13511 {
13512 Window window;
13513
13514 #ifdef USE_X_TOOLKIT
13515 /* Use the frame's outermost window, not the one we normally draw on. */
13516 window = XtWindow (f->output_data.x->widget);
13517 #else /* not USE_X_TOOLKIT */
13518 window = FRAME_X_WINDOW (f);
13519 #endif /* not USE_X_TOOLKIT */
13520
13521 /* Don't keep the highlight on an invisible frame. */
13522 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13523 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13524
13525 #if 0/* This might add unreliability; I don't trust it -- rms. */
13526 if (! f->async_visible && ! f->async_iconified)
13527 return;
13528 #endif
13529
13530 BLOCK_INPUT;
13531
13532 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
13533 that the current position of the window is user-specified, rather than
13534 program-specified, so that when the window is mapped again, it will be
13535 placed at the same location, without forcing the user to position it
13536 by hand again (they have already done that once for this window.) */
13537 x_wm_set_size_hint (f, (long) 0, 1);
13538
13539 #ifdef HAVE_X11R4
13540
13541 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
13542 DefaultScreen (FRAME_X_DISPLAY (f))))
13543 {
13544 UNBLOCK_INPUT_RESIGNAL;
13545 error ("Can't notify window manager of window withdrawal");
13546 }
13547 #else /* ! defined (HAVE_X11R4) */
13548
13549 /* Tell the window manager what we're going to do. */
13550 if (! EQ (Vx_no_window_manager, Qt))
13551 {
13552 XEvent unmap;
13553
13554 unmap.xunmap.type = UnmapNotify;
13555 unmap.xunmap.window = window;
13556 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
13557 unmap.xunmap.from_configure = False;
13558 if (! XSendEvent (FRAME_X_DISPLAY (f),
13559 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13560 False,
13561 SubstructureRedirectMaskSubstructureNotifyMask,
13562 &unmap))
13563 {
13564 UNBLOCK_INPUT_RESIGNAL;
13565 error ("Can't notify window manager of withdrawal");
13566 }
13567 }
13568
13569 /* Unmap the window ourselves. Cheeky! */
13570 XUnmapWindow (FRAME_X_DISPLAY (f), window);
13571 #endif /* ! defined (HAVE_X11R4) */
13572
13573 /* We can't distinguish this from iconification
13574 just by the event that we get from the server.
13575 So we can't win using the usual strategy of letting
13576 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
13577 and synchronize with the server to make sure we agree. */
13578 f->visible = 0;
13579 FRAME_ICONIFIED_P (f) = 0;
13580 f->async_visible = 0;
13581 f->async_iconified = 0;
13582
13583 x_sync (f);
13584
13585 UNBLOCK_INPUT;
13586 }
13587
13588 /* Change window state from mapped to iconified. */
13589
13590 void
13591 x_iconify_frame (f)
13592 struct frame *f;
13593 {
13594 int result;
13595 Lisp_Object type;
13596
13597 /* Don't keep the highlight on an invisible frame. */
13598 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13599 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
13600
13601 if (f->async_iconified)
13602 return;
13603
13604 BLOCK_INPUT;
13605
13606 FRAME_SAMPLE_VISIBILITY (f);
13607
13608 type = x_icon_type (f);
13609 if (!NILP (type))
13610 x_bitmap_icon (f, type);
13611
13612 #ifdef USE_X_TOOLKIT
13613
13614 if (! FRAME_VISIBLE_P (f))
13615 {
13616 if (! EQ (Vx_no_window_manager, Qt))
13617 x_wm_set_window_state (f, IconicState);
13618 /* This was XtPopup, but that did nothing for an iconified frame. */
13619 XtMapWidget (f->output_data.x->widget);
13620 /* The server won't give us any event to indicate
13621 that an invisible frame was changed to an icon,
13622 so we have to record it here. */
13623 f->iconified = 1;
13624 f->visible = 1;
13625 f->async_iconified = 1;
13626 f->async_visible = 0;
13627 UNBLOCK_INPUT;
13628 return;
13629 }
13630
13631 result = XIconifyWindow (FRAME_X_DISPLAY (f),
13632 XtWindow (f->output_data.x->widget),
13633 DefaultScreen (FRAME_X_DISPLAY (f)));
13634 UNBLOCK_INPUT;
13635
13636 if (!result)
13637 error ("Can't notify window manager of iconification");
13638
13639 f->async_iconified = 1;
13640 f->async_visible = 0;
13641
13642
13643 BLOCK_INPUT;
13644 XFlush (FRAME_X_DISPLAY (f));
13645 UNBLOCK_INPUT;
13646 #else /* not USE_X_TOOLKIT */
13647
13648 /* Make sure the X server knows where the window should be positioned,
13649 in case the user deiconifies with the window manager. */
13650 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
13651 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
13652
13653 /* Since we don't know which revision of X we're running, we'll use both
13654 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13655
13656 /* X11R4: send a ClientMessage to the window manager using the
13657 WM_CHANGE_STATE type. */
13658 {
13659 XEvent message;
13660
13661 message.xclient.window = FRAME_X_WINDOW (f);
13662 message.xclient.type = ClientMessage;
13663 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
13664 message.xclient.format = 32;
13665 message.xclient.data.l[0] = IconicState;
13666
13667 if (! XSendEvent (FRAME_X_DISPLAY (f),
13668 DefaultRootWindow (FRAME_X_DISPLAY (f)),
13669 False,
13670 SubstructureRedirectMask | SubstructureNotifyMask,
13671 &message))
13672 {
13673 UNBLOCK_INPUT_RESIGNAL;
13674 error ("Can't notify window manager of iconification");
13675 }
13676 }
13677
13678 /* X11R3: set the initial_state field of the window manager hints to
13679 IconicState. */
13680 x_wm_set_window_state (f, IconicState);
13681
13682 if (!FRAME_VISIBLE_P (f))
13683 {
13684 /* If the frame was withdrawn, before, we must map it. */
13685 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13686 }
13687
13688 f->async_iconified = 1;
13689 f->async_visible = 0;
13690
13691 XFlush (FRAME_X_DISPLAY (f));
13692 UNBLOCK_INPUT;
13693 #endif /* not USE_X_TOOLKIT */
13694 }
13695
13696 \f
13697 /* Free X resources of frame F. */
13698
13699 void
13700 x_free_frame_resources (f)
13701 struct frame *f;
13702 {
13703 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13704 Lisp_Object bar;
13705 struct scroll_bar *b;
13706
13707 BLOCK_INPUT;
13708
13709 /* If a display connection is dead, don't try sending more
13710 commands to the X server. */
13711 if (dpyinfo->display)
13712 {
13713 if (f->output_data.x->icon_desc)
13714 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
13715
13716 #ifdef USE_X_TOOLKIT
13717 /* Explicitly destroy the scroll bars of the frame. Without
13718 this, we get "BadDrawable" errors from the toolkit later on,
13719 presumably from expose events generated for the disappearing
13720 toolkit scroll bars. */
13721 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
13722 {
13723 b = XSCROLL_BAR (bar);
13724 x_scroll_bar_remove (b);
13725 }
13726 #endif
13727
13728 #ifdef HAVE_X_I18N
13729 if (FRAME_XIC (f))
13730 free_frame_xic (f);
13731 #endif
13732
13733 #ifdef USE_X_TOOLKIT
13734 if (f->output_data.x->widget)
13735 {
13736 XtDestroyWidget (f->output_data.x->widget);
13737 f->output_data.x->widget = NULL;
13738 }
13739 /* Tooltips don't have widgets, only a simple X window, even if
13740 we are using a toolkit. */
13741 else if (FRAME_X_WINDOW (f))
13742 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13743
13744 free_frame_menubar (f);
13745 #else /* !USE_X_TOOLKIT */
13746 if (FRAME_X_WINDOW (f))
13747 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13748 #endif /* !USE_X_TOOLKIT */
13749
13750 unload_color (f, f->output_data.x->foreground_pixel);
13751 unload_color (f, f->output_data.x->background_pixel);
13752 unload_color (f, f->output_data.x->cursor_pixel);
13753 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13754 unload_color (f, f->output_data.x->border_pixel);
13755 unload_color (f, f->output_data.x->mouse_pixel);
13756
13757 if (f->output_data.x->scroll_bar_background_pixel != -1)
13758 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13759 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13760 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
13761 #ifdef USE_TOOLKIT_SCROLL_BARS
13762 /* Scrollbar shadow colors. */
13763 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13764 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13765 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13766 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13767 #endif /* USE_TOOLKIT_SCROLL_BARS */
13768 if (f->output_data.x->white_relief.allocated_p)
13769 unload_color (f, f->output_data.x->white_relief.pixel);
13770 if (f->output_data.x->black_relief.allocated_p)
13771 unload_color (f, f->output_data.x->black_relief.pixel);
13772
13773 if (FRAME_FACE_CACHE (f))
13774 free_frame_faces (f);
13775
13776 x_free_gcs (f);
13777 XFlush (FRAME_X_DISPLAY (f));
13778 }
13779
13780 if (f->output_data.x->saved_menu_event)
13781 xfree (f->output_data.x->saved_menu_event);
13782
13783 xfree (f->output_data.x);
13784 f->output_data.x = NULL;
13785
13786 if (f == dpyinfo->x_focus_frame)
13787 dpyinfo->x_focus_frame = 0;
13788 if (f == dpyinfo->x_focus_event_frame)
13789 dpyinfo->x_focus_event_frame = 0;
13790 if (f == dpyinfo->x_highlight_frame)
13791 dpyinfo->x_highlight_frame = 0;
13792
13793 if (f == dpyinfo->mouse_face_mouse_frame)
13794 {
13795 dpyinfo->mouse_face_beg_row
13796 = dpyinfo->mouse_face_beg_col = -1;
13797 dpyinfo->mouse_face_end_row
13798 = dpyinfo->mouse_face_end_col = -1;
13799 dpyinfo->mouse_face_window = Qnil;
13800 dpyinfo->mouse_face_deferred_gc = 0;
13801 dpyinfo->mouse_face_mouse_frame = 0;
13802 }
13803
13804 UNBLOCK_INPUT;
13805 }
13806
13807
13808 /* Destroy the X window of frame F. */
13809
13810 void
13811 x_destroy_window (f)
13812 struct frame *f;
13813 {
13814 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13815
13816 /* If a display connection is dead, don't try sending more
13817 commands to the X server. */
13818 if (dpyinfo->display != 0)
13819 x_free_frame_resources (f);
13820
13821 dpyinfo->reference_count--;
13822 }
13823
13824 \f
13825 /* Setting window manager hints. */
13826
13827 /* Set the normal size hints for the window manager, for frame F.
13828 FLAGS is the flags word to use--or 0 meaning preserve the flags
13829 that the window now has.
13830 If USER_POSITION is nonzero, we set the USPosition
13831 flag (this is useful when FLAGS is 0). */
13832
13833 void
13834 x_wm_set_size_hint (f, flags, user_position)
13835 struct frame *f;
13836 long flags;
13837 int user_position;
13838 {
13839 XSizeHints size_hints;
13840
13841 #ifdef USE_X_TOOLKIT
13842 Arg al[2];
13843 int ac = 0;
13844 Dimension widget_width, widget_height;
13845 Window window = XtWindow (f->output_data.x->widget);
13846 #else /* not USE_X_TOOLKIT */
13847 Window window = FRAME_X_WINDOW (f);
13848 #endif /* not USE_X_TOOLKIT */
13849
13850 /* Setting PMaxSize caused various problems. */
13851 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
13852
13853 size_hints.x = f->output_data.x->left_pos;
13854 size_hints.y = f->output_data.x->top_pos;
13855
13856 #ifdef USE_X_TOOLKIT
13857 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13858 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
13859 XtGetValues (f->output_data.x->widget, al, ac);
13860 size_hints.height = widget_height;
13861 size_hints.width = widget_width;
13862 #else /* not USE_X_TOOLKIT */
13863 size_hints.height = PIXEL_HEIGHT (f);
13864 size_hints.width = PIXEL_WIDTH (f);
13865 #endif /* not USE_X_TOOLKIT */
13866
13867 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13868 size_hints.height_inc = f->output_data.x->line_height;
13869 size_hints.max_width
13870 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13871 size_hints.max_height
13872 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
13873
13874 /* Calculate the base and minimum sizes.
13875
13876 (When we use the X toolkit, we don't do it here.
13877 Instead we copy the values that the widgets are using, below.) */
13878 #ifndef USE_X_TOOLKIT
13879 {
13880 int base_width, base_height;
13881 int min_rows = 0, min_cols = 0;
13882
13883 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13884 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
13885
13886 check_frame_size (f, &min_rows, &min_cols);
13887
13888 /* The window manager uses the base width hints to calculate the
13889 current number of rows and columns in the frame while
13890 resizing; min_width and min_height aren't useful for this
13891 purpose, since they might not give the dimensions for a
13892 zero-row, zero-column frame.
13893
13894 We use the base_width and base_height members if we have
13895 them; otherwise, we set the min_width and min_height members
13896 to the size for a zero x zero frame. */
13897
13898 #ifdef HAVE_X11R4
13899 size_hints.flags |= PBaseSize;
13900 size_hints.base_width = base_width;
13901 size_hints.base_height = base_height;
13902 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13903 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
13904 #else
13905 size_hints.min_width = base_width;
13906 size_hints.min_height = base_height;
13907 #endif
13908 }
13909
13910 /* If we don't need the old flags, we don't need the old hint at all. */
13911 if (flags)
13912 {
13913 size_hints.flags |= flags;
13914 goto no_read;
13915 }
13916 #endif /* not USE_X_TOOLKIT */
13917
13918 {
13919 XSizeHints hints; /* Sometimes I hate X Windows... */
13920 long supplied_return;
13921 int value;
13922
13923 #ifdef HAVE_X11R4
13924 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13925 &supplied_return);
13926 #else
13927 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
13928 #endif
13929
13930 #ifdef USE_X_TOOLKIT
13931 size_hints.base_height = hints.base_height;
13932 size_hints.base_width = hints.base_width;
13933 size_hints.min_height = hints.min_height;
13934 size_hints.min_width = hints.min_width;
13935 #endif
13936
13937 if (flags)
13938 size_hints.flags |= flags;
13939 else
13940 {
13941 if (value == 0)
13942 hints.flags = 0;
13943 if (hints.flags & PSize)
13944 size_hints.flags |= PSize;
13945 if (hints.flags & PPosition)
13946 size_hints.flags |= PPosition;
13947 if (hints.flags & USPosition)
13948 size_hints.flags |= USPosition;
13949 if (hints.flags & USSize)
13950 size_hints.flags |= USSize;
13951 }
13952 }
13953
13954 #ifndef USE_X_TOOLKIT
13955 no_read:
13956 #endif
13957
13958 #ifdef PWinGravity
13959 size_hints.win_gravity = f->output_data.x->win_gravity;
13960 size_hints.flags |= PWinGravity;
13961
13962 if (user_position)
13963 {
13964 size_hints.flags &= ~ PPosition;
13965 size_hints.flags |= USPosition;
13966 }
13967 #endif /* PWinGravity */
13968
13969 #ifdef HAVE_X11R4
13970 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13971 #else
13972 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
13973 #endif
13974 }
13975
13976 /* Used for IconicState or NormalState */
13977
13978 void
13979 x_wm_set_window_state (f, state)
13980 struct frame *f;
13981 int state;
13982 {
13983 #ifdef USE_X_TOOLKIT
13984 Arg al[1];
13985
13986 XtSetArg (al[0], XtNinitialState, state);
13987 XtSetValues (f->output_data.x->widget, al, 1);
13988 #else /* not USE_X_TOOLKIT */
13989 Window window = FRAME_X_WINDOW (f);
13990
13991 f->output_data.x->wm_hints.flags |= StateHint;
13992 f->output_data.x->wm_hints.initial_state = state;
13993
13994 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
13995 #endif /* not USE_X_TOOLKIT */
13996 }
13997
13998 void
13999 x_wm_set_icon_pixmap (f, pixmap_id)
14000 struct frame *f;
14001 int pixmap_id;
14002 {
14003 Pixmap icon_pixmap;
14004
14005 #ifndef USE_X_TOOLKIT
14006 Window window = FRAME_X_WINDOW (f);
14007 #endif
14008
14009 if (pixmap_id > 0)
14010 {
14011 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
14012 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
14013 }
14014 else
14015 {
14016 /* It seems there is no way to turn off use of an icon pixmap.
14017 The following line does it, only if no icon has yet been created,
14018 for some window managers. But with mwm it crashes.
14019 Some people say it should clear the IconPixmapHint bit in this case,
14020 but that doesn't work, and the X consortium said it isn't the
14021 right thing at all. Since there is no way to win,
14022 best to explicitly give up. */
14023 #if 0
14024 f->output_data.x->wm_hints.icon_pixmap = None;
14025 #else
14026 return;
14027 #endif
14028 }
14029
14030 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
14031
14032 {
14033 Arg al[1];
14034 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
14035 XtSetValues (f->output_data.x->widget, al, 1);
14036 }
14037
14038 #else /* not USE_X_TOOLKIT */
14039
14040 f->output_data.x->wm_hints.flags |= IconPixmapHint;
14041 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14042
14043 #endif /* not USE_X_TOOLKIT */
14044 }
14045
14046 void
14047 x_wm_set_icon_position (f, icon_x, icon_y)
14048 struct frame *f;
14049 int icon_x, icon_y;
14050 {
14051 #ifdef USE_X_TOOLKIT
14052 Window window = XtWindow (f->output_data.x->widget);
14053 #else
14054 Window window = FRAME_X_WINDOW (f);
14055 #endif
14056
14057 f->output_data.x->wm_hints.flags |= IconPositionHint;
14058 f->output_data.x->wm_hints.icon_x = icon_x;
14059 f->output_data.x->wm_hints.icon_y = icon_y;
14060
14061 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
14062 }
14063
14064 \f
14065 /***********************************************************************
14066 Fonts
14067 ***********************************************************************/
14068
14069 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
14070
14071 struct font_info *
14072 x_get_font_info (f, font_idx)
14073 FRAME_PTR f;
14074 int font_idx;
14075 {
14076 return (FRAME_X_FONT_TABLE (f) + font_idx);
14077 }
14078
14079
14080 /* Return a list of names of available fonts matching PATTERN on frame F.
14081
14082 If SIZE is > 0, it is the size (maximum bounds width) of fonts
14083 to be listed.
14084
14085 SIZE < 0 means include scalable fonts.
14086
14087 Frame F null means we have not yet created any frame on X, and
14088 consult the first display in x_display_list. MAXNAMES sets a limit
14089 on how many fonts to match. */
14090
14091 Lisp_Object
14092 x_list_fonts (f, pattern, size, maxnames)
14093 struct frame *f;
14094 Lisp_Object pattern;
14095 int size;
14096 int maxnames;
14097 {
14098 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
14099 Lisp_Object tem, second_best;
14100 struct x_display_info *dpyinfo
14101 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
14102 Display *dpy = dpyinfo->display;
14103 int try_XLoadQueryFont = 0;
14104 int count;
14105 int allow_scalable_fonts_p = 0;
14106
14107 if (size < 0)
14108 {
14109 allow_scalable_fonts_p = 1;
14110 size = 0;
14111 }
14112
14113 patterns = Fassoc (pattern, Valternate_fontname_alist);
14114 if (NILP (patterns))
14115 patterns = Fcons (pattern, Qnil);
14116
14117 if (maxnames == 1 && !size)
14118 /* We can return any single font matching PATTERN. */
14119 try_XLoadQueryFont = 1;
14120
14121 for (; CONSP (patterns); patterns = XCDR (patterns))
14122 {
14123 int num_fonts;
14124 char **names = NULL;
14125
14126 pattern = XCAR (patterns);
14127 /* See if we cached the result for this particular query.
14128 The cache is an alist of the form:
14129 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
14130 tem = XCDR (dpyinfo->name_list_element);
14131 key = Fcons (Fcons (pattern, make_number (maxnames)),
14132 allow_scalable_fonts_p ? Qt : Qnil);
14133 list = Fassoc (key, tem);
14134 if (!NILP (list))
14135 {
14136 list = Fcdr_safe (list);
14137 /* We have a cashed list. Don't have to get the list again. */
14138 goto label_cached;
14139 }
14140
14141 /* At first, put PATTERN in the cache. */
14142
14143 BLOCK_INPUT;
14144 count = x_catch_errors (dpy);
14145
14146 if (try_XLoadQueryFont)
14147 {
14148 XFontStruct *font;
14149 unsigned long value;
14150
14151 font = XLoadQueryFont (dpy, SDATA (pattern));
14152 if (x_had_errors_p (dpy))
14153 {
14154 /* This error is perhaps due to insufficient memory on X
14155 server. Let's just ignore it. */
14156 font = NULL;
14157 x_clear_errors (dpy);
14158 }
14159
14160 if (font
14161 && XGetFontProperty (font, XA_FONT, &value))
14162 {
14163 char *name = (char *) XGetAtomName (dpy, (Atom) value);
14164 int len = strlen (name);
14165 char *tmp;
14166
14167 /* If DXPC (a Differential X Protocol Compressor)
14168 Ver.3.7 is running, XGetAtomName will return null
14169 string. We must avoid such a name. */
14170 if (len == 0)
14171 try_XLoadQueryFont = 0;
14172 else
14173 {
14174 num_fonts = 1;
14175 names = (char **) alloca (sizeof (char *));
14176 /* Some systems only allow alloca assigned to a
14177 simple var. */
14178 tmp = (char *) alloca (len + 1); names[0] = tmp;
14179 bcopy (name, names[0], len + 1);
14180 XFree (name);
14181 }
14182 }
14183 else
14184 try_XLoadQueryFont = 0;
14185
14186 if (font)
14187 XFreeFont (dpy, font);
14188 }
14189
14190 if (!try_XLoadQueryFont)
14191 {
14192 /* We try at least 10 fonts because XListFonts will return
14193 auto-scaled fonts at the head. */
14194 names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
14195 &num_fonts);
14196 if (x_had_errors_p (dpy))
14197 {
14198 /* This error is perhaps due to insufficient memory on X
14199 server. Let's just ignore it. */
14200 names = NULL;
14201 x_clear_errors (dpy);
14202 }
14203 }
14204
14205 x_uncatch_errors (dpy, count);
14206 UNBLOCK_INPUT;
14207
14208 if (names)
14209 {
14210 int i;
14211
14212 /* Make a list of all the fonts we got back.
14213 Store that in the font cache for the display. */
14214 for (i = 0; i < num_fonts; i++)
14215 {
14216 int width = 0;
14217 char *p = names[i];
14218 int average_width = -1, dashes = 0;
14219
14220 /* Count the number of dashes in NAMES[I]. If there are
14221 14 dashes, and the field value following 12th dash
14222 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
14223 is usually too ugly to be used for editing. Let's
14224 ignore it. */
14225 while (*p)
14226 if (*p++ == '-')
14227 {
14228 dashes++;
14229 if (dashes == 7) /* PIXEL_SIZE field */
14230 width = atoi (p);
14231 else if (dashes == 12) /* AVERAGE_WIDTH field */
14232 average_width = atoi (p);
14233 }
14234
14235 if (allow_scalable_fonts_p
14236 || dashes < 14 || average_width != 0)
14237 {
14238 tem = build_string (names[i]);
14239 if (NILP (Fassoc (tem, list)))
14240 {
14241 if (STRINGP (Vx_pixel_size_width_font_regexp)
14242 && ((fast_c_string_match_ignore_case
14243 (Vx_pixel_size_width_font_regexp, names[i]))
14244 >= 0))
14245 /* We can set the value of PIXEL_SIZE to the
14246 width of this font. */
14247 list = Fcons (Fcons (tem, make_number (width)), list);
14248 else
14249 /* For the moment, width is not known. */
14250 list = Fcons (Fcons (tem, Qnil), list);
14251 }
14252 }
14253 }
14254
14255 if (!try_XLoadQueryFont)
14256 {
14257 BLOCK_INPUT;
14258 XFreeFontNames (names);
14259 UNBLOCK_INPUT;
14260 }
14261 }
14262
14263 /* Now store the result in the cache. */
14264 XSETCDR (dpyinfo->name_list_element,
14265 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
14266
14267 label_cached:
14268 if (NILP (list)) continue; /* Try the remaining alternatives. */
14269
14270 newlist = second_best = Qnil;
14271 /* Make a list of the fonts that have the right width. */
14272 for (; CONSP (list); list = XCDR (list))
14273 {
14274 int found_size;
14275
14276 tem = XCAR (list);
14277
14278 if (!CONSP (tem) || NILP (XCAR (tem)))
14279 continue;
14280 if (!size)
14281 {
14282 newlist = Fcons (XCAR (tem), newlist);
14283 continue;
14284 }
14285
14286 if (!INTEGERP (XCDR (tem)))
14287 {
14288 /* Since we have not yet known the size of this font, we
14289 must try slow function call XLoadQueryFont. */
14290 XFontStruct *thisinfo;
14291
14292 BLOCK_INPUT;
14293 count = x_catch_errors (dpy);
14294 thisinfo = XLoadQueryFont (dpy,
14295 SDATA (XCAR (tem)));
14296 if (x_had_errors_p (dpy))
14297 {
14298 /* This error is perhaps due to insufficient memory on X
14299 server. Let's just ignore it. */
14300 thisinfo = NULL;
14301 x_clear_errors (dpy);
14302 }
14303 x_uncatch_errors (dpy, count);
14304 UNBLOCK_INPUT;
14305
14306 if (thisinfo)
14307 {
14308 XSETCDR (tem,
14309 (thisinfo->min_bounds.width == 0
14310 ? make_number (0)
14311 : make_number (thisinfo->max_bounds.width)));
14312 BLOCK_INPUT;
14313 XFreeFont (dpy, thisinfo);
14314 UNBLOCK_INPUT;
14315 }
14316 else
14317 /* For unknown reason, the previous call of XListFont had
14318 returned a font which can't be opened. Record the size
14319 as 0 not to try to open it again. */
14320 XSETCDR (tem, make_number (0));
14321 }
14322
14323 found_size = XINT (XCDR (tem));
14324 if (found_size == size)
14325 newlist = Fcons (XCAR (tem), newlist);
14326 else if (found_size > 0)
14327 {
14328 if (NILP (second_best))
14329 second_best = tem;
14330 else if (found_size < size)
14331 {
14332 if (XINT (XCDR (second_best)) > size
14333 || XINT (XCDR (second_best)) < found_size)
14334 second_best = tem;
14335 }
14336 else
14337 {
14338 if (XINT (XCDR (second_best)) > size
14339 && XINT (XCDR (second_best)) > found_size)
14340 second_best = tem;
14341 }
14342 }
14343 }
14344 if (!NILP (newlist))
14345 break;
14346 else if (!NILP (second_best))
14347 {
14348 newlist = Fcons (XCAR (second_best), Qnil);
14349 break;
14350 }
14351 }
14352
14353 return newlist;
14354 }
14355
14356
14357 #if GLYPH_DEBUG
14358
14359 /* Check that FONT is valid on frame F. It is if it can be found in F's
14360 font table. */
14361
14362 static void
14363 x_check_font (f, font)
14364 struct frame *f;
14365 XFontStruct *font;
14366 {
14367 int i;
14368 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14369
14370 xassert (font != NULL);
14371
14372 for (i = 0; i < dpyinfo->n_fonts; i++)
14373 if (dpyinfo->font_table[i].name
14374 && font == dpyinfo->font_table[i].font)
14375 break;
14376
14377 xassert (i < dpyinfo->n_fonts);
14378 }
14379
14380 #endif /* GLYPH_DEBUG != 0 */
14381
14382 /* Set *W to the minimum width, *H to the minimum font height of FONT.
14383 Note: There are (broken) X fonts out there with invalid XFontStruct
14384 min_bounds contents. For example, handa@etl.go.jp reports that
14385 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
14386 have font->min_bounds.width == 0. */
14387
14388 static INLINE void
14389 x_font_min_bounds (font, w, h)
14390 XFontStruct *font;
14391 int *w, *h;
14392 {
14393 *h = FONT_HEIGHT (font);
14394 *w = font->min_bounds.width;
14395
14396 /* Try to handle the case where FONT->min_bounds has invalid
14397 contents. Since the only font known to have invalid min_bounds
14398 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
14399 if (*w <= 0)
14400 *w = font->max_bounds.width;
14401 }
14402
14403
14404 /* Compute the smallest character width and smallest font height over
14405 all fonts available on frame F. Set the members smallest_char_width
14406 and smallest_font_height in F's x_display_info structure to
14407 the values computed. Value is non-zero if smallest_font_height or
14408 smallest_char_width become smaller than they were before. */
14409
14410 static int
14411 x_compute_min_glyph_bounds (f)
14412 struct frame *f;
14413 {
14414 int i;
14415 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14416 XFontStruct *font;
14417 int old_width = dpyinfo->smallest_char_width;
14418 int old_height = dpyinfo->smallest_font_height;
14419
14420 dpyinfo->smallest_font_height = 100000;
14421 dpyinfo->smallest_char_width = 100000;
14422
14423 for (i = 0; i < dpyinfo->n_fonts; ++i)
14424 if (dpyinfo->font_table[i].name)
14425 {
14426 struct font_info *fontp = dpyinfo->font_table + i;
14427 int w, h;
14428
14429 font = (XFontStruct *) fontp->font;
14430 xassert (font != (XFontStruct *) ~0);
14431 x_font_min_bounds (font, &w, &h);
14432
14433 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
14434 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
14435 }
14436
14437 xassert (dpyinfo->smallest_char_width > 0
14438 && dpyinfo->smallest_font_height > 0);
14439
14440 return (dpyinfo->n_fonts == 1
14441 || dpyinfo->smallest_char_width < old_width
14442 || dpyinfo->smallest_font_height < old_height);
14443 }
14444
14445
14446 /* Load font named FONTNAME of the size SIZE for frame F, and return a
14447 pointer to the structure font_info while allocating it dynamically.
14448 If SIZE is 0, load any size of font.
14449 If loading is failed, return NULL. */
14450
14451 struct font_info *
14452 x_load_font (f, fontname, size)
14453 struct frame *f;
14454 register char *fontname;
14455 int size;
14456 {
14457 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14458 Lisp_Object font_names;
14459 int count;
14460
14461 /* Get a list of all the fonts that match this name. Once we
14462 have a list of matching fonts, we compare them against the fonts
14463 we already have by comparing names. */
14464 font_names = x_list_fonts (f, build_string (fontname), size, 1);
14465
14466 if (!NILP (font_names))
14467 {
14468 Lisp_Object tail;
14469 int i;
14470
14471 for (i = 0; i < dpyinfo->n_fonts; i++)
14472 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
14473 if (dpyinfo->font_table[i].name
14474 && (!strcmp (dpyinfo->font_table[i].name,
14475 SDATA (XCAR (tail)))
14476 || !strcmp (dpyinfo->font_table[i].full_name,
14477 SDATA (XCAR (tail)))))
14478 return (dpyinfo->font_table + i);
14479 }
14480
14481 /* Load the font and add it to the table. */
14482 {
14483 char *full_name;
14484 XFontStruct *font;
14485 struct font_info *fontp;
14486 unsigned long value;
14487 int i;
14488
14489 /* If we have found fonts by x_list_font, load one of them. If
14490 not, we still try to load a font by the name given as FONTNAME
14491 because XListFonts (called in x_list_font) of some X server has
14492 a bug of not finding a font even if the font surely exists and
14493 is loadable by XLoadQueryFont. */
14494 if (size > 0 && !NILP (font_names))
14495 fontname = (char *) SDATA (XCAR (font_names));
14496
14497 BLOCK_INPUT;
14498 count = x_catch_errors (FRAME_X_DISPLAY (f));
14499 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
14500 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
14501 {
14502 /* This error is perhaps due to insufficient memory on X
14503 server. Let's just ignore it. */
14504 font = NULL;
14505 x_clear_errors (FRAME_X_DISPLAY (f));
14506 }
14507 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
14508 UNBLOCK_INPUT;
14509 if (!font)
14510 return NULL;
14511
14512 /* Find a free slot in the font table. */
14513 for (i = 0; i < dpyinfo->n_fonts; ++i)
14514 if (dpyinfo->font_table[i].name == NULL)
14515 break;
14516
14517 /* If no free slot found, maybe enlarge the font table. */
14518 if (i == dpyinfo->n_fonts
14519 && dpyinfo->n_fonts == dpyinfo->font_table_size)
14520 {
14521 int sz;
14522 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
14523 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
14524 dpyinfo->font_table
14525 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
14526 }
14527
14528 fontp = dpyinfo->font_table + i;
14529 if (i == dpyinfo->n_fonts)
14530 ++dpyinfo->n_fonts;
14531
14532 /* Now fill in the slots of *FONTP. */
14533 BLOCK_INPUT;
14534 fontp->font = font;
14535 fontp->font_idx = i;
14536 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
14537 bcopy (fontname, fontp->name, strlen (fontname) + 1);
14538
14539 /* Try to get the full name of FONT. Put it in FULL_NAME. */
14540 full_name = 0;
14541 if (XGetFontProperty (font, XA_FONT, &value))
14542 {
14543 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
14544 char *p = name;
14545 int dashes = 0;
14546
14547 /* Count the number of dashes in the "full name".
14548 If it is too few, this isn't really the font's full name,
14549 so don't use it.
14550 In X11R4, the fonts did not come with their canonical names
14551 stored in them. */
14552 while (*p)
14553 {
14554 if (*p == '-')
14555 dashes++;
14556 p++;
14557 }
14558
14559 if (dashes >= 13)
14560 {
14561 full_name = (char *) xmalloc (p - name + 1);
14562 bcopy (name, full_name, p - name + 1);
14563 }
14564
14565 XFree (name);
14566 }
14567
14568 if (full_name != 0)
14569 fontp->full_name = full_name;
14570 else
14571 fontp->full_name = fontp->name;
14572
14573 fontp->size = font->max_bounds.width;
14574 fontp->height = FONT_HEIGHT (font);
14575
14576 if (NILP (font_names))
14577 {
14578 /* We come here because of a bug of XListFonts mentioned at
14579 the head of this block. Let's store this information in
14580 the cache for x_list_fonts. */
14581 Lisp_Object lispy_name = build_string (fontname);
14582 Lisp_Object lispy_full_name = build_string (fontp->full_name);
14583 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
14584 Qnil);
14585
14586 XSETCDR (dpyinfo->name_list_element,
14587 Fcons (Fcons (key,
14588 Fcons (Fcons (lispy_full_name,
14589 make_number (fontp->size)),
14590 Qnil)),
14591 XCDR (dpyinfo->name_list_element)));
14592 if (full_name)
14593 {
14594 key = Fcons (Fcons (lispy_full_name, make_number (256)),
14595 Qnil);
14596 XSETCDR (dpyinfo->name_list_element,
14597 Fcons (Fcons (key,
14598 Fcons (Fcons (lispy_full_name,
14599 make_number (fontp->size)),
14600 Qnil)),
14601 XCDR (dpyinfo->name_list_element)));
14602 }
14603 }
14604
14605 /* The slot `encoding' specifies how to map a character
14606 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
14607 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14608 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
14609 2:0xA020..0xFF7F). For the moment, we don't know which charset
14610 uses this font. So, we set information in fontp->encoding[1]
14611 which is never used by any charset. If mapping can't be
14612 decided, set FONT_ENCODING_NOT_DECIDED. */
14613 fontp->encoding[1]
14614 = (font->max_byte1 == 0
14615 /* 1-byte font */
14616 ? (font->min_char_or_byte2 < 0x80
14617 ? (font->max_char_or_byte2 < 0x80
14618 ? 0 /* 0x20..0x7F */
14619 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
14620 : 1) /* 0xA0..0xFF */
14621 /* 2-byte font */
14622 : (font->min_byte1 < 0x80
14623 ? (font->max_byte1 < 0x80
14624 ? (font->min_char_or_byte2 < 0x80
14625 ? (font->max_char_or_byte2 < 0x80
14626 ? 0 /* 0x2020..0x7F7F */
14627 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
14628 : 3) /* 0x20A0..0x7FFF */
14629 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
14630 : (font->min_char_or_byte2 < 0x80
14631 ? (font->max_char_or_byte2 < 0x80
14632 ? 2 /* 0xA020..0xFF7F */
14633 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
14634 : 1))); /* 0xA0A0..0xFFFF */
14635
14636 fontp->baseline_offset
14637 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14638 ? (long) value : 0);
14639 fontp->relative_compose
14640 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14641 ? (long) value : 0);
14642 fontp->default_ascent
14643 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14644 ? (long) value : 0);
14645
14646 /* Set global flag fonts_changed_p to non-zero if the font loaded
14647 has a character with a smaller width than any other character
14648 before, or if the font loaded has a smaller height than any
14649 other font loaded before. If this happens, it will make a
14650 glyph matrix reallocation necessary. */
14651 fonts_changed_p |= x_compute_min_glyph_bounds (f);
14652 UNBLOCK_INPUT;
14653 return fontp;
14654 }
14655 }
14656
14657
14658 /* Return a pointer to struct font_info of a font named FONTNAME for
14659 frame F. If no such font is loaded, return NULL. */
14660
14661 struct font_info *
14662 x_query_font (f, fontname)
14663 struct frame *f;
14664 register char *fontname;
14665 {
14666 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14667 int i;
14668
14669 for (i = 0; i < dpyinfo->n_fonts; i++)
14670 if (dpyinfo->font_table[i].name
14671 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14672 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
14673 return (dpyinfo->font_table + i);
14674 return NULL;
14675 }
14676
14677
14678 /* Find a CCL program for a font specified by FONTP, and set the member
14679 `encoder' of the structure. */
14680
14681 void
14682 x_find_ccl_program (fontp)
14683 struct font_info *fontp;
14684 {
14685 Lisp_Object list, elt;
14686
14687 elt = Qnil;
14688 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
14689 {
14690 elt = XCAR (list);
14691 if (CONSP (elt)
14692 && STRINGP (XCAR (elt))
14693 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14694 >= 0)
14695 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14696 >= 0)))
14697 break;
14698 }
14699
14700 if (! NILP (list))
14701 {
14702 struct ccl_program *ccl
14703 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
14704
14705 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
14706 xfree (ccl);
14707 else
14708 fontp->font_encoder = ccl;
14709 }
14710 }
14711
14712
14713 \f
14714 /***********************************************************************
14715 Initialization
14716 ***********************************************************************/
14717
14718 #ifdef USE_X_TOOLKIT
14719 static XrmOptionDescRec emacs_options[] = {
14720 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14721 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14722
14723 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14724 XrmoptionSepArg, NULL},
14725 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14726
14727 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14728 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14729 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14730 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14731 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14732 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14733 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14734 };
14735 #endif /* USE_X_TOOLKIT */
14736
14737 static int x_initialized;
14738
14739 #ifdef MULTI_KBOARD
14740 /* Test whether two display-name strings agree up to the dot that separates
14741 the screen number from the server number. */
14742 static int
14743 same_x_server (name1, name2)
14744 const char *name1, *name2;
14745 {
14746 int seen_colon = 0;
14747 const unsigned char *system_name = SDATA (Vsystem_name);
14748 int system_name_length = strlen (system_name);
14749 int length_until_period = 0;
14750
14751 while (system_name[length_until_period] != 0
14752 && system_name[length_until_period] != '.')
14753 length_until_period++;
14754
14755 /* Treat `unix' like an empty host name. */
14756 if (! strncmp (name1, "unix:", 5))
14757 name1 += 4;
14758 if (! strncmp (name2, "unix:", 5))
14759 name2 += 4;
14760 /* Treat this host's name like an empty host name. */
14761 if (! strncmp (name1, system_name, system_name_length)
14762 && name1[system_name_length] == ':')
14763 name1 += system_name_length;
14764 if (! strncmp (name2, system_name, system_name_length)
14765 && name2[system_name_length] == ':')
14766 name2 += system_name_length;
14767 /* Treat this host's domainless name like an empty host name. */
14768 if (! strncmp (name1, system_name, length_until_period)
14769 && name1[length_until_period] == ':')
14770 name1 += length_until_period;
14771 if (! strncmp (name2, system_name, length_until_period)
14772 && name2[length_until_period] == ':')
14773 name2 += length_until_period;
14774
14775 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14776 {
14777 if (*name1 == ':')
14778 seen_colon++;
14779 if (seen_colon && *name1 == '.')
14780 return 1;
14781 }
14782 return (seen_colon
14783 && (*name1 == '.' || *name1 == '\0')
14784 && (*name2 == '.' || *name2 == '\0'));
14785 }
14786 #endif
14787
14788 struct x_display_info *
14789 x_term_init (display_name, xrm_option, resource_name)
14790 Lisp_Object display_name;
14791 char *xrm_option;
14792 char *resource_name;
14793 {
14794 int connection;
14795 Display *dpy;
14796 struct x_display_info *dpyinfo;
14797 XrmDatabase xrdb;
14798
14799 BLOCK_INPUT;
14800
14801 if (!x_initialized)
14802 {
14803 x_initialize ();
14804 x_initialized = 1;
14805 }
14806
14807 #ifdef USE_X_TOOLKIT
14808 /* weiner@footloose.sps.mot.com reports that this causes
14809 errors with X11R5:
14810 X protocol error: BadAtom (invalid Atom parameter)
14811 on protocol request 18skiloaf.
14812 So let's not use it until R6. */
14813 #ifdef HAVE_X11XTR6
14814 XtSetLanguageProc (NULL, NULL, NULL);
14815 #endif
14816
14817 {
14818 int argc = 0;
14819 char *argv[3];
14820
14821 argv[0] = "";
14822 argc = 1;
14823 if (xrm_option)
14824 {
14825 argv[argc++] = "-xrm";
14826 argv[argc++] = xrm_option;
14827 }
14828 turn_on_atimers (0);
14829 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
14830 resource_name, EMACS_CLASS,
14831 emacs_options, XtNumber (emacs_options),
14832 &argc, argv);
14833 turn_on_atimers (1);
14834
14835 #ifdef HAVE_X11XTR6
14836 /* I think this is to compensate for XtSetLanguageProc. */
14837 fixup_locale ();
14838 #endif
14839 }
14840
14841 #else /* not USE_X_TOOLKIT */
14842 #ifdef HAVE_X11R5
14843 XSetLocaleModifiers ("");
14844 #endif
14845 dpy = XOpenDisplay (SDATA (display_name));
14846 #endif /* not USE_X_TOOLKIT */
14847
14848 /* Detect failure. */
14849 if (dpy == 0)
14850 {
14851 UNBLOCK_INPUT;
14852 return 0;
14853 }
14854
14855 /* We have definitely succeeded. Record the new connection. */
14856
14857 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
14858 bzero (dpyinfo, sizeof *dpyinfo);
14859
14860 #ifdef MULTI_KBOARD
14861 {
14862 struct x_display_info *share;
14863 Lisp_Object tail;
14864
14865 for (share = x_display_list, tail = x_display_name_list; share;
14866 share = share->next, tail = XCDR (tail))
14867 if (same_x_server (SDATA (XCAR (XCAR (tail))),
14868 SDATA (display_name)))
14869 break;
14870 if (share)
14871 dpyinfo->kboard = share->kboard;
14872 else
14873 {
14874 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14875 init_kboard (dpyinfo->kboard);
14876 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14877 {
14878 char *vendor = ServerVendor (dpy);
14879 UNBLOCK_INPUT;
14880 dpyinfo->kboard->Vsystem_key_alist
14881 = call1 (Qvendor_specific_keysyms,
14882 build_string (vendor ? vendor : ""));
14883 BLOCK_INPUT;
14884 }
14885
14886 dpyinfo->kboard->next_kboard = all_kboards;
14887 all_kboards = dpyinfo->kboard;
14888 /* Don't let the initial kboard remain current longer than necessary.
14889 That would cause problems if a file loaded on startup tries to
14890 prompt in the mini-buffer. */
14891 if (current_kboard == initial_kboard)
14892 current_kboard = dpyinfo->kboard;
14893 }
14894 dpyinfo->kboard->reference_count++;
14895 }
14896 #endif
14897
14898 /* Put this display on the chain. */
14899 dpyinfo->next = x_display_list;
14900 x_display_list = dpyinfo;
14901
14902 /* Put it on x_display_name_list as well, to keep them parallel. */
14903 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14904 x_display_name_list);
14905 dpyinfo->name_list_element = XCAR (x_display_name_list);
14906
14907 dpyinfo->display = dpy;
14908
14909 #if 0
14910 XSetAfterFunction (x_current_display, x_trace_wire);
14911 #endif /* ! 0 */
14912
14913 dpyinfo->x_id_name
14914 = (char *) xmalloc (SBYTES (Vinvocation_name)
14915 + SBYTES (Vsystem_name)
14916 + 2);
14917 sprintf (dpyinfo->x_id_name, "%s@%s",
14918 SDATA (Vinvocation_name), SDATA (Vsystem_name));
14919
14920 /* Figure out which modifier bits mean what. */
14921 x_find_modifier_meanings (dpyinfo);
14922
14923 /* Get the scroll bar cursor. */
14924 dpyinfo->vertical_scroll_bar_cursor
14925 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
14926
14927 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14928 resource_name, EMACS_CLASS);
14929 #ifdef HAVE_XRMSETDATABASE
14930 XrmSetDatabase (dpyinfo->display, xrdb);
14931 #else
14932 dpyinfo->display->db = xrdb;
14933 #endif
14934 /* Put the rdb where we can find it in a way that works on
14935 all versions. */
14936 dpyinfo->xrdb = xrdb;
14937
14938 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14939 DefaultScreen (dpyinfo->display));
14940 select_visual (dpyinfo);
14941 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
14942 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14943 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14944 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14945 dpyinfo->grabbed = 0;
14946 dpyinfo->reference_count = 0;
14947 dpyinfo->icon_bitmap_id = -1;
14948 dpyinfo->font_table = NULL;
14949 dpyinfo->n_fonts = 0;
14950 dpyinfo->font_table_size = 0;
14951 dpyinfo->bitmaps = 0;
14952 dpyinfo->bitmaps_size = 0;
14953 dpyinfo->bitmaps_last = 0;
14954 dpyinfo->scratch_cursor_gc = 0;
14955 dpyinfo->mouse_face_mouse_frame = 0;
14956 dpyinfo->mouse_face_deferred_gc = 0;
14957 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14958 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
14959 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
14960 dpyinfo->mouse_face_window = Qnil;
14961 dpyinfo->mouse_face_overlay = Qnil;
14962 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14963 dpyinfo->mouse_face_defer = 0;
14964 dpyinfo->mouse_face_hidden = 0;
14965 dpyinfo->x_focus_frame = 0;
14966 dpyinfo->x_focus_event_frame = 0;
14967 dpyinfo->x_highlight_frame = 0;
14968 dpyinfo->image_cache = make_image_cache ();
14969
14970 /* See if a private colormap is requested. */
14971 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14972 {
14973 if (dpyinfo->visual->class == PseudoColor)
14974 {
14975 Lisp_Object value;
14976 value = display_x_get_resource (dpyinfo,
14977 build_string ("privateColormap"),
14978 build_string ("PrivateColormap"),
14979 Qnil, Qnil);
14980 if (STRINGP (value)
14981 && (!strcmp (SDATA (value), "true")
14982 || !strcmp (SDATA (value), "on")))
14983 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14984 }
14985 }
14986 else
14987 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14988 dpyinfo->visual, AllocNone);
14989
14990 {
14991 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14992 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14993 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14994 dpyinfo->resy = pixels * 25.4 / mm;
14995 pixels = DisplayWidth (dpyinfo->display, screen_number);
14996 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14997 dpyinfo->resx = pixels * 25.4 / mm;
14998 }
14999
15000 dpyinfo->Xatom_wm_protocols
15001 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
15002 dpyinfo->Xatom_wm_take_focus
15003 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
15004 dpyinfo->Xatom_wm_save_yourself
15005 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
15006 dpyinfo->Xatom_wm_delete_window
15007 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
15008 dpyinfo->Xatom_wm_change_state
15009 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
15010 dpyinfo->Xatom_wm_configure_denied
15011 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
15012 dpyinfo->Xatom_wm_window_moved
15013 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
15014 dpyinfo->Xatom_editres
15015 = XInternAtom (dpyinfo->display, "Editres", False);
15016 dpyinfo->Xatom_CLIPBOARD
15017 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
15018 dpyinfo->Xatom_TIMESTAMP
15019 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
15020 dpyinfo->Xatom_TEXT
15021 = XInternAtom (dpyinfo->display, "TEXT", False);
15022 dpyinfo->Xatom_COMPOUND_TEXT
15023 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
15024 dpyinfo->Xatom_UTF8_STRING
15025 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
15026 dpyinfo->Xatom_DELETE
15027 = XInternAtom (dpyinfo->display, "DELETE", False);
15028 dpyinfo->Xatom_MULTIPLE
15029 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
15030 dpyinfo->Xatom_INCR
15031 = XInternAtom (dpyinfo->display, "INCR", False);
15032 dpyinfo->Xatom_EMACS_TMP
15033 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
15034 dpyinfo->Xatom_TARGETS
15035 = XInternAtom (dpyinfo->display, "TARGETS", False);
15036 dpyinfo->Xatom_NULL
15037 = XInternAtom (dpyinfo->display, "NULL", False);
15038 dpyinfo->Xatom_ATOM_PAIR
15039 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
15040 /* For properties of font. */
15041 dpyinfo->Xatom_PIXEL_SIZE
15042 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
15043 dpyinfo->Xatom_MULE_BASELINE_OFFSET
15044 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
15045 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
15046 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
15047 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
15048 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
15049
15050 /* Ghostscript support. */
15051 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
15052 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
15053
15054 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
15055 False);
15056
15057 dpyinfo->cut_buffers_initialized = 0;
15058
15059 connection = ConnectionNumber (dpyinfo->display);
15060 dpyinfo->connection = connection;
15061
15062 {
15063 char null_bits[1];
15064
15065 null_bits[0] = 0x00;
15066
15067 dpyinfo->null_pixel
15068 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15069 null_bits, 1, 1, (long) 0, (long) 0,
15070 1);
15071 }
15072
15073 {
15074 extern int gray_bitmap_width, gray_bitmap_height;
15075 extern char *gray_bitmap_bits;
15076 dpyinfo->gray
15077 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
15078 gray_bitmap_bits,
15079 gray_bitmap_width, gray_bitmap_height,
15080 (unsigned long) 1, (unsigned long) 0, 1);
15081 }
15082
15083 #ifdef HAVE_X_I18N
15084 xim_initialize (dpyinfo, resource_name);
15085 #endif
15086
15087 #ifdef subprocesses
15088 /* This is only needed for distinguishing keyboard and process input. */
15089 if (connection != 0)
15090 add_keyboard_wait_descriptor (connection);
15091 #endif
15092
15093 #ifndef F_SETOWN_BUG
15094 #ifdef F_SETOWN
15095 #ifdef F_SETOWN_SOCK_NEG
15096 /* stdin is a socket here */
15097 fcntl (connection, F_SETOWN, -getpid ());
15098 #else /* ! defined (F_SETOWN_SOCK_NEG) */
15099 fcntl (connection, F_SETOWN, getpid ());
15100 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
15101 #endif /* ! defined (F_SETOWN) */
15102 #endif /* F_SETOWN_BUG */
15103
15104 #ifdef SIGIO
15105 if (interrupt_input)
15106 init_sigio (connection);
15107 #endif /* ! defined (SIGIO) */
15108
15109 #ifdef USE_LUCID
15110 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
15111 /* Make sure that we have a valid font for dialog boxes
15112 so that Xt does not crash. */
15113 {
15114 Display *dpy = dpyinfo->display;
15115 XrmValue d, fr, to;
15116 Font font;
15117 int count;
15118
15119 d.addr = (XPointer)&dpy;
15120 d.size = sizeof (Display *);
15121 fr.addr = XtDefaultFont;
15122 fr.size = sizeof (XtDefaultFont);
15123 to.size = sizeof (Font *);
15124 to.addr = (XPointer)&font;
15125 count = x_catch_errors (dpy);
15126 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
15127 abort ();
15128 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
15129 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
15130 x_uncatch_errors (dpy, count);
15131 }
15132 #endif
15133 #endif
15134
15135 /* See if we should run in synchronous mode. This is useful
15136 for debugging X code. */
15137 {
15138 Lisp_Object value;
15139 value = display_x_get_resource (dpyinfo,
15140 build_string ("synchronous"),
15141 build_string ("Synchronous"),
15142 Qnil, Qnil);
15143 if (STRINGP (value)
15144 && (!strcmp (SDATA (value), "true")
15145 || !strcmp (SDATA (value), "on")))
15146 XSynchronize (dpyinfo->display, True);
15147 }
15148
15149 UNBLOCK_INPUT;
15150
15151 return dpyinfo;
15152 }
15153 \f
15154 /* Get rid of display DPYINFO, assuming all frames are already gone,
15155 and without sending any more commands to the X server. */
15156
15157 void
15158 x_delete_display (dpyinfo)
15159 struct x_display_info *dpyinfo;
15160 {
15161 delete_keyboard_wait_descriptor (dpyinfo->connection);
15162
15163 /* Discard this display from x_display_name_list and x_display_list.
15164 We can't use Fdelq because that can quit. */
15165 if (! NILP (x_display_name_list)
15166 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
15167 x_display_name_list = XCDR (x_display_name_list);
15168 else
15169 {
15170 Lisp_Object tail;
15171
15172 tail = x_display_name_list;
15173 while (CONSP (tail) && CONSP (XCDR (tail)))
15174 {
15175 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
15176 {
15177 XSETCDR (tail, XCDR (XCDR (tail)));
15178 break;
15179 }
15180 tail = XCDR (tail);
15181 }
15182 }
15183
15184 if (next_noop_dpyinfo == dpyinfo)
15185 next_noop_dpyinfo = dpyinfo->next;
15186
15187 if (x_display_list == dpyinfo)
15188 x_display_list = dpyinfo->next;
15189 else
15190 {
15191 struct x_display_info *tail;
15192
15193 for (tail = x_display_list; tail; tail = tail->next)
15194 if (tail->next == dpyinfo)
15195 tail->next = tail->next->next;
15196 }
15197
15198 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
15199 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
15200 XrmDestroyDatabase (dpyinfo->xrdb);
15201 #endif
15202 #endif
15203 #ifdef MULTI_KBOARD
15204 if (--dpyinfo->kboard->reference_count == 0)
15205 delete_kboard (dpyinfo->kboard);
15206 #endif
15207 #ifdef HAVE_X_I18N
15208 if (dpyinfo->xim)
15209 xim_close_dpy (dpyinfo);
15210 #endif
15211
15212 xfree (dpyinfo->font_table);
15213 xfree (dpyinfo->x_id_name);
15214 xfree (dpyinfo->color_cells);
15215 xfree (dpyinfo);
15216 }
15217
15218 \f
15219 /* Set up use of X before we make the first connection. */
15220
15221 static struct redisplay_interface x_redisplay_interface =
15222 {
15223 x_produce_glyphs,
15224 x_write_glyphs,
15225 x_insert_glyphs,
15226 x_clear_end_of_line,
15227 x_scroll_run,
15228 x_after_update_window_line,
15229 x_update_window_begin,
15230 x_update_window_end,
15231 XTcursor_to,
15232 x_flush,
15233 x_clear_mouse_face,
15234 x_get_glyph_overhangs,
15235 x_fix_overlapping_area
15236 };
15237
15238 void
15239 x_initialize ()
15240 {
15241 rif = &x_redisplay_interface;
15242
15243 clear_frame_hook = x_clear_frame;
15244 ins_del_lines_hook = x_ins_del_lines;
15245 delete_glyphs_hook = x_delete_glyphs;
15246 ring_bell_hook = XTring_bell;
15247 reset_terminal_modes_hook = XTreset_terminal_modes;
15248 set_terminal_modes_hook = XTset_terminal_modes;
15249 update_begin_hook = x_update_begin;
15250 update_end_hook = x_update_end;
15251 set_terminal_window_hook = XTset_terminal_window;
15252 read_socket_hook = XTread_socket;
15253 frame_up_to_date_hook = XTframe_up_to_date;
15254 mouse_position_hook = XTmouse_position;
15255 frame_rehighlight_hook = XTframe_rehighlight;
15256 frame_raise_lower_hook = XTframe_raise_lower;
15257 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
15258 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
15259 redeem_scroll_bar_hook = XTredeem_scroll_bar;
15260 judge_scroll_bars_hook = XTjudge_scroll_bars;
15261 estimate_mode_line_height_hook = x_estimate_mode_line_height;
15262
15263 scroll_region_ok = 1; /* we'll scroll partial frames */
15264 char_ins_del_ok = 1;
15265 line_ins_del_ok = 1; /* we'll just blt 'em */
15266 fast_clear_end_of_line = 1; /* X does this well */
15267 memory_below_frame = 0; /* we don't remember what scrolls
15268 off the bottom */
15269 baud_rate = 19200;
15270
15271 x_noop_count = 0;
15272 last_tool_bar_item = -1;
15273 any_help_event_p = 0;
15274
15275 /* Try to use interrupt input; if we can't, then start polling. */
15276 Fset_input_mode (Qt, Qnil, Qt, Qnil);
15277
15278 #ifdef USE_X_TOOLKIT
15279 XtToolkitInitialize ();
15280
15281 Xt_app_con = XtCreateApplicationContext ();
15282
15283 /* Register a converter from strings to pixels, which uses
15284 Emacs' color allocation infrastructure. */
15285 XtAppSetTypeConverter (Xt_app_con,
15286 XtRString, XtRPixel, cvt_string_to_pixel,
15287 cvt_string_to_pixel_args,
15288 XtNumber (cvt_string_to_pixel_args),
15289 XtCacheByDisplay, cvt_pixel_dtor);
15290
15291 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
15292
15293 /* Install an asynchronous timer that processes Xt timeout events
15294 every 0.1s. This is necessary because some widget sets use
15295 timeouts internally, for example the LessTif menu bar, or the
15296 Xaw3d scroll bar. When Xt timouts aren't processed, these
15297 widgets don't behave normally. */
15298 {
15299 EMACS_TIME interval;
15300 EMACS_SET_SECS_USECS (interval, 0, 100000);
15301 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
15302 }
15303 #endif
15304
15305 #ifdef USE_TOOLKIT_SCROLL_BARS
15306 xaw3d_arrow_scroll = False;
15307 xaw3d_pick_top = True;
15308 #endif
15309
15310 /* Note that there is no real way portable across R3/R4 to get the
15311 original error handler. */
15312 XSetErrorHandler (x_error_handler);
15313 XSetIOErrorHandler (x_io_error_quitter);
15314
15315 /* Disable Window Change signals; they are handled by X events. */
15316 #ifdef SIGWINCH
15317 signal (SIGWINCH, SIG_DFL);
15318 #endif /* SIGWINCH */
15319
15320 signal (SIGPIPE, x_connection_signal);
15321
15322 #ifdef HAVE_X_SM
15323 x_session_initialize ();
15324 #endif
15325 }
15326
15327
15328 void
15329 syms_of_xterm ()
15330 {
15331 staticpro (&x_error_message_string);
15332 x_error_message_string = Qnil;
15333
15334 staticpro (&x_display_name_list);
15335 x_display_name_list = Qnil;
15336
15337 staticpro (&last_mouse_scroll_bar);
15338 last_mouse_scroll_bar = Qnil;
15339
15340 staticpro (&Qvendor_specific_keysyms);
15341 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
15342
15343 staticpro (&Qutf_8);
15344 Qutf_8 = intern ("utf-8");
15345 staticpro (&Qlatin_1);
15346 Qlatin_1 = intern ("latin-1");
15347
15348 staticpro (&last_mouse_press_frame);
15349 last_mouse_press_frame = Qnil;
15350
15351 help_echo = Qnil;
15352 staticpro (&help_echo);
15353 help_echo_object = Qnil;
15354 staticpro (&help_echo_object);
15355 help_echo_window = Qnil;
15356 staticpro (&help_echo_window);
15357 previous_help_echo = Qnil;
15358 staticpro (&previous_help_echo);
15359 help_echo_pos = -1;
15360
15361 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
15362 doc: /* *Non-nil means autoselect window with mouse pointer. */);
15363 mouse_autoselect_window = 0;
15364
15365 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
15366 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
15367 For example, if a block cursor is over a tab, it will be drawn as
15368 wide as that tab on the display. */);
15369 x_stretch_cursor_p = 0;
15370
15371 DEFVAR_BOOL ("x-use-underline-position-properties",
15372 &x_use_underline_position_properties,
15373 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
15374 nil means ignore them. If you encounter fonts with bogus
15375 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
15376 to 4.1, set this to nil. */);
15377 x_use_underline_position_properties = 1;
15378
15379 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
15380 doc: /* What X toolkit scroll bars Emacs uses.
15381 A value of nil means Emacs doesn't use X toolkit scroll bars.
15382 Otherwise, value is a symbol describing the X toolkit. */);
15383 #ifdef USE_TOOLKIT_SCROLL_BARS
15384 #ifdef USE_MOTIF
15385 Vx_toolkit_scroll_bars = intern ("motif");
15386 #elif defined HAVE_XAW3D
15387 Vx_toolkit_scroll_bars = intern ("xaw3d");
15388 #else
15389 Vx_toolkit_scroll_bars = intern ("xaw");
15390 #endif
15391 #else
15392 Vx_toolkit_scroll_bars = Qnil;
15393 #endif
15394
15395 staticpro (&last_mouse_motion_frame);
15396 last_mouse_motion_frame = Qnil;
15397
15398 Qmodifier_value = intern ("modifier-value");
15399 Qalt = intern ("alt");
15400 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
15401 Qhyper = intern ("hyper");
15402 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
15403 Qmeta = intern ("meta");
15404 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
15405 Qsuper = intern ("super");
15406 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
15407
15408 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
15409 doc: /* Which keys Emacs uses for the alt modifier.
15410 This should be one of the symbols `alt', `hyper', `meta', `super'.
15411 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
15412 is nil, which is the same as `alt'. */);
15413 Vx_alt_keysym = Qnil;
15414
15415 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
15416 doc: /* Which keys Emacs uses for the hyper modifier.
15417 This should be one of the symbols `alt', `hyper', `meta', `super'.
15418 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
15419 default is nil, which is the same as `hyper'. */);
15420 Vx_hyper_keysym = Qnil;
15421
15422 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
15423 doc: /* Which keys Emacs uses for the meta modifier.
15424 This should be one of the symbols `alt', `hyper', `meta', `super'.
15425 For example, `meta' means use the Meta_L and Meta_R keysyms. The
15426 default is nil, which is the same as `meta'. */);
15427 Vx_meta_keysym = Qnil;
15428
15429 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
15430 doc: /* Which keys Emacs uses for the super modifier.
15431 This should be one of the symbols `alt', `hyper', `meta', `super'.
15432 For example, `super' means use the Super_L and Super_R keysyms. The
15433 default is nil, which is the same as `super'. */);
15434 Vx_super_keysym = Qnil;
15435
15436 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
15437 doc: /* Hash table of character codes indexed by X keysym codes. */);
15438 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
15439 make_float (DEFAULT_REHASH_SIZE),
15440 make_float (DEFAULT_REHASH_THRESHOLD),
15441 Qnil, Qnil, Qnil);
15442 }
15443
15444 #endif /* HAVE_X_WINDOWS */