(x_estimate_mode_line_height): If `mode-line' face
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
24
25 #include <config.h>
26
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
29 #include <signal.h>
30
31 #include <stdio.h>
32
33 #ifdef HAVE_X_WINDOWS
34
35 #include "lisp.h"
36 #include "blockinput.h"
37
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
41
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
46
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
56
57 #include "systty.h"
58 #include "systime.h"
59
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
69
70 #include "charset.h"
71 #include "coding.h"
72 #include "ccl.h"
73 #include "frame.h"
74 #include "dispextern.h"
75 #include "fontset.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #if 0
80 #include "sink.h"
81 #include "sinkmask.h"
82 #endif /* ! 0 */
83 #include "gnu.h"
84 #include "disptab.h"
85 #include "buffer.h"
86 #include "window.h"
87 #include "keyboard.h"
88 #include "intervals.h"
89 #include "process.h"
90 #include "atimer.h"
91
92 #ifdef USE_X_TOOLKIT
93 #include <X11/Shell.h>
94 #endif
95
96 #ifdef HAVE_SYS_TIME_H
97 #include <sys/time.h>
98 #endif
99 #ifdef HAVE_UNISTD_H
100 #include <unistd.h>
101 #endif
102
103 #ifdef USE_X_TOOLKIT
104
105 extern void free_frame_menubar P_ ((struct frame *));
106 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
108
109 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110 #define HACK_EDITRES
111 extern void _XEditResCheckMessages ();
112 #endif /* not NO_EDITRES */
113
114 /* Include toolkit specific headers for the scroll bar widget. */
115
116 #ifdef USE_TOOLKIT_SCROLL_BARS
117 #if defined USE_MOTIF
118 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
119 #include <Xm/ScrollBar.h>
120 #include <Xm/ScrollBarP.h>
121 #else /* !USE_MOTIF i.e. use Xaw */
122
123 #ifdef HAVE_XAW3D
124 #include <X11/Xaw3d/Simple.h>
125 #include <X11/Xaw3d/Scrollbar.h>
126 #define ARROW_SCROLLBAR
127 #include <X11/Xaw3d/ScrollbarP.h>
128 #else /* !HAVE_XAW3D */
129 #include <X11/Xaw/Simple.h>
130 #include <X11/Xaw/Scrollbar.h>
131 #endif /* !HAVE_XAW3D */
132 #ifndef XtNpickTop
133 #define XtNpickTop "pickTop"
134 #endif /* !XtNpickTop */
135 #endif /* !USE_MOTIF */
136 #endif /* USE_TOOLKIT_SCROLL_BARS */
137
138 #endif /* USE_X_TOOLKIT */
139
140 #ifndef USE_X_TOOLKIT
141 #define x_any_window_to_frame x_window_to_frame
142 #define x_top_window_to_frame x_window_to_frame
143 #endif
144
145 #ifdef USE_X_TOOLKIT
146 #include "widget.h"
147 #ifndef XtNinitialState
148 #define XtNinitialState "initialState"
149 #endif
150 #endif
151
152 #ifndef min
153 #define min(a,b) ((a) < (b) ? (a) : (b))
154 #endif
155 #ifndef max
156 #define max(a,b) ((a) > (b) ? (a) : (b))
157 #endif
158
159 #define abs(x) ((x) < 0 ? -(x) : (x))
160
161 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
162
163 \f
164 /* Bitmaps for truncated lines. */
165
166 enum bitmap_type
167 {
168 NO_BITMAP,
169 LEFT_TRUNCATION_BITMAP,
170 RIGHT_TRUNCATION_BITMAP,
171 OVERLAY_ARROW_BITMAP,
172 CONTINUED_LINE_BITMAP,
173 CONTINUATION_LINE_BITMAP,
174 ZV_LINE_BITMAP
175 };
176
177 /* Bitmap drawn to indicate lines not displaying text if
178 `indicate-empty-lines' is non-nil. */
179
180 #define zv_width 8
181 #define zv_height 8
182 static unsigned char zv_bits[] = {
183 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
184
185 /* An arrow like this: `<-'. */
186
187 #define left_width 8
188 #define left_height 8
189 static unsigned char left_bits[] = {
190 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
191
192 /* Right truncation arrow bitmap `->'. */
193
194 #define right_width 8
195 #define right_height 8
196 static unsigned char right_bits[] = {
197 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
198
199 /* Marker for continued lines. */
200
201 #define continued_width 8
202 #define continued_height 8
203 static unsigned char continued_bits[] = {
204 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
205
206 /* Marker for continuation lines. */
207
208 #define continuation_width 8
209 #define continuation_height 8
210 static unsigned char continuation_bits[] = {
211 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
212
213 /* Overlay arrow bitmap. */
214
215 #if 0
216 /* A bomb. */
217 #define ov_width 8
218 #define ov_height 8
219 static unsigned char ov_bits[] = {
220 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
221 #else
222 /* A triangular arrow. */
223 #define ov_width 8
224 #define ov_height 8
225 static unsigned char ov_bits[] = {
226 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
227
228 #endif
229
230 extern Lisp_Object Qhelp_echo;
231
232 \f
233 /* Non-zero means Emacs uses toolkit scroll bars. */
234
235 int x_toolkit_scroll_bars_p;
236
237 /* If a string, XTread_socket generates an event to display that string.
238 (The display is done in read_char.) */
239
240 static Lisp_Object help_echo;
241 static Lisp_Object help_echo_window;
242 static Lisp_Object help_echo_object;
243 static int help_echo_pos;
244
245 /* Temporary variable for XTread_socket. */
246
247 static Lisp_Object previous_help_echo;
248
249 /* Non-zero means that a HELP_EVENT has been generated since Emacs
250 start. */
251
252 static int any_help_event_p;
253
254 /* Non-zero means draw block and hollow cursor as wide as the glyph
255 under it. For example, if a block cursor is over a tab, it will be
256 drawn as wide as that tab on the display. */
257
258 int x_stretch_cursor_p;
259
260 /* This is a chain of structures for all the X displays currently in
261 use. */
262
263 struct x_display_info *x_display_list;
264
265 /* This is a list of cons cells, each of the form (NAME
266 . FONT-LIST-CACHE), one for each element of x_display_list and in
267 the same order. NAME is the name of the frame. FONT-LIST-CACHE
268 records previous values returned by x-list-fonts. */
269
270 Lisp_Object x_display_name_list;
271
272 /* Frame being updated by update_frame. This is declared in term.c.
273 This is set by update_begin and looked at by all the XT functions.
274 It is zero while not inside an update. In that case, the XT
275 functions assume that `selected_frame' is the frame to apply to. */
276
277 extern struct frame *updating_frame;
278
279 extern int waiting_for_input;
280
281 /* This is a frame waiting to be auto-raised, within XTread_socket. */
282
283 struct frame *pending_autoraise_frame;
284
285 #ifdef USE_X_TOOLKIT
286 /* The application context for Xt use. */
287 XtAppContext Xt_app_con;
288 static String Xt_default_resources[] = {0};
289 #endif /* USE_X_TOOLKIT */
290
291 /* Nominal cursor position -- where to draw output.
292 HPOS and VPOS are window relative glyph matrix coordinates.
293 X and Y are window relative pixel coordinates. */
294
295 struct cursor_pos output_cursor;
296
297 /* Non-zero means user is interacting with a toolkit scroll bar. */
298
299 static int toolkit_scroll_bar_interaction;
300
301 /* Mouse movement.
302
303 Formerly, we used PointerMotionHintMask (in standard_event_mask)
304 so that we would have to call XQueryPointer after each MotionNotify
305 event to ask for another such event. However, this made mouse tracking
306 slow, and there was a bug that made it eventually stop.
307
308 Simply asking for MotionNotify all the time seems to work better.
309
310 In order to avoid asking for motion events and then throwing most
311 of them away or busy-polling the server for mouse positions, we ask
312 the server for pointer motion hints. This means that we get only
313 one event per group of mouse movements. "Groups" are delimited by
314 other kinds of events (focus changes and button clicks, for
315 example), or by XQueryPointer calls; when one of these happens, we
316 get another MotionNotify event the next time the mouse moves. This
317 is at least as efficient as getting motion events when mouse
318 tracking is on, and I suspect only negligibly worse when tracking
319 is off. */
320
321 /* Where the mouse was last time we reported a mouse event. */
322
323 FRAME_PTR last_mouse_frame;
324 static XRectangle last_mouse_glyph;
325 static Lisp_Object last_mouse_press_frame;
326
327 /* The scroll bar in which the last X motion event occurred.
328
329 If the last X motion event occurred in a scroll bar, we set this so
330 XTmouse_position can know whether to report a scroll bar motion or
331 an ordinary motion.
332
333 If the last X motion event didn't occur in a scroll bar, we set
334 this to Qnil, to tell XTmouse_position to return an ordinary motion
335 event. */
336
337 static Lisp_Object last_mouse_scroll_bar;
338
339 /* This is a hack. We would really prefer that XTmouse_position would
340 return the time associated with the position it returns, but there
341 doesn't seem to be any way to wrest the time-stamp from the server
342 along with the position query. So, we just keep track of the time
343 of the last movement we received, and return that in hopes that
344 it's somewhat accurate. */
345
346 static Time last_mouse_movement_time;
347
348 /* Incremented by XTread_socket whenever it really tries to read
349 events. */
350
351 #ifdef __STDC__
352 static int volatile input_signal_count;
353 #else
354 static int input_signal_count;
355 #endif
356
357 /* Used locally within XTread_socket. */
358
359 static int x_noop_count;
360
361 /* Initial values of argv and argc. */
362
363 extern char **initial_argv;
364 extern int initial_argc;
365
366 extern Lisp_Object Vcommand_line_args, Vsystem_name;
367
368 /* Tells if a window manager is present or not. */
369
370 extern Lisp_Object Vx_no_window_manager;
371
372 extern Lisp_Object Qface, Qmouse_face;
373
374 extern int errno;
375
376 /* A mask of extra modifier bits to put into every keyboard char. */
377
378 extern int extra_keyboard_modifiers;
379
380 static Lisp_Object Qvendor_specific_keysyms;
381
382 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
383 extern Lisp_Object x_icon_type P_ ((struct frame *));
384
385
386 /* Enumeration for overriding/changing the face to use for drawing
387 glyphs in x_draw_glyphs. */
388
389 enum draw_glyphs_face
390 {
391 DRAW_NORMAL_TEXT,
392 DRAW_INVERSE_VIDEO,
393 DRAW_CURSOR,
394 DRAW_MOUSE_FACE,
395 DRAW_IMAGE_RAISED,
396 DRAW_IMAGE_SUNKEN
397 };
398
399 static const XColor *x_color_cells P_ ((struct frame *, int *));
400 static void x_update_window_end P_ ((struct window *, int, int));
401 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
402 void x_delete_display P_ ((struct x_display_info *));
403 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
404 unsigned));
405 static int fast_find_position P_ ((struct window *, int, int *, int *,
406 int *, int *));
407 static void set_output_cursor P_ ((struct cursor_pos *));
408 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
409 int *, int *, int *));
410 static void note_mode_line_highlight P_ ((struct window *, int, int));
411 static void note_mouse_highlight P_ ((struct frame *, int, int));
412 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
413 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
414 static void show_mouse_face P_ ((struct x_display_info *,
415 enum draw_glyphs_face));
416 static int x_io_error_quitter P_ ((Display *));
417 int x_catch_errors P_ ((Display *));
418 void x_uncatch_errors P_ ((Display *, int));
419 void x_lower_frame P_ ((struct frame *));
420 void x_scroll_bar_clear P_ ((struct frame *));
421 int x_had_errors_p P_ ((Display *));
422 void x_wm_set_size_hint P_ ((struct frame *, long, int));
423 void x_raise_frame P_ ((struct frame *));
424 void x_set_window_size P_ ((struct frame *, int, int, int));
425 void x_wm_set_window_state P_ ((struct frame *, int));
426 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
427 void x_initialize P_ ((void));
428 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
429 static int x_compute_min_glyph_bounds P_ ((struct frame *));
430 static void x_draw_phys_cursor_glyph P_ ((struct window *,
431 struct glyph_row *,
432 enum draw_glyphs_face));
433 static void x_update_end P_ ((struct frame *));
434 static void XTframe_up_to_date P_ ((struct frame *));
435 static void XTreassert_line_highlight P_ ((int, int));
436 static void x_change_line_highlight P_ ((int, int, int, int));
437 static void XTset_terminal_modes P_ ((void));
438 static void XTreset_terminal_modes P_ ((void));
439 static void XTcursor_to P_ ((int, int, int, int));
440 static void x_write_glyphs P_ ((struct glyph *, int));
441 static void x_clear_end_of_line P_ ((int));
442 static void x_clear_frame P_ ((void));
443 static void x_clear_cursor P_ ((struct window *));
444 static void frame_highlight P_ ((struct frame *));
445 static void frame_unhighlight P_ ((struct frame *));
446 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
447 static void XTframe_rehighlight P_ ((struct frame *));
448 static void x_frame_rehighlight P_ ((struct x_display_info *));
449 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
450 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
451 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
452 XRectangle *));
453 static void expose_frame P_ ((struct frame *, int, int, int, int));
454 static void expose_window_tree P_ ((struct window *, XRectangle *));
455 static void expose_window P_ ((struct window *, XRectangle *));
456 static void expose_area P_ ((struct window *, struct glyph_row *,
457 XRectangle *, enum glyph_row_area));
458 static void expose_line P_ ((struct window *, struct glyph_row *,
459 XRectangle *));
460 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
461 static void x_update_window_cursor P_ ((struct window *, int));
462 static void x_erase_phys_cursor P_ ((struct window *));
463 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
464 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
465 enum bitmap_type));
466
467 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
468 GC, int));
469 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
470 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
471 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
472 static void x_flush P_ ((struct frame *f));
473 static void x_update_begin P_ ((struct frame *));
474 static void x_update_window_begin P_ ((struct window *));
475 static void x_draw_vertical_border P_ ((struct window *));
476 static void x_after_update_window_line P_ ((struct glyph_row *));
477 static INLINE void take_vertical_position_into_account P_ ((struct it *));
478 static void x_produce_stretch_glyph P_ ((struct it *));
479
480
481 /* Flush display of frame F, or of all frames if F is null. */
482
483 static void
484 x_flush (f)
485 struct frame *f;
486 {
487 BLOCK_INPUT;
488 if (f == NULL)
489 {
490 Lisp_Object rest, frame;
491 FOR_EACH_FRAME (rest, frame)
492 x_flush (XFRAME (frame));
493 }
494 else if (FRAME_X_P (f))
495 XFlush (FRAME_X_DISPLAY (f));
496 UNBLOCK_INPUT;
497 }
498
499
500 /* Remove calls to XFlush by defining XFlush to an empty replacement.
501 Calls to XFlush should be unnecessary because the X output buffer
502 is flushed automatically as needed by calls to XPending,
503 XNextEvent, or XWindowEvent according to the XFlush man page.
504 XTread_socket calls XPending. Removing XFlush improves
505 performance. */
506
507 #define XFlush(DISPLAY) (void) 0
508
509 \f
510 /***********************************************************************
511 Debugging
512 ***********************************************************************/
513
514 #if 0
515
516 /* This is a function useful for recording debugging information about
517 the sequence of occurrences in this file. */
518
519 struct record
520 {
521 char *locus;
522 int type;
523 };
524
525 struct record event_record[100];
526
527 int event_record_index;
528
529 record_event (locus, type)
530 char *locus;
531 int type;
532 {
533 if (event_record_index == sizeof (event_record) / sizeof (struct record))
534 event_record_index = 0;
535
536 event_record[event_record_index].locus = locus;
537 event_record[event_record_index].type = type;
538 event_record_index++;
539 }
540
541 #endif /* 0 */
542
543
544 \f
545 /* Return the struct x_display_info corresponding to DPY. */
546
547 struct x_display_info *
548 x_display_info_for_display (dpy)
549 Display *dpy;
550 {
551 struct x_display_info *dpyinfo;
552
553 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
554 if (dpyinfo->display == dpy)
555 return dpyinfo;
556
557 return 0;
558 }
559
560
561 \f
562 /***********************************************************************
563 Starting and ending an update
564 ***********************************************************************/
565
566 /* Start an update of frame F. This function is installed as a hook
567 for update_begin, i.e. it is called when update_begin is called.
568 This function is called prior to calls to x_update_window_begin for
569 each window being updated. Currently, there is nothing to do here
570 because all interesting stuff is done on a window basis. */
571
572 static void
573 x_update_begin (f)
574 struct frame *f;
575 {
576 /* Nothing to do. */
577 }
578
579
580 /* Start update of window W. Set the global variable updated_window
581 to the window being updated and set output_cursor to the cursor
582 position of W. */
583
584 static void
585 x_update_window_begin (w)
586 struct window *w;
587 {
588 struct frame *f = XFRAME (WINDOW_FRAME (w));
589 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
590
591 updated_window = w;
592 set_output_cursor (&w->cursor);
593
594 BLOCK_INPUT;
595
596 if (f == display_info->mouse_face_mouse_frame)
597 {
598 /* Don't do highlighting for mouse motion during the update. */
599 display_info->mouse_face_defer = 1;
600
601 /* If F needs to be redrawn, simply forget about any prior mouse
602 highlighting. */
603 if (FRAME_GARBAGED_P (f))
604 display_info->mouse_face_window = Qnil;
605
606 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
607 their mouse_face_p flag set, which means that they are always
608 unequal to rows in a desired matrix which never have that
609 flag set. So, rows containing mouse-face glyphs are never
610 scrolled, and we don't have to switch the mouse highlight off
611 here to prevent it from being scrolled. */
612
613 /* Can we tell that this update does not affect the window
614 where the mouse highlight is? If so, no need to turn off.
615 Likewise, don't do anything if the frame is garbaged;
616 in that case, the frame's current matrix that we would use
617 is all wrong, and we will redisplay that line anyway. */
618 if (!NILP (display_info->mouse_face_window)
619 && w == XWINDOW (display_info->mouse_face_window))
620 {
621 int i;
622
623 for (i = 0; i < w->desired_matrix->nrows; ++i)
624 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
625 break;
626
627 if (i < w->desired_matrix->nrows)
628 clear_mouse_face (display_info);
629 }
630 #endif /* 0 */
631 }
632
633 UNBLOCK_INPUT;
634 }
635
636
637 /* Draw a vertical window border to the right of window W if W doesn't
638 have vertical scroll bars. */
639
640 static void
641 x_draw_vertical_border (w)
642 struct window *w;
643 {
644 struct frame *f = XFRAME (WINDOW_FRAME (w));
645
646 /* Redraw borders between horizontally adjacent windows. Don't
647 do it for frames with vertical scroll bars because either the
648 right scroll bar of a window, or the left scroll bar of its
649 neighbor will suffice as a border. */
650 if (!WINDOW_RIGHTMOST_P (w)
651 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
652 {
653 int x0, x1, y0, y1;
654
655 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
656 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
657 y1 -= 1;
658
659 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
660 f->output_data.x->normal_gc, x1, y0, x1, y1);
661 }
662 }
663
664
665 /* End update of window W (which is equal to updated_window).
666
667 Draw vertical borders between horizontally adjacent windows, and
668 display W's cursor if CURSOR_ON_P is non-zero.
669
670 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
671 glyphs in mouse-face were overwritten. In that case we have to
672 make sure that the mouse-highlight is properly redrawn.
673
674 W may be a menu bar pseudo-window in case we don't have X toolkit
675 support. Such windows don't have a cursor, so don't display it
676 here. */
677
678 static void
679 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
680 struct window *w;
681 int cursor_on_p, mouse_face_overwritten_p;
682 {
683 if (!w->pseudo_window_p)
684 {
685 struct x_display_info *dpyinfo
686 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
687
688 BLOCK_INPUT;
689
690 /* If a row with mouse-face was overwritten, arrange for
691 XTframe_up_to_date to redisplay the mouse highlight. */
692 if (mouse_face_overwritten_p)
693 {
694 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
695 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
696 dpyinfo->mouse_face_window = Qnil;
697 }
698
699 if (cursor_on_p)
700 x_display_and_set_cursor (w, 1, output_cursor.hpos,
701 output_cursor.vpos,
702 output_cursor.x, output_cursor.y);
703
704 x_draw_vertical_border (w);
705 UNBLOCK_INPUT;
706 }
707
708 updated_window = NULL;
709 }
710
711
712 /* End update of frame F. This function is installed as a hook in
713 update_end. */
714
715 static void
716 x_update_end (f)
717 struct frame *f;
718 {
719 /* Mouse highlight may be displayed again. */
720 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
721
722 BLOCK_INPUT;
723 XFlush (FRAME_X_DISPLAY (f));
724 UNBLOCK_INPUT;
725 }
726
727
728 /* This function is called from various places in xdisp.c whenever a
729 complete update has been performed. The global variable
730 updated_window is not available here. */
731
732 static void
733 XTframe_up_to_date (f)
734 struct frame *f;
735 {
736 if (FRAME_X_P (f))
737 {
738 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
739
740 if (dpyinfo->mouse_face_deferred_gc
741 || f == dpyinfo->mouse_face_mouse_frame)
742 {
743 BLOCK_INPUT;
744 if (dpyinfo->mouse_face_mouse_frame)
745 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
746 dpyinfo->mouse_face_mouse_x,
747 dpyinfo->mouse_face_mouse_y);
748 dpyinfo->mouse_face_deferred_gc = 0;
749 UNBLOCK_INPUT;
750 }
751 }
752 }
753
754
755 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
756 arrow bitmaps, or clear the areas where they would be displayed
757 before DESIRED_ROW is made current. The window being updated is
758 found in updated_window. This function It is called from
759 update_window_line only if it is known that there are differences
760 between bitmaps to be drawn between current row and DESIRED_ROW. */
761
762 static void
763 x_after_update_window_line (desired_row)
764 struct glyph_row *desired_row;
765 {
766 struct window *w = updated_window;
767
768 xassert (w);
769
770 if (!desired_row->mode_line_p && !w->pseudo_window_p)
771 {
772 BLOCK_INPUT;
773 x_draw_row_bitmaps (w, desired_row);
774
775 /* When a window has disappeared, make sure that no rest of
776 full-width rows stays visible in the internal border. */
777 if (windows_or_buffers_changed)
778 {
779 struct frame *f = XFRAME (w->frame);
780 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
781 int height = desired_row->visible_height;
782 int x = (window_box_right (w, -1)
783 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
784 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
785
786 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
787 x, y, width, height, False);
788 }
789
790 UNBLOCK_INPUT;
791 }
792 }
793
794
795 /* Draw the bitmap WHICH in one of the areas to the left or right of
796 window W. ROW is the glyph row for which to display the bitmap; it
797 determines the vertical position at which the bitmap has to be
798 drawn. */
799
800 static void
801 x_draw_bitmap (w, row, which)
802 struct window *w;
803 struct glyph_row *row;
804 enum bitmap_type which;
805 {
806 struct frame *f = XFRAME (WINDOW_FRAME (w));
807 Display *display = FRAME_X_DISPLAY (f);
808 Window window = FRAME_X_WINDOW (f);
809 int x, y, wd, h, dy;
810 unsigned char *bits;
811 Pixmap pixmap;
812 GC gc = f->output_data.x->normal_gc;
813 struct face *face;
814 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
815
816 /* Must clip because of partially visible lines. */
817 x_clip_to_row (w, row, gc, 1);
818
819 switch (which)
820 {
821 case LEFT_TRUNCATION_BITMAP:
822 wd = left_width;
823 h = left_height;
824 bits = left_bits;
825 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
826 - wd
827 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
828 break;
829
830 case OVERLAY_ARROW_BITMAP:
831 wd = left_width;
832 h = left_height;
833 bits = ov_bits;
834 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
835 - wd
836 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
837 break;
838
839 case RIGHT_TRUNCATION_BITMAP:
840 wd = right_width;
841 h = right_height;
842 bits = right_bits;
843 x = window_box_right (w, -1);
844 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
845 break;
846
847 case CONTINUED_LINE_BITMAP:
848 wd = right_width;
849 h = right_height;
850 bits = continued_bits;
851 x = window_box_right (w, -1);
852 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
853 break;
854
855 case CONTINUATION_LINE_BITMAP:
856 wd = continuation_width;
857 h = continuation_height;
858 bits = continuation_bits;
859 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
860 - wd
861 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
862 break;
863
864 case ZV_LINE_BITMAP:
865 wd = zv_width;
866 h = zv_height;
867 bits = zv_bits;
868 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
869 - wd
870 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
871 break;
872
873 default:
874 abort ();
875 }
876
877 /* Convert to frame coordinates. Set dy to the offset in the row to
878 start drawing the bitmap. */
879 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
880 dy = (row->height - h) / 2;
881
882 /* Draw the bitmap. I believe these small pixmaps can be cached
883 by the server. */
884 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
885 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
886 face->foreground,
887 face->background, depth);
888 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
889 XFreePixmap (display, pixmap);
890 XSetClipMask (display, gc, None);
891 }
892
893
894 /* Draw flags bitmaps for glyph row ROW on window W. Call this
895 function with input blocked. */
896
897 static void
898 x_draw_row_bitmaps (w, row)
899 struct window *w;
900 struct glyph_row *row;
901 {
902 struct frame *f = XFRAME (w->frame);
903 enum bitmap_type bitmap;
904 struct face *face;
905 int header_line_height = -1;
906
907 xassert (interrupt_input_blocked);
908
909 /* If row is completely invisible, because of vscrolling, we
910 don't have to draw anything. */
911 if (row->visible_height <= 0)
912 return;
913
914 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
915 PREPARE_FACE_FOR_DISPLAY (f, face);
916
917 /* Decide which bitmap to draw at the left side. */
918 if (row->overlay_arrow_p)
919 bitmap = OVERLAY_ARROW_BITMAP;
920 else if (row->truncated_on_left_p)
921 bitmap = LEFT_TRUNCATION_BITMAP;
922 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
923 bitmap = CONTINUATION_LINE_BITMAP;
924 else if (row->indicate_empty_line_p)
925 bitmap = ZV_LINE_BITMAP;
926 else
927 bitmap = NO_BITMAP;
928
929 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
930 the flags area. */
931 if (bitmap == NO_BITMAP
932 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
933 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
934 {
935 /* If W has a vertical border to its left, don't draw over it. */
936 int border = ((XFASTINT (w->left) > 0
937 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
938 ? 1 : 0);
939 int left = window_box_left (w, -1);
940
941 if (header_line_height < 0)
942 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
943
944 /* In case the same realized face is used for bitmap areas and
945 for something displayed in the text (e.g. face `region' on
946 mono-displays, the fill style may have been changed to
947 FillSolid in x_draw_glyph_string_background. */
948 if (face->stipple)
949 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
950 else
951 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
952
953 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
954 face->gc,
955 (left
956 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
957 + border),
958 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
959 row->y)),
960 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
961 row->visible_height);
962 if (!face->stipple)
963 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
964 }
965
966 /* Draw the left bitmap. */
967 if (bitmap != NO_BITMAP)
968 x_draw_bitmap (w, row, bitmap);
969
970 /* Decide which bitmap to draw at the right side. */
971 if (row->truncated_on_right_p)
972 bitmap = RIGHT_TRUNCATION_BITMAP;
973 else if (row->continued_p)
974 bitmap = CONTINUED_LINE_BITMAP;
975 else
976 bitmap = NO_BITMAP;
977
978 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
979 the flags area. */
980 if (bitmap == NO_BITMAP
981 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
982 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
983 {
984 int right = window_box_right (w, -1);
985
986 if (header_line_height < 0)
987 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
988
989 /* In case the same realized face is used for bitmap areas and
990 for something displayed in the text (e.g. face `region' on
991 mono-displays, the fill style may have been changed to
992 FillSolid in x_draw_glyph_string_background. */
993 if (face->stipple)
994 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
995 else
996 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
997 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
998 face->gc,
999 right,
1000 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
1001 row->y)),
1002 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
1003 row->visible_height);
1004 if (!face->stipple)
1005 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1006 }
1007
1008 /* Draw the right bitmap. */
1009 if (bitmap != NO_BITMAP)
1010 x_draw_bitmap (w, row, bitmap);
1011 }
1012
1013 \f
1014 /***********************************************************************
1015 Line Highlighting
1016 ***********************************************************************/
1017
1018 /* External interface to control of standout mode. Not used for X
1019 frames. Aborts when called. */
1020
1021 static void
1022 XTreassert_line_highlight (new, vpos)
1023 int new, vpos;
1024 {
1025 abort ();
1026 }
1027
1028
1029 /* Call this when about to modify line at position VPOS and change
1030 whether it is highlighted. Not used for X frames. Aborts when
1031 called. */
1032
1033 static void
1034 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1035 int new_highlight, vpos, y, first_unused_hpos;
1036 {
1037 abort ();
1038 }
1039
1040
1041 /* This is called when starting Emacs and when restarting after
1042 suspend. When starting Emacs, no X window is mapped. And nothing
1043 must be done to Emacs's own window if it is suspended (though that
1044 rarely happens). */
1045
1046 static void
1047 XTset_terminal_modes ()
1048 {
1049 }
1050
1051 /* This is called when exiting or suspending Emacs. Exiting will make
1052 the X-windows go away, and suspending requires no action. */
1053
1054 static void
1055 XTreset_terminal_modes ()
1056 {
1057 }
1058
1059
1060 \f
1061 /***********************************************************************
1062 Output Cursor
1063 ***********************************************************************/
1064
1065 /* Set the global variable output_cursor to CURSOR. All cursor
1066 positions are relative to updated_window. */
1067
1068 static void
1069 set_output_cursor (cursor)
1070 struct cursor_pos *cursor;
1071 {
1072 output_cursor.hpos = cursor->hpos;
1073 output_cursor.vpos = cursor->vpos;
1074 output_cursor.x = cursor->x;
1075 output_cursor.y = cursor->y;
1076 }
1077
1078
1079 /* Set a nominal cursor position.
1080
1081 HPOS and VPOS are column/row positions in a window glyph matrix. X
1082 and Y are window text area relative pixel positions.
1083
1084 If this is done during an update, updated_window will contain the
1085 window that is being updated and the position is the future output
1086 cursor position for that window. If updated_window is null, use
1087 selected_window and display the cursor at the given position. */
1088
1089 static void
1090 XTcursor_to (vpos, hpos, y, x)
1091 int vpos, hpos, y, x;
1092 {
1093 struct window *w;
1094
1095 /* If updated_window is not set, work on selected_window. */
1096 if (updated_window)
1097 w = updated_window;
1098 else
1099 w = XWINDOW (selected_window);
1100
1101 /* Set the output cursor. */
1102 output_cursor.hpos = hpos;
1103 output_cursor.vpos = vpos;
1104 output_cursor.x = x;
1105 output_cursor.y = y;
1106
1107 /* If not called as part of an update, really display the cursor.
1108 This will also set the cursor position of W. */
1109 if (updated_window == NULL)
1110 {
1111 BLOCK_INPUT;
1112 x_display_cursor (w, 1, hpos, vpos, x, y);
1113 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1114 UNBLOCK_INPUT;
1115 }
1116 }
1117
1118
1119 \f
1120 /***********************************************************************
1121 Display Iterator
1122 ***********************************************************************/
1123
1124 /* Function prototypes of this page. */
1125
1126 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1127 struct glyph *,
1128 XChar2b *,
1129 int *));
1130 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1131 int, XChar2b *, int));
1132 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1133 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1134 static void x_append_glyph P_ ((struct it *));
1135 static void x_append_composite_glyph P_ ((struct it *));
1136 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1137 int, int, double));
1138 static void x_produce_glyphs P_ ((struct it *));
1139 static void x_produce_image_glyph P_ ((struct it *it));
1140
1141
1142 /* Return a pointer to per-char metric information in FONT of a
1143 character pointed by B which is a pointer to an XChar2b. */
1144
1145 #define PER_CHAR_METRIC(font, b) \
1146 ((font)->per_char \
1147 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1148 + (((font)->min_byte1 || (font)->max_byte1) \
1149 ? (((b)->byte1 - (font)->min_byte1) \
1150 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1151 : 0)) \
1152 : &((font)->max_bounds))
1153
1154
1155 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1156 is not contained in the font. */
1157
1158 static INLINE XCharStruct *
1159 x_per_char_metric (font, char2b)
1160 XFontStruct *font;
1161 XChar2b *char2b;
1162 {
1163 /* The result metric information. */
1164 XCharStruct *pcm = NULL;
1165
1166 xassert (font && char2b);
1167
1168 if (font->per_char != NULL)
1169 {
1170 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1171 {
1172 /* min_char_or_byte2 specifies the linear character index
1173 corresponding to the first element of the per_char array,
1174 max_char_or_byte2 is the index of the last character. A
1175 character with non-zero CHAR2B->byte1 is not in the font.
1176 A character with byte2 less than min_char_or_byte2 or
1177 greater max_char_or_byte2 is not in the font. */
1178 if (char2b->byte1 == 0
1179 && char2b->byte2 >= font->min_char_or_byte2
1180 && char2b->byte2 <= font->max_char_or_byte2)
1181 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1182 }
1183 else
1184 {
1185 /* If either min_byte1 or max_byte1 are nonzero, both
1186 min_char_or_byte2 and max_char_or_byte2 are less than
1187 256, and the 2-byte character index values corresponding
1188 to the per_char array element N (counting from 0) are:
1189
1190 byte1 = N/D + min_byte1
1191 byte2 = N\D + min_char_or_byte2
1192
1193 where:
1194
1195 D = max_char_or_byte2 - min_char_or_byte2 + 1
1196 / = integer division
1197 \ = integer modulus */
1198 if (char2b->byte1 >= font->min_byte1
1199 && char2b->byte1 <= font->max_byte1
1200 && char2b->byte2 >= font->min_char_or_byte2
1201 && char2b->byte2 <= font->max_char_or_byte2)
1202 {
1203 pcm = (font->per_char
1204 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1205 * (char2b->byte1 - font->min_byte1))
1206 + (char2b->byte2 - font->min_char_or_byte2));
1207 }
1208 }
1209 }
1210 else
1211 {
1212 /* If the per_char pointer is null, all glyphs between the first
1213 and last character indexes inclusive have the same
1214 information, as given by both min_bounds and max_bounds. */
1215 if (char2b->byte2 >= font->min_char_or_byte2
1216 && char2b->byte2 <= font->max_char_or_byte2)
1217 pcm = &font->max_bounds;
1218 }
1219
1220 return ((pcm == NULL
1221 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1222 ? NULL : pcm);
1223 }
1224
1225
1226 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1227 the two-byte form of C. Encoding is returned in *CHAR2B. */
1228
1229 static INLINE void
1230 x_encode_char (c, char2b, font_info)
1231 int c;
1232 XChar2b *char2b;
1233 struct font_info *font_info;
1234 {
1235 int charset = CHAR_CHARSET (c);
1236 XFontStruct *font = font_info->font;
1237
1238 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1239 This may be either a program in a special encoder language or a
1240 fixed encoding. */
1241 if (font_info->font_encoder)
1242 {
1243 /* It's a program. */
1244 struct ccl_program *ccl = font_info->font_encoder;
1245
1246 if (CHARSET_DIMENSION (charset) == 1)
1247 {
1248 ccl->reg[0] = charset;
1249 ccl->reg[1] = char2b->byte2;
1250 }
1251 else
1252 {
1253 ccl->reg[0] = charset;
1254 ccl->reg[1] = char2b->byte1;
1255 ccl->reg[2] = char2b->byte2;
1256 }
1257
1258 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1259
1260 /* We assume that MSBs are appropriately set/reset by CCL
1261 program. */
1262 if (font->max_byte1 == 0) /* 1-byte font */
1263 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1264 else
1265 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1266 }
1267 else if (font_info->encoding[charset])
1268 {
1269 /* Fixed encoding scheme. See fontset.h for the meaning of the
1270 encoding numbers. */
1271 int enc = font_info->encoding[charset];
1272
1273 if ((enc == 1 || enc == 2)
1274 && CHARSET_DIMENSION (charset) == 2)
1275 char2b->byte1 |= 0x80;
1276
1277 if (enc == 1 || enc == 3)
1278 char2b->byte2 |= 0x80;
1279 }
1280 }
1281
1282
1283 /* Get face and two-byte form of character C in face FACE_ID on frame
1284 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1285 means we want to display multibyte text. Value is a pointer to a
1286 realized face that is ready for display. */
1287
1288 static INLINE struct face *
1289 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1290 struct frame *f;
1291 int c, face_id;
1292 XChar2b *char2b;
1293 int multibyte_p;
1294 {
1295 struct face *face = FACE_FROM_ID (f, face_id);
1296
1297 if (!multibyte_p)
1298 {
1299 /* Unibyte case. We don't have to encode, but we have to make
1300 sure to use a face suitable for unibyte. */
1301 char2b->byte1 = 0;
1302 char2b->byte2 = c;
1303 face_id = FACE_FOR_CHAR (f, face, c);
1304 face = FACE_FROM_ID (f, face_id);
1305 }
1306 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1307 {
1308 /* Case of ASCII in a face known to fit ASCII. */
1309 char2b->byte1 = 0;
1310 char2b->byte2 = c;
1311 }
1312 else
1313 {
1314 int c1, c2, charset;
1315
1316 /* Split characters into bytes. If c2 is -1 afterwards, C is
1317 really a one-byte character so that byte1 is zero. */
1318 SPLIT_CHAR (c, charset, c1, c2);
1319 if (c2 > 0)
1320 char2b->byte1 = c1, char2b->byte2 = c2;
1321 else
1322 char2b->byte1 = 0, char2b->byte2 = c1;
1323
1324 /* Maybe encode the character in *CHAR2B. */
1325 if (face->font != NULL)
1326 {
1327 struct font_info *font_info
1328 = FONT_INFO_FROM_ID (f, face->font_info_id);
1329 if (font_info)
1330 x_encode_char (c, char2b, font_info);
1331 }
1332 }
1333
1334 /* Make sure X resources of the face are allocated. */
1335 xassert (face != NULL);
1336 PREPARE_FACE_FOR_DISPLAY (f, face);
1337
1338 return face;
1339 }
1340
1341
1342 /* Get face and two-byte form of character glyph GLYPH on frame F.
1343 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1344 a pointer to a realized face that is ready for display. */
1345
1346 static INLINE struct face *
1347 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1348 struct frame *f;
1349 struct glyph *glyph;
1350 XChar2b *char2b;
1351 int *two_byte_p;
1352 {
1353 struct face *face;
1354
1355 xassert (glyph->type == CHAR_GLYPH);
1356 face = FACE_FROM_ID (f, glyph->face_id);
1357
1358 if (two_byte_p)
1359 *two_byte_p = 0;
1360
1361 if (!glyph->multibyte_p)
1362 {
1363 /* Unibyte case. We don't have to encode, but we have to make
1364 sure to use a face suitable for unibyte. */
1365 char2b->byte1 = 0;
1366 char2b->byte2 = glyph->u.ch;
1367 }
1368 else if (glyph->u.ch < 128
1369 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1370 {
1371 /* Case of ASCII in a face known to fit ASCII. */
1372 char2b->byte1 = 0;
1373 char2b->byte2 = glyph->u.ch;
1374 }
1375 else
1376 {
1377 int c1, c2, charset;
1378
1379 /* Split characters into bytes. If c2 is -1 afterwards, C is
1380 really a one-byte character so that byte1 is zero. */
1381 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1382 if (c2 > 0)
1383 char2b->byte1 = c1, char2b->byte2 = c2;
1384 else
1385 char2b->byte1 = 0, char2b->byte2 = c1;
1386
1387 /* Maybe encode the character in *CHAR2B. */
1388 if (charset != CHARSET_ASCII)
1389 {
1390 struct font_info *font_info
1391 = FONT_INFO_FROM_ID (f, face->font_info_id);
1392 if (font_info)
1393 {
1394 x_encode_char (glyph->u.ch, char2b, font_info);
1395 if (two_byte_p)
1396 *two_byte_p
1397 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1398 }
1399 }
1400 }
1401
1402 /* Make sure X resources of the face are allocated. */
1403 xassert (face != NULL);
1404 PREPARE_FACE_FOR_DISPLAY (f, face);
1405 return face;
1406 }
1407
1408
1409 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1410 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1411
1412 static INLINE void
1413 x_append_glyph (it)
1414 struct it *it;
1415 {
1416 struct glyph *glyph;
1417 enum glyph_row_area area = it->area;
1418
1419 xassert (it->glyph_row);
1420 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1421
1422 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1423 if (glyph < it->glyph_row->glyphs[area + 1])
1424 {
1425 glyph->charpos = CHARPOS (it->position);
1426 glyph->object = it->object;
1427 glyph->pixel_width = it->pixel_width;
1428 glyph->voffset = it->voffset;
1429 glyph->type = CHAR_GLYPH;
1430 glyph->multibyte_p = it->multibyte_p;
1431 glyph->left_box_line_p = it->start_of_box_run_p;
1432 glyph->right_box_line_p = it->end_of_box_run_p;
1433 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1434 || it->phys_descent > it->descent);
1435 glyph->padding_p = 0;
1436 glyph->glyph_not_available_p = it->glyph_not_available_p;
1437 glyph->face_id = it->face_id;
1438 glyph->u.ch = it->char_to_display;
1439 ++it->glyph_row->used[area];
1440 }
1441 }
1442
1443 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1444 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1445
1446 static INLINE void
1447 x_append_composite_glyph (it)
1448 struct it *it;
1449 {
1450 struct glyph *glyph;
1451 enum glyph_row_area area = it->area;
1452
1453 xassert (it->glyph_row);
1454
1455 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1456 if (glyph < it->glyph_row->glyphs[area + 1])
1457 {
1458 glyph->charpos = CHARPOS (it->position);
1459 glyph->object = it->object;
1460 glyph->pixel_width = it->pixel_width;
1461 glyph->voffset = it->voffset;
1462 glyph->type = COMPOSITE_GLYPH;
1463 glyph->multibyte_p = it->multibyte_p;
1464 glyph->left_box_line_p = it->start_of_box_run_p;
1465 glyph->right_box_line_p = it->end_of_box_run_p;
1466 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1467 || it->phys_descent > it->descent);
1468 glyph->padding_p = 0;
1469 glyph->glyph_not_available_p = 0;
1470 glyph->face_id = it->face_id;
1471 glyph->u.cmp_id = it->cmp_id;
1472 ++it->glyph_row->used[area];
1473 }
1474 }
1475
1476
1477 /* Change IT->ascent and IT->height according to the setting of
1478 IT->voffset. */
1479
1480 static INLINE void
1481 take_vertical_position_into_account (it)
1482 struct it *it;
1483 {
1484 if (it->voffset)
1485 {
1486 if (it->voffset < 0)
1487 /* Increase the ascent so that we can display the text higher
1488 in the line. */
1489 it->ascent += abs (it->voffset);
1490 else
1491 /* Increase the descent so that we can display the text lower
1492 in the line. */
1493 it->descent += it->voffset;
1494 }
1495 }
1496
1497
1498 /* Produce glyphs/get display metrics for the image IT is loaded with.
1499 See the description of struct display_iterator in dispextern.h for
1500 an overview of struct display_iterator. */
1501
1502 static void
1503 x_produce_image_glyph (it)
1504 struct it *it;
1505 {
1506 struct image *img;
1507 struct face *face;
1508
1509 xassert (it->what == IT_IMAGE);
1510
1511 face = FACE_FROM_ID (it->f, it->face_id);
1512 img = IMAGE_FROM_ID (it->f, it->image_id);
1513 xassert (img);
1514
1515 /* Make sure X resources of the face and image are loaded. */
1516 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1517 prepare_image_for_display (it->f, img);
1518
1519 it->ascent = it->phys_ascent = image_ascent (img, face);
1520 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1521 it->pixel_width = img->width + 2 * img->margin;
1522
1523 it->nglyphs = 1;
1524
1525 if (face->box != FACE_NO_BOX)
1526 {
1527 it->ascent += face->box_line_width;
1528 it->descent += face->box_line_width;
1529
1530 if (it->start_of_box_run_p)
1531 it->pixel_width += face->box_line_width;
1532 if (it->end_of_box_run_p)
1533 it->pixel_width += face->box_line_width;
1534 }
1535
1536 take_vertical_position_into_account (it);
1537
1538 if (it->glyph_row)
1539 {
1540 struct glyph *glyph;
1541 enum glyph_row_area area = it->area;
1542
1543 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1544 if (glyph < it->glyph_row->glyphs[area + 1])
1545 {
1546 glyph->charpos = CHARPOS (it->position);
1547 glyph->object = it->object;
1548 glyph->pixel_width = it->pixel_width;
1549 glyph->voffset = it->voffset;
1550 glyph->type = IMAGE_GLYPH;
1551 glyph->multibyte_p = it->multibyte_p;
1552 glyph->left_box_line_p = it->start_of_box_run_p;
1553 glyph->right_box_line_p = it->end_of_box_run_p;
1554 glyph->overlaps_vertically_p = 0;
1555 glyph->padding_p = 0;
1556 glyph->glyph_not_available_p = 0;
1557 glyph->face_id = it->face_id;
1558 glyph->u.img_id = img->id;
1559 ++it->glyph_row->used[area];
1560 }
1561 }
1562 }
1563
1564
1565 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1566 of the glyph, WIDTH and HEIGHT are the width and height of the
1567 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1568 ascent of the glyph (0 <= ASCENT <= 1). */
1569
1570 static void
1571 x_append_stretch_glyph (it, object, width, height, ascent)
1572 struct it *it;
1573 Lisp_Object object;
1574 int width, height;
1575 double ascent;
1576 {
1577 struct glyph *glyph;
1578 enum glyph_row_area area = it->area;
1579
1580 xassert (ascent >= 0 && ascent <= 1);
1581
1582 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1583 if (glyph < it->glyph_row->glyphs[area + 1])
1584 {
1585 glyph->charpos = CHARPOS (it->position);
1586 glyph->object = object;
1587 glyph->pixel_width = width;
1588 glyph->voffset = it->voffset;
1589 glyph->type = STRETCH_GLYPH;
1590 glyph->multibyte_p = it->multibyte_p;
1591 glyph->left_box_line_p = it->start_of_box_run_p;
1592 glyph->right_box_line_p = it->end_of_box_run_p;
1593 glyph->overlaps_vertically_p = 0;
1594 glyph->padding_p = 0;
1595 glyph->glyph_not_available_p = 0;
1596 glyph->face_id = it->face_id;
1597 glyph->u.stretch.ascent = height * ascent;
1598 glyph->u.stretch.height = height;
1599 ++it->glyph_row->used[area];
1600 }
1601 }
1602
1603
1604 /* Produce a stretch glyph for iterator IT. IT->object is the value
1605 of the glyph property displayed. The value must be a list
1606 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1607 being recognized:
1608
1609 1. `:width WIDTH' specifies that the space should be WIDTH *
1610 canonical char width wide. WIDTH may be an integer or floating
1611 point number.
1612
1613 2. `:relative-width FACTOR' specifies that the width of the stretch
1614 should be computed from the width of the first character having the
1615 `glyph' property, and should be FACTOR times that width.
1616
1617 3. `:align-to HPOS' specifies that the space should be wide enough
1618 to reach HPOS, a value in canonical character units.
1619
1620 Exactly one of the above pairs must be present.
1621
1622 4. `:height HEIGHT' specifies that the height of the stretch produced
1623 should be HEIGHT, measured in canonical character units.
1624
1625 5. `:relative-height FACTOR' specifies that the height of the the
1626 stretch should be FACTOR times the height of the characters having
1627 the glyph property.
1628
1629 Either none or exactly one of 4 or 5 must be present.
1630
1631 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1632 of the stretch should be used for the ascent of the stretch.
1633 ASCENT must be in the range 0 <= ASCENT <= 100. */
1634
1635 #define NUMVAL(X) \
1636 ((INTEGERP (X) || FLOATP (X)) \
1637 ? XFLOATINT (X) \
1638 : - 1)
1639
1640
1641 static void
1642 x_produce_stretch_glyph (it)
1643 struct it *it;
1644 {
1645 /* (space :width WIDTH :height HEIGHT. */
1646 #if GLYPH_DEBUG
1647 extern Lisp_Object Qspace;
1648 #endif
1649 extern Lisp_Object QCwidth, QCheight, QCascent;
1650 extern Lisp_Object QCrelative_width, QCrelative_height;
1651 extern Lisp_Object QCalign_to;
1652 Lisp_Object prop, plist;
1653 double width = 0, height = 0, ascent = 0;
1654 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1655 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1656
1657 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1658
1659 /* List should start with `space'. */
1660 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1661 plist = XCDR (it->object);
1662
1663 /* Compute the width of the stretch. */
1664 if (prop = Fplist_get (plist, QCwidth),
1665 NUMVAL (prop) > 0)
1666 /* Absolute width `:width WIDTH' specified and valid. */
1667 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1668 else if (prop = Fplist_get (plist, QCrelative_width),
1669 NUMVAL (prop) > 0)
1670 {
1671 /* Relative width `:relative-width FACTOR' specified and valid.
1672 Compute the width of the characters having the `glyph'
1673 property. */
1674 struct it it2;
1675 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1676
1677 it2 = *it;
1678 if (it->multibyte_p)
1679 {
1680 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1681 - IT_BYTEPOS (*it));
1682 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1683 }
1684 else
1685 it2.c = *p, it2.len = 1;
1686
1687 it2.glyph_row = NULL;
1688 it2.what = IT_CHARACTER;
1689 x_produce_glyphs (&it2);
1690 width = NUMVAL (prop) * it2.pixel_width;
1691 }
1692 else if (prop = Fplist_get (plist, QCalign_to),
1693 NUMVAL (prop) > 0)
1694 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1695 else
1696 /* Nothing specified -> width defaults to canonical char width. */
1697 width = CANON_X_UNIT (it->f);
1698
1699 /* Compute height. */
1700 if (prop = Fplist_get (plist, QCheight),
1701 NUMVAL (prop) > 0)
1702 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1703 else if (prop = Fplist_get (plist, QCrelative_height),
1704 NUMVAL (prop) > 0)
1705 height = FONT_HEIGHT (font) * NUMVAL (prop);
1706 else
1707 height = FONT_HEIGHT (font);
1708
1709 /* Compute percentage of height used for ascent. If
1710 `:ascent ASCENT' is present and valid, use that. Otherwise,
1711 derive the ascent from the font in use. */
1712 if (prop = Fplist_get (plist, QCascent),
1713 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1714 ascent = NUMVAL (prop) / 100.0;
1715 else
1716 ascent = (double) font->ascent / FONT_HEIGHT (font);
1717
1718 if (width <= 0)
1719 width = 1;
1720 if (height <= 0)
1721 height = 1;
1722
1723 if (it->glyph_row)
1724 {
1725 Lisp_Object object = it->stack[it->sp - 1].string;
1726 if (!STRINGP (object))
1727 object = it->w->buffer;
1728 x_append_stretch_glyph (it, object, width, height, ascent);
1729 }
1730
1731 it->pixel_width = width;
1732 it->ascent = it->phys_ascent = height * ascent;
1733 it->descent = it->phys_descent = height - it->ascent;
1734 it->nglyphs = 1;
1735
1736 if (face->box != FACE_NO_BOX)
1737 {
1738 it->ascent += face->box_line_width;
1739 it->descent += face->box_line_width;
1740
1741 if (it->start_of_box_run_p)
1742 it->pixel_width += face->box_line_width;
1743 if (it->end_of_box_run_p)
1744 it->pixel_width += face->box_line_width;
1745 }
1746
1747 take_vertical_position_into_account (it);
1748 }
1749
1750 /* Return proper value to be used as baseline offset of font that has
1751 ASCENT and DESCENT to draw characters by the font at the vertical
1752 center of the line of frame F.
1753
1754 Here, out task is to find the value of BOFF in the following figure;
1755
1756 -------------------------+-----------+-
1757 -+-+---------+-+ | |
1758 | | | | | |
1759 | | | | F_ASCENT F_HEIGHT
1760 | | | ASCENT | |
1761 HEIGHT | | | | |
1762 | | |-|-+------+-----------|------- baseline
1763 | | | | BOFF | |
1764 | |---------|-+-+ | |
1765 | | | DESCENT | |
1766 -+-+---------+-+ F_DESCENT |
1767 -------------------------+-----------+-
1768
1769 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1770 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1771 DESCENT = FONT->descent
1772 HEIGHT = FONT_HEIGHT (FONT)
1773 F_DESCENT = (F->output_data.x->font->descent
1774 - F->output_data.x->baseline_offset)
1775 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1776 */
1777
1778 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1779 ((FONT)->descent \
1780 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1781 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1782 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1783
1784 /* Produce glyphs/get display metrics for the display element IT is
1785 loaded with. See the description of struct display_iterator in
1786 dispextern.h for an overview of struct display_iterator. */
1787
1788 static void
1789 x_produce_glyphs (it)
1790 struct it *it;
1791 {
1792 it->glyph_not_available_p = 0;
1793
1794 if (it->what == IT_CHARACTER)
1795 {
1796 XChar2b char2b;
1797 XFontStruct *font;
1798 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1799 XCharStruct *pcm;
1800 int font_not_found_p;
1801 struct font_info *font_info;
1802 int boff; /* baseline offset */
1803 /* We may change it->multibyte_p upon unibyte<->multibyte
1804 conversion. So, save the current value now and restore it
1805 later.
1806
1807 Note: It seems that we don't have to record multibyte_p in
1808 struct glyph because the character code itself tells if or
1809 not the character is multibyte. Thus, in the future, we must
1810 consider eliminating the field `multibyte_p' in the struct
1811 glyph.
1812 */
1813 int saved_multibyte_p = it->multibyte_p;
1814
1815 /* Maybe translate single-byte characters to multibyte, or the
1816 other way. */
1817 it->char_to_display = it->c;
1818 if (!ASCII_BYTE_P (it->c))
1819 {
1820 if (unibyte_display_via_language_environment
1821 && SINGLE_BYTE_CHAR_P (it->c)
1822 && (it->c >= 0240
1823 || !NILP (Vnonascii_translation_table)))
1824 {
1825 it->char_to_display = unibyte_char_to_multibyte (it->c);
1826 it->multibyte_p = 1;
1827 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1828 face = FACE_FROM_ID (it->f, it->face_id);
1829 }
1830 else if (!SINGLE_BYTE_CHAR_P (it->c)
1831 && !it->multibyte_p)
1832 {
1833 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1834 it->multibyte_p = 0;
1835 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1836 face = FACE_FROM_ID (it->f, it->face_id);
1837 }
1838 }
1839
1840 /* Get font to use. Encode IT->char_to_display. */
1841 x_get_char_face_and_encoding (it->f, it->char_to_display,
1842 it->face_id, &char2b,
1843 it->multibyte_p);
1844 font = face->font;
1845
1846 /* When no suitable font found, use the default font. */
1847 font_not_found_p = font == NULL;
1848 if (font_not_found_p)
1849 {
1850 font = FRAME_FONT (it->f);
1851 boff = it->f->output_data.x->baseline_offset;
1852 font_info = NULL;
1853 }
1854 else
1855 {
1856 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1857 boff = font_info->baseline_offset;
1858 if (font_info->vertical_centering)
1859 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1860 }
1861
1862 if (it->char_to_display >= ' '
1863 && (!it->multibyte_p || it->char_to_display < 128))
1864 {
1865 /* Either unibyte or ASCII. */
1866 int stretched_p;
1867
1868 it->nglyphs = 1;
1869
1870 pcm = x_per_char_metric (font, &char2b);
1871 it->ascent = font->ascent + boff;
1872 it->descent = font->descent - boff;
1873
1874 if (pcm)
1875 {
1876 it->phys_ascent = pcm->ascent + boff;
1877 it->phys_descent = pcm->descent - boff;
1878 it->pixel_width = pcm->width;
1879 }
1880 else
1881 {
1882 it->glyph_not_available_p = 1;
1883 it->phys_ascent = font->ascent + boff;
1884 it->phys_descent = font->descent - boff;
1885 it->pixel_width = FONT_WIDTH (font);
1886 }
1887
1888 /* If this is a space inside a region of text with
1889 `space-width' property, change its width. */
1890 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1891 if (stretched_p)
1892 it->pixel_width *= XFLOATINT (it->space_width);
1893
1894 /* If face has a box, add the box thickness to the character
1895 height. If character has a box line to the left and/or
1896 right, add the box line width to the character's width. */
1897 if (face->box != FACE_NO_BOX)
1898 {
1899 int thick = face->box_line_width;
1900
1901 it->ascent += thick;
1902 it->descent += thick;
1903
1904 if (it->start_of_box_run_p)
1905 it->pixel_width += thick;
1906 if (it->end_of_box_run_p)
1907 it->pixel_width += thick;
1908 }
1909
1910 /* If face has an overline, add the height of the overline
1911 (1 pixel) and a 1 pixel margin to the character height. */
1912 if (face->overline_p)
1913 it->ascent += 2;
1914
1915 take_vertical_position_into_account (it);
1916
1917 /* If we have to actually produce glyphs, do it. */
1918 if (it->glyph_row)
1919 {
1920 if (stretched_p)
1921 {
1922 /* Translate a space with a `space-width' property
1923 into a stretch glyph. */
1924 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1925 x_append_stretch_glyph (it, it->object, it->pixel_width,
1926 it->ascent + it->descent, ascent);
1927 }
1928 else
1929 x_append_glyph (it);
1930
1931 /* If characters with lbearing or rbearing are displayed
1932 in this line, record that fact in a flag of the
1933 glyph row. This is used to optimize X output code. */
1934 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1935 it->glyph_row->contains_overlapping_glyphs_p = 1;
1936 }
1937 }
1938 else if (it->char_to_display == '\n')
1939 {
1940 /* A newline has no width but we need the height of the line. */
1941 it->pixel_width = 0;
1942 it->nglyphs = 0;
1943 it->ascent = it->phys_ascent = font->ascent + boff;
1944 it->descent = it->phys_descent = font->descent - boff;
1945
1946 if (face->box != FACE_NO_BOX)
1947 {
1948 int thick = face->box_line_width;
1949 it->ascent += thick;
1950 it->descent += thick;
1951 }
1952 }
1953 else if (it->char_to_display == '\t')
1954 {
1955 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1956 int x = it->current_x + it->continuation_lines_width;
1957 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1958
1959 /* If the distance from the current position to the next tab
1960 stop is less than a canonical character width, use the
1961 tab stop after that. */
1962 if (next_tab_x - x < CANON_X_UNIT (it->f))
1963 next_tab_x += tab_width;
1964
1965 it->pixel_width = next_tab_x - x;
1966 it->nglyphs = 1;
1967 it->ascent = it->phys_ascent = font->ascent + boff;
1968 it->descent = it->phys_descent = font->descent - boff;
1969
1970 if (it->glyph_row)
1971 {
1972 double ascent = (double) it->ascent / (it->ascent + it->descent);
1973 x_append_stretch_glyph (it, it->object, it->pixel_width,
1974 it->ascent + it->descent, ascent);
1975 }
1976 }
1977 else
1978 {
1979 /* A multi-byte character. Assume that the display width of the
1980 character is the width of the character multiplied by the
1981 width of the font. */
1982
1983 /* If we found a font, this font should give us the right
1984 metrics. If we didn't find a font, use the frame's
1985 default font and calculate the width of the character
1986 from the charset width; this is what old redisplay code
1987 did. */
1988 pcm = x_per_char_metric (font, &char2b);
1989 if (font_not_found_p || !pcm)
1990 {
1991 int charset = CHAR_CHARSET (it->char_to_display);
1992
1993 it->glyph_not_available_p = 1;
1994 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1995 * CHARSET_WIDTH (charset));
1996 it->phys_ascent = font->ascent + boff;
1997 it->phys_descent = font->descent - boff;
1998 }
1999 else
2000 {
2001 it->pixel_width = pcm->width;
2002 it->phys_ascent = pcm->ascent + boff;
2003 it->phys_descent = pcm->descent - boff;
2004 if (it->glyph_row
2005 && (pcm->lbearing < 0
2006 || pcm->rbearing > pcm->width))
2007 it->glyph_row->contains_overlapping_glyphs_p = 1;
2008 }
2009 it->nglyphs = 1;
2010 it->ascent = font->ascent + boff;
2011 it->descent = font->descent - boff;
2012 if (face->box != FACE_NO_BOX)
2013 {
2014 int thick = face->box_line_width;
2015 it->ascent += thick;
2016 it->descent += thick;
2017
2018 if (it->start_of_box_run_p)
2019 it->pixel_width += thick;
2020 if (it->end_of_box_run_p)
2021 it->pixel_width += thick;
2022 }
2023
2024 /* If face has an overline, add the height of the overline
2025 (1 pixel) and a 1 pixel margin to the character height. */
2026 if (face->overline_p)
2027 it->ascent += 2;
2028
2029 take_vertical_position_into_account (it);
2030
2031 if (it->glyph_row)
2032 x_append_glyph (it);
2033 }
2034 it->multibyte_p = saved_multibyte_p;
2035 }
2036 else if (it->what == IT_COMPOSITION)
2037 {
2038 /* Note: A composition is represented as one glyph in the
2039 glyph matrix. There are no padding glyphs. */
2040 XChar2b char2b;
2041 XFontStruct *font;
2042 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2043 XCharStruct *pcm;
2044 int font_not_found_p;
2045 struct font_info *font_info;
2046 int boff; /* baseline offset */
2047 struct composition *cmp = composition_table[it->cmp_id];
2048
2049 /* Maybe translate single-byte characters to multibyte. */
2050 it->char_to_display = it->c;
2051 if (unibyte_display_via_language_environment
2052 && SINGLE_BYTE_CHAR_P (it->c)
2053 && (it->c >= 0240
2054 || (it->c >= 0200
2055 && !NILP (Vnonascii_translation_table))))
2056 {
2057 it->char_to_display = unibyte_char_to_multibyte (it->c);
2058 }
2059
2060 /* Get face and font to use. Encode IT->char_to_display. */
2061 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2062 face = FACE_FROM_ID (it->f, it->face_id);
2063 x_get_char_face_and_encoding (it->f, it->char_to_display,
2064 it->face_id, &char2b, it->multibyte_p);
2065 font = face->font;
2066
2067 /* When no suitable font found, use the default font. */
2068 font_not_found_p = font == NULL;
2069 if (font_not_found_p)
2070 {
2071 font = FRAME_FONT (it->f);
2072 boff = it->f->output_data.x->baseline_offset;
2073 font_info = NULL;
2074 }
2075 else
2076 {
2077 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2078 boff = font_info->baseline_offset;
2079 if (font_info->vertical_centering)
2080 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2081 }
2082
2083 /* There are no padding glyphs, so there is only one glyph to
2084 produce for the composition. Important is that pixel_width,
2085 ascent and descent are the values of what is drawn by
2086 draw_glyphs (i.e. the values of the overall glyphs composed). */
2087 it->nglyphs = 1;
2088
2089 /* If we have not yet calculated pixel size data of glyphs of
2090 the composition for the current face font, calculate them
2091 now. Theoretically, we have to check all fonts for the
2092 glyphs, but that requires much time and memory space. So,
2093 here we check only the font of the first glyph. This leads
2094 to incorrect display very rarely, and C-l (recenter) can
2095 correct the display anyway. */
2096 if (cmp->font != (void *) font)
2097 {
2098 /* Ascent and descent of the font of the first character of
2099 this composition (adjusted by baseline offset). Ascent
2100 and descent of overall glyphs should not be less than
2101 them respectively. */
2102 int font_ascent = font->ascent + boff;
2103 int font_descent = font->descent - boff;
2104 /* Bounding box of the overall glyphs. */
2105 int leftmost, rightmost, lowest, highest;
2106 int i, width, ascent, descent;
2107
2108 cmp->font = (void *) font;
2109
2110 /* Initialize the bounding box. */
2111 pcm = x_per_char_metric (font, &char2b);
2112 if (pcm)
2113 {
2114 width = pcm->width;
2115 ascent = pcm->ascent;
2116 descent = pcm->descent;
2117 }
2118 else
2119 {
2120 width = FONT_WIDTH (font);
2121 ascent = font->ascent;
2122 descent = font->descent;
2123 }
2124
2125 rightmost = width;
2126 lowest = - descent + boff;
2127 highest = ascent + boff;
2128 leftmost = 0;
2129
2130 if (font_info
2131 && font_info->default_ascent
2132 && CHAR_TABLE_P (Vuse_default_ascent)
2133 && !NILP (Faref (Vuse_default_ascent,
2134 make_number (it->char_to_display))))
2135 highest = font_info->default_ascent + boff;
2136
2137 /* Draw the first glyph at the normal position. It may be
2138 shifted to right later if some other glyphs are drawn at
2139 the left. */
2140 cmp->offsets[0] = 0;
2141 cmp->offsets[1] = boff;
2142
2143 /* Set cmp->offsets for the remaining glyphs. */
2144 for (i = 1; i < cmp->glyph_len; i++)
2145 {
2146 int left, right, btm, top;
2147 int ch = COMPOSITION_GLYPH (cmp, i);
2148 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2149
2150 face = FACE_FROM_ID (it->f, face_id);
2151 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2152 it->multibyte_p);
2153 font = face->font;
2154 if (font == NULL)
2155 {
2156 font = FRAME_FONT (it->f);
2157 boff = it->f->output_data.x->baseline_offset;
2158 font_info = NULL;
2159 }
2160 else
2161 {
2162 font_info
2163 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2164 boff = font_info->baseline_offset;
2165 if (font_info->vertical_centering)
2166 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2167 }
2168
2169 pcm = x_per_char_metric (font, &char2b);
2170 if (pcm)
2171 {
2172 width = pcm->width;
2173 ascent = pcm->ascent;
2174 descent = pcm->descent;
2175 }
2176 else
2177 {
2178 width = FONT_WIDTH (font);
2179 ascent = font->ascent;
2180 descent = font->descent;
2181 }
2182
2183 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2184 {
2185 /* Relative composition with or without
2186 alternate chars. */
2187 left = (leftmost + rightmost - width) / 2;
2188 btm = - descent + boff;
2189 if (font_info && font_info->relative_compose
2190 && (! CHAR_TABLE_P (Vignore_relative_composition)
2191 || NILP (Faref (Vignore_relative_composition,
2192 make_number (ch)))))
2193 {
2194
2195 if (- descent >= font_info->relative_compose)
2196 /* One extra pixel between two glyphs. */
2197 btm = highest + 1;
2198 else if (ascent <= 0)
2199 /* One extra pixel between two glyphs. */
2200 btm = lowest - 1 - ascent - descent;
2201 }
2202 }
2203 else
2204 {
2205 /* A composition rule is specified by an integer
2206 value that encodes global and new reference
2207 points (GREF and NREF). GREF and NREF are
2208 specified by numbers as below:
2209
2210 0---1---2 -- ascent
2211 | |
2212 | |
2213 | |
2214 9--10--11 -- center
2215 | |
2216 ---3---4---5--- baseline
2217 | |
2218 6---7---8 -- descent
2219 */
2220 int rule = COMPOSITION_RULE (cmp, i);
2221 int gref, nref, grefx, grefy, nrefx, nrefy;
2222
2223 COMPOSITION_DECODE_RULE (rule, gref, nref);
2224 grefx = gref % 3, nrefx = nref % 3;
2225 grefy = gref / 3, nrefy = nref / 3;
2226
2227 left = (leftmost
2228 + grefx * (rightmost - leftmost) / 2
2229 - nrefx * width / 2);
2230 btm = ((grefy == 0 ? highest
2231 : grefy == 1 ? 0
2232 : grefy == 2 ? lowest
2233 : (highest + lowest) / 2)
2234 - (nrefy == 0 ? ascent + descent
2235 : nrefy == 1 ? descent - boff
2236 : nrefy == 2 ? 0
2237 : (ascent + descent) / 2));
2238 }
2239
2240 cmp->offsets[i * 2] = left;
2241 cmp->offsets[i * 2 + 1] = btm + descent;
2242
2243 /* Update the bounding box of the overall glyphs. */
2244 right = left + width;
2245 top = btm + descent + ascent;
2246 if (left < leftmost)
2247 leftmost = left;
2248 if (right > rightmost)
2249 rightmost = right;
2250 if (top > highest)
2251 highest = top;
2252 if (btm < lowest)
2253 lowest = btm;
2254 }
2255
2256 /* If there are glyphs whose x-offsets are negative,
2257 shift all glyphs to the right and make all x-offsets
2258 non-negative. */
2259 if (leftmost < 0)
2260 {
2261 for (i = 0; i < cmp->glyph_len; i++)
2262 cmp->offsets[i * 2] -= leftmost;
2263 rightmost -= leftmost;
2264 }
2265
2266 cmp->pixel_width = rightmost;
2267 cmp->ascent = highest;
2268 cmp->descent = - lowest;
2269 if (cmp->ascent < font_ascent)
2270 cmp->ascent = font_ascent;
2271 if (cmp->descent < font_descent)
2272 cmp->descent = font_descent;
2273 }
2274
2275 it->pixel_width = cmp->pixel_width;
2276 it->ascent = it->phys_ascent = cmp->ascent;
2277 it->descent = it->phys_descent = cmp->descent;
2278
2279 if (face->box != FACE_NO_BOX)
2280 {
2281 int thick = face->box_line_width;
2282 it->ascent += thick;
2283 it->descent += thick;
2284
2285 if (it->start_of_box_run_p)
2286 it->pixel_width += thick;
2287 if (it->end_of_box_run_p)
2288 it->pixel_width += thick;
2289 }
2290
2291 /* If face has an overline, add the height of the overline
2292 (1 pixel) and a 1 pixel margin to the character height. */
2293 if (face->overline_p)
2294 it->ascent += 2;
2295
2296 take_vertical_position_into_account (it);
2297
2298 if (it->glyph_row)
2299 x_append_composite_glyph (it);
2300 }
2301 else if (it->what == IT_IMAGE)
2302 x_produce_image_glyph (it);
2303 else if (it->what == IT_STRETCH)
2304 x_produce_stretch_glyph (it);
2305
2306 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2307 because this isn't true for images with `:ascent 100'. */
2308 xassert (it->ascent >= 0 && it->descent >= 0);
2309 if (it->area == TEXT_AREA)
2310 it->current_x += it->pixel_width;
2311
2312 it->descent += it->extra_line_spacing;
2313
2314 it->max_ascent = max (it->max_ascent, it->ascent);
2315 it->max_descent = max (it->max_descent, it->descent);
2316 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2317 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2318 }
2319
2320
2321 /* Estimate the pixel height of the mode or top line on frame F.
2322 FACE_ID specifies what line's height to estimate. */
2323
2324 int
2325 x_estimate_mode_line_height (f, face_id)
2326 struct frame *f;
2327 enum face_id face_id;
2328 {
2329 int height = FONT_HEIGHT (FRAME_FONT (f));
2330
2331 /* This function is called so early when Emacs starts that the face
2332 cache and mode line face are not yet initialized. */
2333 if (FRAME_FACE_CACHE (f))
2334 {
2335 struct face *face = FACE_FROM_ID (f, face_id);
2336 if (face)
2337 {
2338 if (face->font)
2339 height = FONT_HEIGHT (face->font);
2340 height += 2 * face->box_line_width;
2341 }
2342 }
2343
2344 return height;
2345 }
2346
2347 \f
2348 /***********************************************************************
2349 Glyph display
2350 ***********************************************************************/
2351
2352 /* A sequence of glyphs to be drawn in the same face.
2353
2354 This data structure is not really completely X specific, so it
2355 could possibly, at least partially, be useful for other systems. It
2356 is currently not part of the external redisplay interface because
2357 it's not clear what other systems will need. */
2358
2359 struct glyph_string
2360 {
2361 /* X-origin of the string. */
2362 int x;
2363
2364 /* Y-origin and y-position of the base line of this string. */
2365 int y, ybase;
2366
2367 /* The width of the string, not including a face extension. */
2368 int width;
2369
2370 /* The width of the string, including a face extension. */
2371 int background_width;
2372
2373 /* The height of this string. This is the height of the line this
2374 string is drawn in, and can be different from the height of the
2375 font the string is drawn in. */
2376 int height;
2377
2378 /* Number of pixels this string overwrites in front of its x-origin.
2379 This number is zero if the string has an lbearing >= 0; it is
2380 -lbearing, if the string has an lbearing < 0. */
2381 int left_overhang;
2382
2383 /* Number of pixels this string overwrites past its right-most
2384 nominal x-position, i.e. x + width. Zero if the string's
2385 rbearing is <= its nominal width, rbearing - width otherwise. */
2386 int right_overhang;
2387
2388 /* The frame on which the glyph string is drawn. */
2389 struct frame *f;
2390
2391 /* The window on which the glyph string is drawn. */
2392 struct window *w;
2393
2394 /* X display and window for convenience. */
2395 Display *display;
2396 Window window;
2397
2398 /* The glyph row for which this string was built. It determines the
2399 y-origin and height of the string. */
2400 struct glyph_row *row;
2401
2402 /* The area within row. */
2403 enum glyph_row_area area;
2404
2405 /* Characters to be drawn, and number of characters. */
2406 XChar2b *char2b;
2407 int nchars;
2408
2409 /* A face-override for drawing cursors, mouse face and similar. */
2410 enum draw_glyphs_face hl;
2411
2412 /* Face in which this string is to be drawn. */
2413 struct face *face;
2414
2415 /* Font in which this string is to be drawn. */
2416 XFontStruct *font;
2417
2418 /* Font info for this string. */
2419 struct font_info *font_info;
2420
2421 /* Non-null means this string describes (part of) a composition.
2422 All characters from char2b are drawn composed. */
2423 struct composition *cmp;
2424
2425 /* Index of this glyph string's first character in the glyph
2426 definition of CMP. If this is zero, this glyph string describes
2427 the first character of a composition. */
2428 int gidx;
2429
2430 /* 1 means this glyph strings face has to be drawn to the right end
2431 of the window's drawing area. */
2432 unsigned extends_to_end_of_line_p : 1;
2433
2434 /* 1 means the background of this string has been drawn. */
2435 unsigned background_filled_p : 1;
2436
2437 /* 1 means glyph string must be drawn with 16-bit functions. */
2438 unsigned two_byte_p : 1;
2439
2440 /* 1 means that the original font determined for drawing this glyph
2441 string could not be loaded. The member `font' has been set to
2442 the frame's default font in this case. */
2443 unsigned font_not_found_p : 1;
2444
2445 /* 1 means that the face in which this glyph string is drawn has a
2446 stipple pattern. */
2447 unsigned stippled_p : 1;
2448
2449 /* 1 means only the foreground of this glyph string must be drawn,
2450 and we should use the physical height of the line this glyph
2451 string appears in as clip rect. */
2452 unsigned for_overlaps_p : 1;
2453
2454 /* The GC to use for drawing this glyph string. */
2455 GC gc;
2456
2457 /* A pointer to the first glyph in the string. This glyph
2458 corresponds to char2b[0]. Needed to draw rectangles if
2459 font_not_found_p is 1. */
2460 struct glyph *first_glyph;
2461
2462 /* Image, if any. */
2463 struct image *img;
2464
2465 struct glyph_string *next, *prev;
2466 };
2467
2468
2469 #if 0
2470
2471 static void
2472 x_dump_glyph_string (s)
2473 struct glyph_string *s;
2474 {
2475 fprintf (stderr, "glyph string\n");
2476 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2477 s->x, s->y, s->width, s->height);
2478 fprintf (stderr, " ybase = %d\n", s->ybase);
2479 fprintf (stderr, " hl = %d\n", s->hl);
2480 fprintf (stderr, " left overhang = %d, right = %d\n",
2481 s->left_overhang, s->right_overhang);
2482 fprintf (stderr, " nchars = %d\n", s->nchars);
2483 fprintf (stderr, " extends to end of line = %d\n",
2484 s->extends_to_end_of_line_p);
2485 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2486 fprintf (stderr, " bg width = %d\n", s->background_width);
2487 }
2488
2489 #endif /* GLYPH_DEBUG */
2490
2491
2492
2493 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2494 struct glyph_string **,
2495 struct glyph_string *,
2496 struct glyph_string *));
2497 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2498 struct glyph_string **,
2499 struct glyph_string *,
2500 struct glyph_string *));
2501 static void x_append_glyph_string P_ ((struct glyph_string **,
2502 struct glyph_string **,
2503 struct glyph_string *));
2504 static int x_left_overwritten P_ ((struct glyph_string *));
2505 static int x_left_overwriting P_ ((struct glyph_string *));
2506 static int x_right_overwritten P_ ((struct glyph_string *));
2507 static int x_right_overwriting P_ ((struct glyph_string *));
2508 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2509 int));
2510 static void x_init_glyph_string P_ ((struct glyph_string *,
2511 XChar2b *, struct window *,
2512 struct glyph_row *,
2513 enum glyph_row_area, int,
2514 enum draw_glyphs_face));
2515 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2516 enum glyph_row_area, int, int,
2517 enum draw_glyphs_face, int *, int *, int));
2518 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2519 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2520 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2521 int));
2522 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2523 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2524 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2525 static void x_draw_glyph_string P_ ((struct glyph_string *));
2526 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2527 static void x_set_cursor_gc P_ ((struct glyph_string *));
2528 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2529 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2530 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2531 int *, int *));
2532 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2533 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2534 unsigned long *, double, int));
2535 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2536 double, int, unsigned long));
2537 static void x_setup_relief_colors P_ ((struct glyph_string *));
2538 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2539 static void x_draw_image_relief P_ ((struct glyph_string *));
2540 static void x_draw_image_foreground P_ ((struct glyph_string *));
2541 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2542 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2543 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2544 int, int, int));
2545 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2546 int, int, int, int, XRectangle *));
2547 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2548 int, int, int, XRectangle *));
2549 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2550 enum glyph_row_area));
2551 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2552 struct glyph_row *,
2553 enum glyph_row_area, int, int));
2554
2555 #if GLYPH_DEBUG
2556 static void x_check_font P_ ((struct frame *, XFontStruct *));
2557 #endif
2558
2559
2560 /* Append the list of glyph strings with head H and tail T to the list
2561 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2562
2563 static INLINE void
2564 x_append_glyph_string_lists (head, tail, h, t)
2565 struct glyph_string **head, **tail;
2566 struct glyph_string *h, *t;
2567 {
2568 if (h)
2569 {
2570 if (*head)
2571 (*tail)->next = h;
2572 else
2573 *head = h;
2574 h->prev = *tail;
2575 *tail = t;
2576 }
2577 }
2578
2579
2580 /* Prepend the list of glyph strings with head H and tail T to the
2581 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2582 result. */
2583
2584 static INLINE void
2585 x_prepend_glyph_string_lists (head, tail, h, t)
2586 struct glyph_string **head, **tail;
2587 struct glyph_string *h, *t;
2588 {
2589 if (h)
2590 {
2591 if (*head)
2592 (*head)->prev = t;
2593 else
2594 *tail = t;
2595 t->next = *head;
2596 *head = h;
2597 }
2598 }
2599
2600
2601 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2602 Set *HEAD and *TAIL to the resulting list. */
2603
2604 static INLINE void
2605 x_append_glyph_string (head, tail, s)
2606 struct glyph_string **head, **tail;
2607 struct glyph_string *s;
2608 {
2609 s->next = s->prev = NULL;
2610 x_append_glyph_string_lists (head, tail, s, s);
2611 }
2612
2613
2614 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2615 face. */
2616
2617 static void
2618 x_set_cursor_gc (s)
2619 struct glyph_string *s;
2620 {
2621 if (s->font == FRAME_FONT (s->f)
2622 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2623 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2624 && !s->cmp)
2625 s->gc = s->f->output_data.x->cursor_gc;
2626 else
2627 {
2628 /* Cursor on non-default face: must merge. */
2629 XGCValues xgcv;
2630 unsigned long mask;
2631
2632 xgcv.background = s->f->output_data.x->cursor_pixel;
2633 xgcv.foreground = s->face->background;
2634
2635 /* If the glyph would be invisible, try a different foreground. */
2636 if (xgcv.foreground == xgcv.background)
2637 xgcv.foreground = s->face->foreground;
2638 if (xgcv.foreground == xgcv.background)
2639 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2640 if (xgcv.foreground == xgcv.background)
2641 xgcv.foreground = s->face->foreground;
2642
2643 /* Make sure the cursor is distinct from text in this face. */
2644 if (xgcv.background == s->face->background
2645 && xgcv.foreground == s->face->foreground)
2646 {
2647 xgcv.background = s->face->foreground;
2648 xgcv.foreground = s->face->background;
2649 }
2650
2651 IF_DEBUG (x_check_font (s->f, s->font));
2652 xgcv.font = s->font->fid;
2653 xgcv.graphics_exposures = False;
2654 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2655
2656 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2657 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2658 mask, &xgcv);
2659 else
2660 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2661 = XCreateGC (s->display, s->window, mask, &xgcv);
2662
2663 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2664 }
2665 }
2666
2667
2668 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2669
2670 static void
2671 x_set_mouse_face_gc (s)
2672 struct glyph_string *s;
2673 {
2674 int face_id;
2675 struct face *face;
2676
2677 /* What face has to be used for the mouse face? */
2678 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2679 face = FACE_FROM_ID (s->f, face_id);
2680 if (s->first_glyph->type == CHAR_GLYPH)
2681 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2682 else
2683 face_id = FACE_FOR_CHAR (s->f, face, 0);
2684 s->face = FACE_FROM_ID (s->f, face_id);
2685 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2686
2687 /* If font in this face is same as S->font, use it. */
2688 if (s->font == s->face->font)
2689 s->gc = s->face->gc;
2690 else
2691 {
2692 /* Otherwise construct scratch_cursor_gc with values from FACE
2693 but font FONT. */
2694 XGCValues xgcv;
2695 unsigned long mask;
2696
2697 xgcv.background = s->face->background;
2698 xgcv.foreground = s->face->foreground;
2699 IF_DEBUG (x_check_font (s->f, s->font));
2700 xgcv.font = s->font->fid;
2701 xgcv.graphics_exposures = False;
2702 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2703
2704 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2705 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2706 mask, &xgcv);
2707 else
2708 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2709 = XCreateGC (s->display, s->window, mask, &xgcv);
2710
2711 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2712 }
2713
2714 xassert (s->gc != 0);
2715 }
2716
2717
2718 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2719 Faces to use in the mode line have already been computed when the
2720 matrix was built, so there isn't much to do, here. */
2721
2722 static INLINE void
2723 x_set_mode_line_face_gc (s)
2724 struct glyph_string *s;
2725 {
2726 s->gc = s->face->gc;
2727 }
2728
2729
2730 /* Set S->gc of glyph string S for drawing that glyph string. Set
2731 S->stippled_p to a non-zero value if the face of S has a stipple
2732 pattern. */
2733
2734 static INLINE void
2735 x_set_glyph_string_gc (s)
2736 struct glyph_string *s;
2737 {
2738 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2739
2740 if (s->hl == DRAW_NORMAL_TEXT)
2741 {
2742 s->gc = s->face->gc;
2743 s->stippled_p = s->face->stipple != 0;
2744 }
2745 else if (s->hl == DRAW_INVERSE_VIDEO)
2746 {
2747 x_set_mode_line_face_gc (s);
2748 s->stippled_p = s->face->stipple != 0;
2749 }
2750 else if (s->hl == DRAW_CURSOR)
2751 {
2752 x_set_cursor_gc (s);
2753 s->stippled_p = 0;
2754 }
2755 else if (s->hl == DRAW_MOUSE_FACE)
2756 {
2757 x_set_mouse_face_gc (s);
2758 s->stippled_p = s->face->stipple != 0;
2759 }
2760 else if (s->hl == DRAW_IMAGE_RAISED
2761 || s->hl == DRAW_IMAGE_SUNKEN)
2762 {
2763 s->gc = s->face->gc;
2764 s->stippled_p = s->face->stipple != 0;
2765 }
2766 else
2767 {
2768 s->gc = s->face->gc;
2769 s->stippled_p = s->face->stipple != 0;
2770 }
2771
2772 /* GC must have been set. */
2773 xassert (s->gc != 0);
2774 }
2775
2776
2777 /* Return in *R the clipping rectangle for glyph string S. */
2778
2779 static void
2780 x_get_glyph_string_clip_rect (s, r)
2781 struct glyph_string *s;
2782 XRectangle *r;
2783 {
2784 if (s->row->full_width_p)
2785 {
2786 /* Draw full-width. X coordinates are relative to S->w->left. */
2787 int canon_x = CANON_X_UNIT (s->f);
2788
2789 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2790 r->width = XFASTINT (s->w->width) * canon_x;
2791
2792 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2793 {
2794 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2795 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2796 r->x -= width;
2797 }
2798
2799 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2800
2801 /* Unless displaying a mode or menu bar line, which are always
2802 fully visible, clip to the visible part of the row. */
2803 if (s->w->pseudo_window_p)
2804 r->height = s->row->visible_height;
2805 else
2806 r->height = s->height;
2807 }
2808 else
2809 {
2810 /* This is a text line that may be partially visible. */
2811 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2812 r->width = window_box_width (s->w, s->area);
2813 r->height = s->row->visible_height;
2814 }
2815
2816 /* Don't use S->y for clipping because it doesn't take partially
2817 visible lines into account. For example, it can be negative for
2818 partially visible lines at the top of a window. */
2819 if (!s->row->full_width_p
2820 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2821 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2822 else
2823 r->y = max (0, s->row->y);
2824
2825 /* If drawing a tool-bar window, draw it over the internal border
2826 at the top of the window. */
2827 if (s->w == XWINDOW (s->f->tool_bar_window))
2828 r->y -= s->f->output_data.x->internal_border_width;
2829
2830 /* If S draws overlapping rows, it's sufficient to use the top and
2831 bottom of the window for clipping because this glyph string
2832 intentionally draws over other lines. */
2833 if (s->for_overlaps_p)
2834 {
2835 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2836 r->height = window_text_bottom_y (s->w) - r->y;
2837 }
2838
2839 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2840 }
2841
2842
2843 /* Set clipping for output of glyph string S. S may be part of a mode
2844 line or menu if we don't have X toolkit support. */
2845
2846 static INLINE void
2847 x_set_glyph_string_clipping (s)
2848 struct glyph_string *s;
2849 {
2850 XRectangle r;
2851 x_get_glyph_string_clip_rect (s, &r);
2852 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2853 }
2854
2855
2856 /* Compute left and right overhang of glyph string S. If S is a glyph
2857 string for a composition, assume overhangs don't exist. */
2858
2859 static INLINE void
2860 x_compute_glyph_string_overhangs (s)
2861 struct glyph_string *s;
2862 {
2863 if (s->cmp == NULL
2864 && s->first_glyph->type == CHAR_GLYPH)
2865 {
2866 XCharStruct cs;
2867 int direction, font_ascent, font_descent;
2868 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2869 &font_ascent, &font_descent, &cs);
2870 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2871 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2872 }
2873 }
2874
2875
2876 /* Compute overhangs and x-positions for glyph string S and its
2877 predecessors, or successors. X is the starting x-position for S.
2878 BACKWARD_P non-zero means process predecessors. */
2879
2880 static void
2881 x_compute_overhangs_and_x (s, x, backward_p)
2882 struct glyph_string *s;
2883 int x;
2884 int backward_p;
2885 {
2886 if (backward_p)
2887 {
2888 while (s)
2889 {
2890 x_compute_glyph_string_overhangs (s);
2891 x -= s->width;
2892 s->x = x;
2893 s = s->prev;
2894 }
2895 }
2896 else
2897 {
2898 while (s)
2899 {
2900 x_compute_glyph_string_overhangs (s);
2901 s->x = x;
2902 x += s->width;
2903 s = s->next;
2904 }
2905 }
2906 }
2907
2908
2909 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2910 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2911 assumed to be zero. */
2912
2913 static void
2914 x_get_glyph_overhangs (glyph, f, left, right)
2915 struct glyph *glyph;
2916 struct frame *f;
2917 int *left, *right;
2918 {
2919 *left = *right = 0;
2920
2921 if (glyph->type == CHAR_GLYPH)
2922 {
2923 XFontStruct *font;
2924 struct face *face;
2925 struct font_info *font_info;
2926 XChar2b char2b;
2927 XCharStruct *pcm;
2928
2929 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2930 font = face->font;
2931 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2932 if (font
2933 && (pcm = x_per_char_metric (font, &char2b)))
2934 {
2935 if (pcm->rbearing > pcm->width)
2936 *right = pcm->rbearing - pcm->width;
2937 if (pcm->lbearing < 0)
2938 *left = -pcm->lbearing;
2939 }
2940 }
2941 }
2942
2943
2944 /* Return the index of the first glyph preceding glyph string S that
2945 is overwritten by S because of S's left overhang. Value is -1
2946 if no glyphs are overwritten. */
2947
2948 static int
2949 x_left_overwritten (s)
2950 struct glyph_string *s;
2951 {
2952 int k;
2953
2954 if (s->left_overhang)
2955 {
2956 int x = 0, i;
2957 struct glyph *glyphs = s->row->glyphs[s->area];
2958 int first = s->first_glyph - glyphs;
2959
2960 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2961 x -= glyphs[i].pixel_width;
2962
2963 k = i + 1;
2964 }
2965 else
2966 k = -1;
2967
2968 return k;
2969 }
2970
2971
2972 /* Return the index of the first glyph preceding glyph string S that
2973 is overwriting S because of its right overhang. Value is -1 if no
2974 glyph in front of S overwrites S. */
2975
2976 static int
2977 x_left_overwriting (s)
2978 struct glyph_string *s;
2979 {
2980 int i, k, x;
2981 struct glyph *glyphs = s->row->glyphs[s->area];
2982 int first = s->first_glyph - glyphs;
2983
2984 k = -1;
2985 x = 0;
2986 for (i = first - 1; i >= 0; --i)
2987 {
2988 int left, right;
2989 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2990 if (x + right > 0)
2991 k = i;
2992 x -= glyphs[i].pixel_width;
2993 }
2994
2995 return k;
2996 }
2997
2998
2999 /* Return the index of the last glyph following glyph string S that is
3000 not overwritten by S because of S's right overhang. Value is -1 if
3001 no such glyph is found. */
3002
3003 static int
3004 x_right_overwritten (s)
3005 struct glyph_string *s;
3006 {
3007 int k = -1;
3008
3009 if (s->right_overhang)
3010 {
3011 int x = 0, i;
3012 struct glyph *glyphs = s->row->glyphs[s->area];
3013 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3014 int end = s->row->used[s->area];
3015
3016 for (i = first; i < end && s->right_overhang > x; ++i)
3017 x += glyphs[i].pixel_width;
3018
3019 k = i;
3020 }
3021
3022 return k;
3023 }
3024
3025
3026 /* Return the index of the last glyph following glyph string S that
3027 overwrites S because of its left overhang. Value is negative
3028 if no such glyph is found. */
3029
3030 static int
3031 x_right_overwriting (s)
3032 struct glyph_string *s;
3033 {
3034 int i, k, x;
3035 int end = s->row->used[s->area];
3036 struct glyph *glyphs = s->row->glyphs[s->area];
3037 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3038
3039 k = -1;
3040 x = 0;
3041 for (i = first; i < end; ++i)
3042 {
3043 int left, right;
3044 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3045 if (x - left < 0)
3046 k = i;
3047 x += glyphs[i].pixel_width;
3048 }
3049
3050 return k;
3051 }
3052
3053
3054 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3055
3056 static INLINE void
3057 x_clear_glyph_string_rect (s, x, y, w, h)
3058 struct glyph_string *s;
3059 int x, y, w, h;
3060 {
3061 XGCValues xgcv;
3062 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3063 XSetForeground (s->display, s->gc, xgcv.background);
3064 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3065 XSetForeground (s->display, s->gc, xgcv.foreground);
3066 }
3067
3068
3069 /* Draw the background of glyph_string S. If S->background_filled_p
3070 is non-zero don't draw it. FORCE_P non-zero means draw the
3071 background even if it wouldn't be drawn normally. This is used
3072 when a string preceding S draws into the background of S, or S
3073 contains the first component of a composition. */
3074
3075 static void
3076 x_draw_glyph_string_background (s, force_p)
3077 struct glyph_string *s;
3078 int force_p;
3079 {
3080 /* Nothing to do if background has already been drawn or if it
3081 shouldn't be drawn in the first place. */
3082 if (!s->background_filled_p)
3083 {
3084 if (s->stippled_p)
3085 {
3086 /* Fill background with a stipple pattern. */
3087 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3088 XFillRectangle (s->display, s->window, s->gc, s->x,
3089 s->y + s->face->box_line_width,
3090 s->background_width,
3091 s->height - 2 * s->face->box_line_width);
3092 XSetFillStyle (s->display, s->gc, FillSolid);
3093 s->background_filled_p = 1;
3094 }
3095 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3096 || s->font_not_found_p
3097 || s->extends_to_end_of_line_p
3098 || force_p)
3099 {
3100 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3101 s->background_width,
3102 s->height - 2 * s->face->box_line_width);
3103 s->background_filled_p = 1;
3104 }
3105 }
3106 }
3107
3108
3109 /* Draw the foreground of glyph string S. */
3110
3111 static void
3112 x_draw_glyph_string_foreground (s)
3113 struct glyph_string *s;
3114 {
3115 int i, x;
3116
3117 /* If first glyph of S has a left box line, start drawing the text
3118 of S to the right of that box line. */
3119 if (s->face->box != FACE_NO_BOX
3120 && s->first_glyph->left_box_line_p)
3121 x = s->x + s->face->box_line_width;
3122 else
3123 x = s->x;
3124
3125 /* Draw characters of S as rectangles if S's font could not be
3126 loaded. */
3127 if (s->font_not_found_p)
3128 {
3129 for (i = 0; i < s->nchars; ++i)
3130 {
3131 struct glyph *g = s->first_glyph + i;
3132 XDrawRectangle (s->display, s->window,
3133 s->gc, x, s->y, g->pixel_width - 1,
3134 s->height - 1);
3135 x += g->pixel_width;
3136 }
3137 }
3138 else
3139 {
3140 char *char1b = (char *) s->char2b;
3141 int boff = s->font_info->baseline_offset;
3142
3143 if (s->font_info->vertical_centering)
3144 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3145
3146 /* If we can use 8-bit functions, condense S->char2b. */
3147 if (!s->two_byte_p)
3148 for (i = 0; i < s->nchars; ++i)
3149 char1b[i] = s->char2b[i].byte2;
3150
3151 /* Draw text with XDrawString if background has already been
3152 filled. Otherwise, use XDrawImageString. (Note that
3153 XDrawImageString is usually faster than XDrawString.) Always
3154 use XDrawImageString when drawing the cursor so that there is
3155 no chance that characters under a box cursor are invisible. */
3156 if (s->for_overlaps_p
3157 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3158 {
3159 /* Draw characters with 16-bit or 8-bit functions. */
3160 if (s->two_byte_p)
3161 XDrawString16 (s->display, s->window, s->gc, x,
3162 s->ybase - boff, s->char2b, s->nchars);
3163 else
3164 XDrawString (s->display, s->window, s->gc, x,
3165 s->ybase - boff, char1b, s->nchars);
3166 }
3167 else
3168 {
3169 if (s->two_byte_p)
3170 XDrawImageString16 (s->display, s->window, s->gc, x,
3171 s->ybase - boff, s->char2b, s->nchars);
3172 else
3173 XDrawImageString (s->display, s->window, s->gc, x,
3174 s->ybase - boff, char1b, s->nchars);
3175 }
3176 }
3177 }
3178
3179 /* Draw the foreground of composite glyph string S. */
3180
3181 static void
3182 x_draw_composite_glyph_string_foreground (s)
3183 struct glyph_string *s;
3184 {
3185 int i, x;
3186
3187 /* If first glyph of S has a left box line, start drawing the text
3188 of S to the right of that box line. */
3189 if (s->face->box != FACE_NO_BOX
3190 && s->first_glyph->left_box_line_p)
3191 x = s->x + s->face->box_line_width;
3192 else
3193 x = s->x;
3194
3195 /* S is a glyph string for a composition. S->gidx is the index of
3196 the first character drawn for glyphs of this composition.
3197 S->gidx == 0 means we are drawing the very first character of
3198 this composition. */
3199
3200 /* Draw a rectangle for the composition if the font for the very
3201 first character of the composition could not be loaded. */
3202 if (s->font_not_found_p)
3203 {
3204 if (s->gidx == 0)
3205 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3206 s->width - 1, s->height - 1);
3207 }
3208 else
3209 {
3210 for (i = 0; i < s->nchars; i++, ++s->gidx)
3211 XDrawString16 (s->display, s->window, s->gc,
3212 x + s->cmp->offsets[s->gidx * 2],
3213 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3214 s->char2b + i, 1);
3215 }
3216 }
3217
3218
3219 #ifdef USE_X_TOOLKIT
3220
3221 static struct frame *x_frame_of_widget P_ ((Widget));
3222
3223
3224 /* Return the frame on which widget WIDGET is used.. Abort if frame
3225 cannot be determined. */
3226
3227 static struct frame *
3228 x_frame_of_widget (widget)
3229 Widget widget;
3230 {
3231 struct x_display_info *dpyinfo;
3232 Lisp_Object tail;
3233 struct frame *f;
3234
3235 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3236
3237 /* Find the top-level shell of the widget. Note that this function
3238 can be called when the widget is not yet realized, so XtWindow
3239 (widget) == 0. That's the reason we can't simply use
3240 x_any_window_to_frame. */
3241 while (!XtIsTopLevelShell (widget))
3242 widget = XtParent (widget);
3243
3244 /* Look for a frame with that top-level widget. Allocate the color
3245 on that frame to get the right gamma correction value. */
3246 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3247 if (GC_FRAMEP (XCAR (tail))
3248 && (f = XFRAME (XCAR (tail)),
3249 (f->output_data.nothing != 1
3250 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3251 && f->output_data.x->widget == widget)
3252 return f;
3253
3254 abort ();
3255 }
3256
3257
3258 /* Allocate the color COLOR->pixel on the screen and display of
3259 widget WIDGET in colormap CMAP. If an exact match cannot be
3260 allocated, try the nearest color available. Value is non-zero
3261 if successful. This is called from lwlib. */
3262
3263 int
3264 x_alloc_nearest_color_for_widget (widget, cmap, color)
3265 Widget widget;
3266 Colormap cmap;
3267 XColor *color;
3268 {
3269 struct frame *f = x_frame_of_widget (widget);
3270 return x_alloc_nearest_color (f, cmap, color);
3271 }
3272
3273
3274 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3275 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3276 If this produces the same color as PIXEL, try a color where all RGB
3277 values have DELTA added. Return the allocated color in *PIXEL.
3278 DISPLAY is the X display, CMAP is the colormap to operate on.
3279 Value is non-zero if successful. */
3280
3281 int
3282 x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3283 Widget widget;
3284 Display *display;
3285 Colormap cmap;
3286 unsigned long *pixel;
3287 double factor;
3288 int delta;
3289 {
3290 struct frame *f = x_frame_of_widget (widget);
3291 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3292 }
3293
3294
3295 #endif /* USE_X_TOOLKIT */
3296
3297
3298 /* Value is an array of XColor structures for the contents of the
3299 color map of frame F. Set *NCELLS to the size of the array.
3300 Note that this probably shouldn't be called for large color maps,
3301 say a 24-bit TrueColor map. */
3302
3303 static const XColor *
3304 x_color_cells (f, ncells)
3305 struct frame *f;
3306 int *ncells;
3307 {
3308 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3309
3310 if (dpyinfo->color_cells == NULL)
3311 {
3312 Display *display = FRAME_X_DISPLAY (f);
3313 Screen *screen = FRAME_X_SCREEN (f);
3314 int i;
3315
3316 dpyinfo->ncolor_cells
3317 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3318 dpyinfo->color_cells
3319 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3320 * sizeof *dpyinfo->color_cells);
3321
3322 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3323 dpyinfo->color_cells[i].pixel = i;
3324
3325 XQueryColors (display, FRAME_X_COLORMAP (f),
3326 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3327 }
3328
3329 *ncells = dpyinfo->ncolor_cells;
3330 return dpyinfo->color_cells;
3331 }
3332
3333
3334 /* On frame F, translate pixel colors to RGB values for the NCOLORS
3335 colors in COLORS. Use cached information, if available. */
3336
3337 void
3338 x_query_colors (f, colors, ncolors)
3339 struct frame *f;
3340 XColor *colors;
3341 int ncolors;
3342 {
3343 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3344
3345 if (dpyinfo->color_cells)
3346 {
3347 int i;
3348 for (i = 0; i < ncolors; ++i)
3349 {
3350 unsigned long pixel = colors[i].pixel;
3351 xassert (pixel < dpyinfo->ncolor_cells);
3352 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3353 colors[i] = dpyinfo->color_cells[pixel];
3354 }
3355 }
3356 else
3357 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3358 }
3359
3360
3361 /* On frame F, translate pixel color to RGB values for the color in
3362 COLOR. Use cached information, if available. */
3363
3364 void
3365 x_query_color (f, color)
3366 struct frame *f;
3367 XColor *color;
3368 {
3369 x_query_colors (f, color, 1);
3370 }
3371
3372
3373 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3374 CMAP. If an exact match can't be allocated, try the nearest color
3375 available. Value is non-zero if successful. Set *COLOR to the
3376 color allocated. */
3377
3378 int
3379 x_alloc_nearest_color (f, cmap, color)
3380 struct frame *f;
3381 Colormap cmap;
3382 XColor *color;
3383 {
3384 Display *display = FRAME_X_DISPLAY (f);
3385 Screen *screen = FRAME_X_SCREEN (f);
3386 int rc;
3387
3388 gamma_correct (f, color);
3389 rc = XAllocColor (display, cmap, color);
3390 if (rc == 0)
3391 {
3392 /* If we got to this point, the colormap is full, so we're going
3393 to try to get the next closest color. The algorithm used is
3394 a least-squares matching, which is what X uses for closest
3395 color matching with StaticColor visuals. */
3396 int nearest, i;
3397 unsigned long nearest_delta = ~0;
3398 int ncells;
3399 const XColor *cells = x_color_cells (f, &ncells);
3400
3401 for (nearest = i = 0; i < ncells; ++i)
3402 {
3403 long dred = (color->red >> 8) - (cells[i].red >> 8);
3404 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3405 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3406 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3407
3408 if (delta < nearest_delta)
3409 {
3410 nearest = i;
3411 nearest_delta = delta;
3412 }
3413 }
3414
3415 color->red = cells[nearest].red;
3416 color->green = cells[nearest].green;
3417 color->blue = cells[nearest].blue;
3418 rc = XAllocColor (display, cmap, color);
3419 }
3420 else
3421 {
3422 /* If allocation succeeded, and the allocated pixel color is not
3423 equal to a cached pixel color recorded earlier, there was a
3424 change in the colormap, so clear the color cache. */
3425 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3426 XColor *cached_color;
3427
3428 if (dpyinfo->color_cells
3429 && (cached_color = &dpyinfo->color_cells[color->pixel],
3430 (cached_color->red != color->red
3431 || cached_color->blue != color->blue
3432 || cached_color->green != color->green)))
3433 {
3434 xfree (dpyinfo->color_cells);
3435 dpyinfo->color_cells = NULL;
3436 dpyinfo->ncolor_cells = 0;
3437 }
3438 }
3439
3440 #ifdef DEBUG_X_COLORS
3441 if (rc)
3442 register_color (color->pixel);
3443 #endif /* DEBUG_X_COLORS */
3444
3445 return rc;
3446 }
3447
3448
3449 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3450 It's necessary to do this instead of just using PIXEL directly to
3451 get color reference counts right. */
3452
3453 unsigned long
3454 x_copy_color (f, pixel)
3455 struct frame *f;
3456 unsigned long pixel;
3457 {
3458 XColor color;
3459
3460 color.pixel = pixel;
3461 BLOCK_INPUT;
3462 x_query_color (f, &color);
3463 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3464 UNBLOCK_INPUT;
3465 #ifdef DEBUG_X_COLORS
3466 register_color (pixel);
3467 #endif
3468 return color.pixel;
3469 }
3470
3471
3472 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3473 It's necessary to do this instead of just using PIXEL directly to
3474 get color reference counts right. */
3475
3476 unsigned long
3477 x_copy_dpy_color (dpy, cmap, pixel)
3478 Display *dpy;
3479 Colormap cmap;
3480 unsigned long pixel;
3481 {
3482 XColor color;
3483
3484 color.pixel = pixel;
3485 BLOCK_INPUT;
3486 XQueryColor (dpy, cmap, &color);
3487 XAllocColor (dpy, cmap, &color);
3488 UNBLOCK_INPUT;
3489 #ifdef DEBUG_X_COLORS
3490 register_color (pixel);
3491 #endif
3492 return color.pixel;
3493 }
3494
3495
3496 /* Brightness beyond which a color won't have its highlight brightness
3497 boosted.
3498
3499 Nominally, highlight colors for `3d' faces are calculated by
3500 brightening an object's color by a constant scale factor, but this
3501 doesn't yield good results for dark colors, so for colors who's
3502 brightness is less than this value (on a scale of 0-65535) have an
3503 use an additional additive factor.
3504
3505 The value here is set so that the default menu-bar/mode-line color
3506 (grey75) will not have its highlights changed at all. */
3507 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3508
3509
3510 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3511 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3512 If this produces the same color as PIXEL, try a color where all RGB
3513 values have DELTA added. Return the allocated color in *PIXEL.
3514 DISPLAY is the X display, CMAP is the colormap to operate on.
3515 Value is non-zero if successful. */
3516
3517 static int
3518 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3519 struct frame *f;
3520 Display *display;
3521 Colormap cmap;
3522 unsigned long *pixel;
3523 double factor;
3524 int delta;
3525 {
3526 XColor color, new;
3527 long bright;
3528 int success_p;
3529
3530 /* Get RGB color values. */
3531 color.pixel = *pixel;
3532 x_query_color (f, &color);
3533
3534 /* Change RGB values by specified FACTOR. Avoid overflow! */
3535 xassert (factor >= 0);
3536 new.red = min (0xffff, factor * color.red);
3537 new.green = min (0xffff, factor * color.green);
3538 new.blue = min (0xffff, factor * color.blue);
3539
3540 /* Calculate brightness of COLOR. */
3541 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3542
3543 /* We only boost colors that are darker than
3544 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3545 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3546 /* Make an additive adjustment to NEW, because it's dark enough so
3547 that scaling by FACTOR alone isn't enough. */
3548 {
3549 /* How far below the limit this color is (0 - 1, 1 being darker). */
3550 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3551 /* The additive adjustment. */
3552 int min_delta = delta * dimness * factor / 2;
3553
3554 if (factor < 1)
3555 {
3556 new.red = max (0, new.red - min_delta);
3557 new.green = max (0, new.green - min_delta);
3558 new.blue = max (0, new.blue - min_delta);
3559 }
3560 else
3561 {
3562 new.red = min (0xffff, min_delta + new.red);
3563 new.green = min (0xffff, min_delta + new.green);
3564 new.blue = min (0xffff, min_delta + new.blue);
3565 }
3566 }
3567
3568 /* Try to allocate the color. */
3569 success_p = x_alloc_nearest_color (f, cmap, &new);
3570 if (success_p)
3571 {
3572 if (new.pixel == *pixel)
3573 {
3574 /* If we end up with the same color as before, try adding
3575 delta to the RGB values. */
3576 x_free_colors (f, &new.pixel, 1);
3577
3578 new.red = min (0xffff, delta + color.red);
3579 new.green = min (0xffff, delta + color.green);
3580 new.blue = min (0xffff, delta + color.blue);
3581 success_p = x_alloc_nearest_color (f, cmap, &new);
3582 }
3583 else
3584 success_p = 1;
3585 *pixel = new.pixel;
3586 }
3587
3588 return success_p;
3589 }
3590
3591
3592 /* Set up the foreground color for drawing relief lines of glyph
3593 string S. RELIEF is a pointer to a struct relief containing the GC
3594 with which lines will be drawn. Use a color that is FACTOR or
3595 DELTA lighter or darker than the relief's background which is found
3596 in S->f->output_data.x->relief_background. If such a color cannot
3597 be allocated, use DEFAULT_PIXEL, instead. */
3598
3599 static void
3600 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3601 struct frame *f;
3602 struct relief *relief;
3603 double factor;
3604 int delta;
3605 unsigned long default_pixel;
3606 {
3607 XGCValues xgcv;
3608 struct x_output *di = f->output_data.x;
3609 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3610 unsigned long pixel;
3611 unsigned long background = di->relief_background;
3612 Colormap cmap = FRAME_X_COLORMAP (f);
3613 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3614 Display *dpy = FRAME_X_DISPLAY (f);
3615
3616 xgcv.graphics_exposures = False;
3617 xgcv.line_width = 1;
3618
3619 /* Free previously allocated color. The color cell will be reused
3620 when it has been freed as many times as it was allocated, so this
3621 doesn't affect faces using the same colors. */
3622 if (relief->gc
3623 && relief->allocated_p)
3624 {
3625 x_free_colors (f, &relief->pixel, 1);
3626 relief->allocated_p = 0;
3627 }
3628
3629 /* Allocate new color. */
3630 xgcv.foreground = default_pixel;
3631 pixel = background;
3632 if (dpyinfo->n_planes != 1
3633 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3634 {
3635 relief->allocated_p = 1;
3636 xgcv.foreground = relief->pixel = pixel;
3637 }
3638
3639 if (relief->gc == 0)
3640 {
3641 xgcv.stipple = dpyinfo->gray;
3642 mask |= GCStipple;
3643 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3644 }
3645 else
3646 XChangeGC (dpy, relief->gc, mask, &xgcv);
3647 }
3648
3649
3650 /* Set up colors for the relief lines around glyph string S. */
3651
3652 static void
3653 x_setup_relief_colors (s)
3654 struct glyph_string *s;
3655 {
3656 struct x_output *di = s->f->output_data.x;
3657 unsigned long color;
3658
3659 if (s->face->use_box_color_for_shadows_p)
3660 color = s->face->box_color;
3661 else
3662 {
3663 XGCValues xgcv;
3664
3665 /* Get the background color of the face. */
3666 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3667 color = xgcv.background;
3668 }
3669
3670 if (di->white_relief.gc == 0
3671 || color != di->relief_background)
3672 {
3673 di->relief_background = color;
3674 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3675 WHITE_PIX_DEFAULT (s->f));
3676 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3677 BLACK_PIX_DEFAULT (s->f));
3678 }
3679 }
3680
3681
3682 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3683 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3684 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3685 relief. LEFT_P non-zero means draw a relief on the left side of
3686 the rectangle. RIGHT_P non-zero means draw a relief on the right
3687 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3688 when drawing. */
3689
3690 static void
3691 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3692 raised_p, left_p, right_p, clip_rect)
3693 struct frame *f;
3694 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3695 XRectangle *clip_rect;
3696 {
3697 int i;
3698 GC gc;
3699
3700 if (raised_p)
3701 gc = f->output_data.x->white_relief.gc;
3702 else
3703 gc = f->output_data.x->black_relief.gc;
3704 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3705
3706 /* Top. */
3707 for (i = 0; i < width; ++i)
3708 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3709 left_x + i * left_p, top_y + i,
3710 right_x + 1 - i * right_p, top_y + i);
3711
3712 /* Left. */
3713 if (left_p)
3714 for (i = 0; i < width; ++i)
3715 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3716 left_x + i, top_y + i, left_x + i, bottom_y - i);
3717
3718 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3719 if (raised_p)
3720 gc = f->output_data.x->black_relief.gc;
3721 else
3722 gc = f->output_data.x->white_relief.gc;
3723 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3724
3725 /* Bottom. */
3726 for (i = 0; i < width; ++i)
3727 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3728 left_x + i * left_p, bottom_y - i,
3729 right_x + 1 - i * right_p, bottom_y - i);
3730
3731 /* Right. */
3732 if (right_p)
3733 for (i = 0; i < width; ++i)
3734 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3735 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3736
3737 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3738 }
3739
3740
3741 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3742 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3743 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3744 left side of the rectangle. RIGHT_P non-zero means draw a line
3745 on the right side of the rectangle. CLIP_RECT is the clipping
3746 rectangle to use when drawing. */
3747
3748 static void
3749 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3750 left_p, right_p, clip_rect)
3751 struct glyph_string *s;
3752 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3753 XRectangle *clip_rect;
3754 {
3755 XGCValues xgcv;
3756
3757 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3758 XSetForeground (s->display, s->gc, s->face->box_color);
3759 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3760
3761 /* Top. */
3762 XFillRectangle (s->display, s->window, s->gc,
3763 left_x, top_y, right_x - left_x + 1, width);
3764
3765 /* Left. */
3766 if (left_p)
3767 XFillRectangle (s->display, s->window, s->gc,
3768 left_x, top_y, width, bottom_y - top_y + 1);
3769
3770 /* Bottom. */
3771 XFillRectangle (s->display, s->window, s->gc,
3772 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3773
3774 /* Right. */
3775 if (right_p)
3776 XFillRectangle (s->display, s->window, s->gc,
3777 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3778
3779 XSetForeground (s->display, s->gc, xgcv.foreground);
3780 XSetClipMask (s->display, s->gc, None);
3781 }
3782
3783
3784 /* Draw a box around glyph string S. */
3785
3786 static void
3787 x_draw_glyph_string_box (s)
3788 struct glyph_string *s;
3789 {
3790 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3791 int left_p, right_p;
3792 struct glyph *last_glyph;
3793 XRectangle clip_rect;
3794
3795 last_x = window_box_right (s->w, s->area);
3796 if (s->row->full_width_p
3797 && !s->w->pseudo_window_p)
3798 {
3799 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3800 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3801 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3802 }
3803
3804 /* The glyph that may have a right box line. */
3805 last_glyph = (s->cmp || s->img
3806 ? s->first_glyph
3807 : s->first_glyph + s->nchars - 1);
3808
3809 width = s->face->box_line_width;
3810 raised_p = s->face->box == FACE_RAISED_BOX;
3811 left_x = s->x;
3812 right_x = ((s->row->full_width_p
3813 ? last_x - 1
3814 : min (last_x, s->x + s->background_width) - 1));
3815 top_y = s->y;
3816 bottom_y = top_y + s->height - 1;
3817
3818 left_p = (s->first_glyph->left_box_line_p
3819 || (s->hl == DRAW_MOUSE_FACE
3820 && (s->prev == NULL
3821 || s->prev->hl != s->hl)));
3822 right_p = (last_glyph->right_box_line_p
3823 || (s->hl == DRAW_MOUSE_FACE
3824 && (s->next == NULL
3825 || s->next->hl != s->hl)));
3826
3827 x_get_glyph_string_clip_rect (s, &clip_rect);
3828
3829 if (s->face->box == FACE_SIMPLE_BOX)
3830 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3831 left_p, right_p, &clip_rect);
3832 else
3833 {
3834 x_setup_relief_colors (s);
3835 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3836 width, raised_p, left_p, right_p, &clip_rect);
3837 }
3838 }
3839
3840
3841 /* Draw foreground of image glyph string S. */
3842
3843 static void
3844 x_draw_image_foreground (s)
3845 struct glyph_string *s;
3846 {
3847 int x;
3848 int y = s->ybase - image_ascent (s->img, s->face);
3849
3850 /* If first glyph of S has a left box line, start drawing it to the
3851 right of that line. */
3852 if (s->face->box != FACE_NO_BOX
3853 && s->first_glyph->left_box_line_p)
3854 x = s->x + s->face->box_line_width;
3855 else
3856 x = s->x;
3857
3858 /* If there is a margin around the image, adjust x- and y-position
3859 by that margin. */
3860 if (s->img->margin)
3861 {
3862 x += s->img->margin;
3863 y += s->img->margin;
3864 }
3865
3866 if (s->img->pixmap)
3867 {
3868 if (s->img->mask)
3869 {
3870 /* We can't set both a clip mask and use XSetClipRectangles
3871 because the latter also sets a clip mask. We also can't
3872 trust on the shape extension to be available
3873 (XShapeCombineRegion). So, compute the rectangle to draw
3874 manually. */
3875 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3876 | GCFunction);
3877 XGCValues xgcv;
3878 XRectangle clip_rect, image_rect, r;
3879
3880 xgcv.clip_mask = s->img->mask;
3881 xgcv.clip_x_origin = x;
3882 xgcv.clip_y_origin = y;
3883 xgcv.function = GXcopy;
3884 XChangeGC (s->display, s->gc, mask, &xgcv);
3885
3886 x_get_glyph_string_clip_rect (s, &clip_rect);
3887 image_rect.x = x;
3888 image_rect.y = y;
3889 image_rect.width = s->img->width;
3890 image_rect.height = s->img->height;
3891 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3892 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3893 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3894 }
3895 else
3896 {
3897 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3898 XGCValues xgcv;
3899 XRectangle clip_rect, image_rect, r;
3900
3901 x_get_glyph_string_clip_rect (s, &clip_rect);
3902 image_rect.x = x;
3903 image_rect.y = y;
3904 image_rect.width = s->img->width;
3905 image_rect.height = s->img->height;
3906 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3907 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3908 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3909
3910 /* When the image has a mask, we can expect that at
3911 least part of a mouse highlight or a block cursor will
3912 be visible. If the image doesn't have a mask, make
3913 a block cursor visible by drawing a rectangle around
3914 the image. I believe it's looking better if we do
3915 nothing here for mouse-face. */
3916 if (s->hl == DRAW_CURSOR)
3917 XDrawRectangle (s->display, s->window, s->gc, x, y,
3918 s->img->width - 1, s->img->height - 1);
3919 }
3920 }
3921 else
3922 /* Draw a rectangle if image could not be loaded. */
3923 XDrawRectangle (s->display, s->window, s->gc, x, y,
3924 s->img->width - 1, s->img->height - 1);
3925 }
3926
3927
3928 /* Draw a relief around the image glyph string S. */
3929
3930 static void
3931 x_draw_image_relief (s)
3932 struct glyph_string *s;
3933 {
3934 int x0, y0, x1, y1, thick, raised_p;
3935 XRectangle r;
3936 int x;
3937 int y = s->ybase - image_ascent (s->img, s->face);
3938
3939 /* If first glyph of S has a left box line, start drawing it to the
3940 right of that line. */
3941 if (s->face->box != FACE_NO_BOX
3942 && s->first_glyph->left_box_line_p)
3943 x = s->x + s->face->box_line_width;
3944 else
3945 x = s->x;
3946
3947 /* If there is a margin around the image, adjust x- and y-position
3948 by that margin. */
3949 if (s->img->margin)
3950 {
3951 x += s->img->margin;
3952 y += s->img->margin;
3953 }
3954
3955 if (s->hl == DRAW_IMAGE_SUNKEN
3956 || s->hl == DRAW_IMAGE_RAISED)
3957 {
3958 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3959 raised_p = s->hl == DRAW_IMAGE_RAISED;
3960 }
3961 else
3962 {
3963 thick = abs (s->img->relief);
3964 raised_p = s->img->relief > 0;
3965 }
3966
3967 x0 = x - thick;
3968 y0 = y - thick;
3969 x1 = x + s->img->width + thick - 1;
3970 y1 = y + s->img->height + thick - 1;
3971
3972 x_setup_relief_colors (s);
3973 x_get_glyph_string_clip_rect (s, &r);
3974 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3975 }
3976
3977
3978 /* Draw the foreground of image glyph string S to PIXMAP. */
3979
3980 static void
3981 x_draw_image_foreground_1 (s, pixmap)
3982 struct glyph_string *s;
3983 Pixmap pixmap;
3984 {
3985 int x;
3986 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3987
3988 /* If first glyph of S has a left box line, start drawing it to the
3989 right of that line. */
3990 if (s->face->box != FACE_NO_BOX
3991 && s->first_glyph->left_box_line_p)
3992 x = s->face->box_line_width;
3993 else
3994 x = 0;
3995
3996 /* If there is a margin around the image, adjust x- and y-position
3997 by that margin. */
3998 if (s->img->margin)
3999 {
4000 x += s->img->margin;
4001 y += s->img->margin;
4002 }
4003
4004 if (s->img->pixmap)
4005 {
4006 if (s->img->mask)
4007 {
4008 /* We can't set both a clip mask and use XSetClipRectangles
4009 because the latter also sets a clip mask. We also can't
4010 trust on the shape extension to be available
4011 (XShapeCombineRegion). So, compute the rectangle to draw
4012 manually. */
4013 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4014 | GCFunction);
4015 XGCValues xgcv;
4016
4017 xgcv.clip_mask = s->img->mask;
4018 xgcv.clip_x_origin = x;
4019 xgcv.clip_y_origin = y;
4020 xgcv.function = GXcopy;
4021 XChangeGC (s->display, s->gc, mask, &xgcv);
4022
4023 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4024 0, 0, s->img->width, s->img->height, x, y);
4025 XSetClipMask (s->display, s->gc, None);
4026 }
4027 else
4028 {
4029 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4030 0, 0, s->img->width, s->img->height, x, y);
4031
4032 /* When the image has a mask, we can expect that at
4033 least part of a mouse highlight or a block cursor will
4034 be visible. If the image doesn't have a mask, make
4035 a block cursor visible by drawing a rectangle around
4036 the image. I believe it's looking better if we do
4037 nothing here for mouse-face. */
4038 if (s->hl == DRAW_CURSOR)
4039 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4040 s->img->width - 1, s->img->height - 1);
4041 }
4042 }
4043 else
4044 /* Draw a rectangle if image could not be loaded. */
4045 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4046 s->img->width - 1, s->img->height - 1);
4047 }
4048
4049
4050 /* Draw part of the background of glyph string S. X, Y, W, and H
4051 give the rectangle to draw. */
4052
4053 static void
4054 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4055 struct glyph_string *s;
4056 int x, y, w, h;
4057 {
4058 if (s->stippled_p)
4059 {
4060 /* Fill background with a stipple pattern. */
4061 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4062 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4063 XSetFillStyle (s->display, s->gc, FillSolid);
4064 }
4065 else
4066 x_clear_glyph_string_rect (s, x, y, w, h);
4067 }
4068
4069
4070 /* Draw image glyph string S.
4071
4072 s->y
4073 s->x +-------------------------
4074 | s->face->box
4075 |
4076 | +-------------------------
4077 | | s->img->margin
4078 | |
4079 | | +-------------------
4080 | | | the image
4081
4082 */
4083
4084 static void
4085 x_draw_image_glyph_string (s)
4086 struct glyph_string *s;
4087 {
4088 int x, y;
4089 int box_line_width = s->face->box_line_width;
4090 int margin = s->img->margin;
4091 int height;
4092 Pixmap pixmap = None;
4093
4094 height = s->height - 2 * box_line_width;
4095
4096 /* Fill background with face under the image. Do it only if row is
4097 taller than image or if image has a clip mask to reduce
4098 flickering. */
4099 s->stippled_p = s->face->stipple != 0;
4100 if (height > s->img->height
4101 || margin
4102 || s->img->mask
4103 || s->img->pixmap == 0
4104 || s->width != s->background_width)
4105 {
4106 if (box_line_width && s->first_glyph->left_box_line_p)
4107 x = s->x + box_line_width;
4108 else
4109 x = s->x;
4110
4111 y = s->y + box_line_width;
4112
4113 if (s->img->mask)
4114 {
4115 /* Create a pixmap as large as the glyph string. Fill it
4116 with the background color. Copy the image to it, using
4117 its mask. Copy the temporary pixmap to the display. */
4118 Screen *screen = FRAME_X_SCREEN (s->f);
4119 int depth = DefaultDepthOfScreen (screen);
4120
4121 /* Create a pixmap as large as the glyph string. */
4122 pixmap = XCreatePixmap (s->display, s->window,
4123 s->background_width,
4124 s->height, depth);
4125
4126 /* Don't clip in the following because we're working on the
4127 pixmap. */
4128 XSetClipMask (s->display, s->gc, None);
4129
4130 /* Fill the pixmap with the background color/stipple. */
4131 if (s->stippled_p)
4132 {
4133 /* Fill background with a stipple pattern. */
4134 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4135 XFillRectangle (s->display, pixmap, s->gc,
4136 0, 0, s->background_width, s->height);
4137 XSetFillStyle (s->display, s->gc, FillSolid);
4138 }
4139 else
4140 {
4141 XGCValues xgcv;
4142 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4143 &xgcv);
4144 XSetForeground (s->display, s->gc, xgcv.background);
4145 XFillRectangle (s->display, pixmap, s->gc,
4146 0, 0, s->background_width, s->height);
4147 XSetForeground (s->display, s->gc, xgcv.foreground);
4148 }
4149 }
4150 else
4151 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4152
4153 s->background_filled_p = 1;
4154 }
4155
4156 /* Draw the foreground. */
4157 if (pixmap != None)
4158 {
4159 x_draw_image_foreground_1 (s, pixmap);
4160 x_set_glyph_string_clipping (s);
4161 XCopyArea (s->display, pixmap, s->window, s->gc,
4162 0, 0, s->background_width, s->height, s->x, s->y);
4163 XFreePixmap (s->display, pixmap);
4164 }
4165 else
4166 x_draw_image_foreground (s);
4167
4168 /* If we must draw a relief around the image, do it. */
4169 if (s->img->relief
4170 || s->hl == DRAW_IMAGE_RAISED
4171 || s->hl == DRAW_IMAGE_SUNKEN)
4172 x_draw_image_relief (s);
4173 }
4174
4175
4176 /* Draw stretch glyph string S. */
4177
4178 static void
4179 x_draw_stretch_glyph_string (s)
4180 struct glyph_string *s;
4181 {
4182 xassert (s->first_glyph->type == STRETCH_GLYPH);
4183 s->stippled_p = s->face->stipple != 0;
4184
4185 if (s->hl == DRAW_CURSOR
4186 && !x_stretch_cursor_p)
4187 {
4188 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4189 as wide as the stretch glyph. */
4190 int width = min (CANON_X_UNIT (s->f), s->background_width);
4191
4192 /* Draw cursor. */
4193 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4194
4195 /* Clear rest using the GC of the original non-cursor face. */
4196 if (width < s->background_width)
4197 {
4198 GC gc = s->face->gc;
4199 int x = s->x + width, y = s->y;
4200 int w = s->background_width - width, h = s->height;
4201 XRectangle r;
4202
4203 x_get_glyph_string_clip_rect (s, &r);
4204 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
4205
4206 if (s->face->stipple)
4207 {
4208 /* Fill background with a stipple pattern. */
4209 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4210 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4211 XSetFillStyle (s->display, gc, FillSolid);
4212 }
4213 else
4214 {
4215 XGCValues xgcv;
4216 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4217 XSetForeground (s->display, gc, xgcv.background);
4218 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4219 XSetForeground (s->display, gc, xgcv.foreground);
4220 }
4221 }
4222 }
4223 else
4224 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4225 s->height);
4226
4227 s->background_filled_p = 1;
4228 }
4229
4230
4231 /* Draw glyph string S. */
4232
4233 static void
4234 x_draw_glyph_string (s)
4235 struct glyph_string *s;
4236 {
4237 /* If S draws into the background of its successor, draw the
4238 background of the successor first so that S can draw into it.
4239 This makes S->next use XDrawString instead of XDrawImageString. */
4240 if (s->next && s->right_overhang && !s->for_overlaps_p)
4241 {
4242 xassert (s->next->img == NULL);
4243 x_set_glyph_string_gc (s->next);
4244 x_set_glyph_string_clipping (s->next);
4245 x_draw_glyph_string_background (s->next, 1);
4246 }
4247
4248 /* Set up S->gc, set clipping and draw S. */
4249 x_set_glyph_string_gc (s);
4250 x_set_glyph_string_clipping (s);
4251
4252 switch (s->first_glyph->type)
4253 {
4254 case IMAGE_GLYPH:
4255 x_draw_image_glyph_string (s);
4256 break;
4257
4258 case STRETCH_GLYPH:
4259 x_draw_stretch_glyph_string (s);
4260 break;
4261
4262 case CHAR_GLYPH:
4263 if (s->for_overlaps_p)
4264 s->background_filled_p = 1;
4265 else
4266 x_draw_glyph_string_background (s, 0);
4267 x_draw_glyph_string_foreground (s);
4268 break;
4269
4270 case COMPOSITE_GLYPH:
4271 if (s->for_overlaps_p || s->gidx > 0)
4272 s->background_filled_p = 1;
4273 else
4274 x_draw_glyph_string_background (s, 1);
4275 x_draw_composite_glyph_string_foreground (s);
4276 break;
4277
4278 default:
4279 abort ();
4280 }
4281
4282 if (!s->for_overlaps_p)
4283 {
4284 /* Draw underline. */
4285 if (s->face->underline_p)
4286 {
4287 unsigned long tem, h;
4288 int y;
4289
4290 /* Get the underline thickness. Default is 1 pixel. */
4291 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4292 h = 1;
4293
4294 /* Get the underline position. This is the recommended
4295 vertical offset in pixels from the baseline to the top of
4296 the underline. This is a signed value according to the
4297 specs, and its default is
4298
4299 ROUND ((maximum descent) / 2), with
4300 ROUND(x) = floor (x + 0.5) */
4301
4302 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4303 y = s->ybase + (long) tem;
4304 else if (s->face->font)
4305 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4306 else
4307 y = s->height - h;
4308
4309 if (s->face->underline_defaulted_p)
4310 XFillRectangle (s->display, s->window, s->gc,
4311 s->x, y, s->width, h);
4312 else
4313 {
4314 XGCValues xgcv;
4315 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4316 XSetForeground (s->display, s->gc, s->face->underline_color);
4317 XFillRectangle (s->display, s->window, s->gc,
4318 s->x, y, s->width, h);
4319 XSetForeground (s->display, s->gc, xgcv.foreground);
4320 }
4321 }
4322
4323 /* Draw overline. */
4324 if (s->face->overline_p)
4325 {
4326 unsigned long dy = 0, h = 1;
4327
4328 if (s->face->overline_color_defaulted_p)
4329 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4330 s->width, h);
4331 else
4332 {
4333 XGCValues xgcv;
4334 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4335 XSetForeground (s->display, s->gc, s->face->overline_color);
4336 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4337 s->width, h);
4338 XSetForeground (s->display, s->gc, xgcv.foreground);
4339 }
4340 }
4341
4342 /* Draw strike-through. */
4343 if (s->face->strike_through_p)
4344 {
4345 unsigned long h = 1;
4346 unsigned long dy = (s->height - h) / 2;
4347
4348 if (s->face->strike_through_color_defaulted_p)
4349 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4350 s->width, h);
4351 else
4352 {
4353 XGCValues xgcv;
4354 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4355 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4356 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4357 s->width, h);
4358 XSetForeground (s->display, s->gc, xgcv.foreground);
4359 }
4360 }
4361
4362 /* Draw relief. */
4363 if (s->face->box != FACE_NO_BOX)
4364 x_draw_glyph_string_box (s);
4365 }
4366
4367 /* Reset clipping. */
4368 XSetClipMask (s->display, s->gc, None);
4369 }
4370
4371
4372 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4373 struct face **, int));
4374
4375
4376 /* Fill glyph string S with composition components specified by S->cmp.
4377
4378 FACES is an array of faces for all components of this composition.
4379 S->gidx is the index of the first component for S.
4380 OVERLAPS_P non-zero means S should draw the foreground only, and
4381 use its physical height for clipping.
4382
4383 Value is the index of a component not in S. */
4384
4385 static int
4386 x_fill_composite_glyph_string (s, faces, overlaps_p)
4387 struct glyph_string *s;
4388 struct face **faces;
4389 int overlaps_p;
4390 {
4391 int i;
4392
4393 xassert (s);
4394
4395 s->for_overlaps_p = overlaps_p;
4396
4397 s->face = faces[s->gidx];
4398 s->font = s->face->font;
4399 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4400
4401 /* For all glyphs of this composition, starting at the offset
4402 S->gidx, until we reach the end of the definition or encounter a
4403 glyph that requires the different face, add it to S. */
4404 ++s->nchars;
4405 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4406 ++s->nchars;
4407
4408 /* All glyph strings for the same composition has the same width,
4409 i.e. the width set for the first component of the composition. */
4410
4411 s->width = s->first_glyph->pixel_width;
4412
4413 /* If the specified font could not be loaded, use the frame's
4414 default font, but record the fact that we couldn't load it in
4415 the glyph string so that we can draw rectangles for the
4416 characters of the glyph string. */
4417 if (s->font == NULL)
4418 {
4419 s->font_not_found_p = 1;
4420 s->font = FRAME_FONT (s->f);
4421 }
4422
4423 /* Adjust base line for subscript/superscript text. */
4424 s->ybase += s->first_glyph->voffset;
4425
4426 xassert (s->face && s->face->gc);
4427
4428 /* This glyph string must always be drawn with 16-bit functions. */
4429 s->two_byte_p = 1;
4430
4431 return s->gidx + s->nchars;
4432 }
4433
4434
4435 /* Fill glyph string S from a sequence of character glyphs.
4436
4437 FACE_ID is the face id of the string. START is the index of the
4438 first glyph to consider, END is the index of the last + 1.
4439 OVERLAPS_P non-zero means S should draw the foreground only, and
4440 use its physical height for clipping.
4441
4442 Value is the index of the first glyph not in S. */
4443
4444 static int
4445 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4446 struct glyph_string *s;
4447 int face_id;
4448 int start, end, overlaps_p;
4449 {
4450 struct glyph *glyph, *last;
4451 int voffset;
4452 int glyph_not_available_p;
4453
4454 xassert (s->f == XFRAME (s->w->frame));
4455 xassert (s->nchars == 0);
4456 xassert (start >= 0 && end > start);
4457
4458 s->for_overlaps_p = overlaps_p,
4459 glyph = s->row->glyphs[s->area] + start;
4460 last = s->row->glyphs[s->area] + end;
4461 voffset = glyph->voffset;
4462
4463 glyph_not_available_p = glyph->glyph_not_available_p;
4464
4465 while (glyph < last
4466 && glyph->type == CHAR_GLYPH
4467 && glyph->voffset == voffset
4468 /* Same face id implies same font, nowadays. */
4469 && glyph->face_id == face_id
4470 && glyph->glyph_not_available_p == glyph_not_available_p)
4471 {
4472 int two_byte_p;
4473
4474 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4475 s->char2b + s->nchars,
4476 &two_byte_p);
4477 s->two_byte_p = two_byte_p;
4478 ++s->nchars;
4479 xassert (s->nchars <= end - start);
4480 s->width += glyph->pixel_width;
4481 ++glyph;
4482 }
4483
4484 s->font = s->face->font;
4485 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4486
4487 /* If the specified font could not be loaded, use the frame's font,
4488 but record the fact that we couldn't load it in
4489 S->font_not_found_p so that we can draw rectangles for the
4490 characters of the glyph string. */
4491 if (s->font == NULL || glyph_not_available_p)
4492 {
4493 s->font_not_found_p = 1;
4494 s->font = FRAME_FONT (s->f);
4495 }
4496
4497 /* Adjust base line for subscript/superscript text. */
4498 s->ybase += voffset;
4499
4500 xassert (s->face && s->face->gc);
4501 return glyph - s->row->glyphs[s->area];
4502 }
4503
4504
4505 /* Fill glyph string S from image glyph S->first_glyph. */
4506
4507 static void
4508 x_fill_image_glyph_string (s)
4509 struct glyph_string *s;
4510 {
4511 xassert (s->first_glyph->type == IMAGE_GLYPH);
4512 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4513 xassert (s->img);
4514 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4515 s->font = s->face->font;
4516 s->width = s->first_glyph->pixel_width;
4517
4518 /* Adjust base line for subscript/superscript text. */
4519 s->ybase += s->first_glyph->voffset;
4520 }
4521
4522
4523 /* Fill glyph string S from a sequence of stretch glyphs.
4524
4525 ROW is the glyph row in which the glyphs are found, AREA is the
4526 area within the row. START is the index of the first glyph to
4527 consider, END is the index of the last + 1.
4528
4529 Value is the index of the first glyph not in S. */
4530
4531 static int
4532 x_fill_stretch_glyph_string (s, row, area, start, end)
4533 struct glyph_string *s;
4534 struct glyph_row *row;
4535 enum glyph_row_area area;
4536 int start, end;
4537 {
4538 struct glyph *glyph, *last;
4539 int voffset, face_id;
4540
4541 xassert (s->first_glyph->type == STRETCH_GLYPH);
4542
4543 glyph = s->row->glyphs[s->area] + start;
4544 last = s->row->glyphs[s->area] + end;
4545 face_id = glyph->face_id;
4546 s->face = FACE_FROM_ID (s->f, face_id);
4547 s->font = s->face->font;
4548 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4549 s->width = glyph->pixel_width;
4550 voffset = glyph->voffset;
4551
4552 for (++glyph;
4553 (glyph < last
4554 && glyph->type == STRETCH_GLYPH
4555 && glyph->voffset == voffset
4556 && glyph->face_id == face_id);
4557 ++glyph)
4558 s->width += glyph->pixel_width;
4559
4560 /* Adjust base line for subscript/superscript text. */
4561 s->ybase += voffset;
4562
4563 xassert (s->face && s->face->gc);
4564 return glyph - s->row->glyphs[s->area];
4565 }
4566
4567
4568 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4569 of XChar2b structures for S; it can't be allocated in
4570 x_init_glyph_string because it must be allocated via `alloca'. W
4571 is the window on which S is drawn. ROW and AREA are the glyph row
4572 and area within the row from which S is constructed. START is the
4573 index of the first glyph structure covered by S. HL is a
4574 face-override for drawing S. */
4575
4576 static void
4577 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4578 struct glyph_string *s;
4579 XChar2b *char2b;
4580 struct window *w;
4581 struct glyph_row *row;
4582 enum glyph_row_area area;
4583 int start;
4584 enum draw_glyphs_face hl;
4585 {
4586 bzero (s, sizeof *s);
4587 s->w = w;
4588 s->f = XFRAME (w->frame);
4589 s->display = FRAME_X_DISPLAY (s->f);
4590 s->window = FRAME_X_WINDOW (s->f);
4591 s->char2b = char2b;
4592 s->hl = hl;
4593 s->row = row;
4594 s->area = area;
4595 s->first_glyph = row->glyphs[area] + start;
4596 s->height = row->height;
4597 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4598
4599 /* Display the internal border below the tool-bar window. */
4600 if (s->w == XWINDOW (s->f->tool_bar_window))
4601 s->y -= s->f->output_data.x->internal_border_width;
4602
4603 s->ybase = s->y + row->ascent;
4604 }
4605
4606
4607 /* Set background width of glyph string S. START is the index of the
4608 first glyph following S. LAST_X is the right-most x-position + 1
4609 in the drawing area. */
4610
4611 static INLINE void
4612 x_set_glyph_string_background_width (s, start, last_x)
4613 struct glyph_string *s;
4614 int start;
4615 int last_x;
4616 {
4617 /* If the face of this glyph string has to be drawn to the end of
4618 the drawing area, set S->extends_to_end_of_line_p. */
4619 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4620
4621 if (start == s->row->used[s->area]
4622 && s->hl == DRAW_NORMAL_TEXT
4623 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4624 || s->face->background != default_face->background
4625 || s->face->stipple != default_face->stipple))
4626 s->extends_to_end_of_line_p = 1;
4627
4628 /* If S extends its face to the end of the line, set its
4629 background_width to the distance to the right edge of the drawing
4630 area. */
4631 if (s->extends_to_end_of_line_p)
4632 s->background_width = last_x - s->x + 1;
4633 else
4634 s->background_width = s->width;
4635 }
4636
4637
4638 /* Add a glyph string for a stretch glyph to the list of strings
4639 between HEAD and TAIL. START is the index of the stretch glyph in
4640 row area AREA of glyph row ROW. END is the index of the last glyph
4641 in that glyph row area. X is the current output position assigned
4642 to the new glyph string constructed. HL overrides that face of the
4643 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4644 is the right-most x-position of the drawing area. */
4645
4646 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4647 and below -- keep them on one line. */
4648 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4649 do \
4650 { \
4651 s = (struct glyph_string *) alloca (sizeof *s); \
4652 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4653 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4654 x_append_glyph_string (&HEAD, &TAIL, s); \
4655 s->x = (X); \
4656 } \
4657 while (0)
4658
4659
4660 /* Add a glyph string for an image glyph to the list of strings
4661 between HEAD and TAIL. START is the index of the image glyph in
4662 row area AREA of glyph row ROW. END is the index of the last glyph
4663 in that glyph row area. X is the current output position assigned
4664 to the new glyph string constructed. HL overrides that face of the
4665 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4666 is the right-most x-position of the drawing area. */
4667
4668 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4669 do \
4670 { \
4671 s = (struct glyph_string *) alloca (sizeof *s); \
4672 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4673 x_fill_image_glyph_string (s); \
4674 x_append_glyph_string (&HEAD, &TAIL, s); \
4675 ++START; \
4676 s->x = (X); \
4677 } \
4678 while (0)
4679
4680
4681 /* Add a glyph string for a sequence of character glyphs to the list
4682 of strings between HEAD and TAIL. START is the index of the first
4683 glyph in row area AREA of glyph row ROW that is part of the new
4684 glyph string. END is the index of the last glyph in that glyph row
4685 area. X is the current output position assigned to the new glyph
4686 string constructed. HL overrides that face of the glyph; e.g. it
4687 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4688 right-most x-position of the drawing area. */
4689
4690 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4691 do \
4692 { \
4693 int c, face_id; \
4694 XChar2b *char2b; \
4695 \
4696 c = (ROW)->glyphs[AREA][START].u.ch; \
4697 face_id = (ROW)->glyphs[AREA][START].face_id; \
4698 \
4699 s = (struct glyph_string *) alloca (sizeof *s); \
4700 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4701 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4702 x_append_glyph_string (&HEAD, &TAIL, s); \
4703 s->x = (X); \
4704 START = x_fill_glyph_string (s, face_id, START, END, \
4705 OVERLAPS_P); \
4706 } \
4707 while (0)
4708
4709
4710 /* Add a glyph string for a composite sequence to the list of strings
4711 between HEAD and TAIL. START is the index of the first glyph in
4712 row area AREA of glyph row ROW that is part of the new glyph
4713 string. END is the index of the last glyph in that glyph row area.
4714 X is the current output position assigned to the new glyph string
4715 constructed. HL overrides that face of the glyph; e.g. it is
4716 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4717 x-position of the drawing area. */
4718
4719 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4720 do { \
4721 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4722 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4723 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4724 struct composition *cmp = composition_table[cmp_id]; \
4725 int glyph_len = cmp->glyph_len; \
4726 XChar2b *char2b; \
4727 struct face **faces; \
4728 struct glyph_string *first_s = NULL; \
4729 int n; \
4730 \
4731 base_face = base_face->ascii_face; \
4732 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4733 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4734 /* At first, fill in `char2b' and `faces'. */ \
4735 for (n = 0; n < glyph_len; n++) \
4736 { \
4737 int c = COMPOSITION_GLYPH (cmp, n); \
4738 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4739 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4740 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4741 this_face_id, char2b + n, 1); \
4742 } \
4743 \
4744 /* Make glyph_strings for each glyph sequence that is drawable by \
4745 the same face, and append them to HEAD/TAIL. */ \
4746 for (n = 0; n < cmp->glyph_len;) \
4747 { \
4748 s = (struct glyph_string *) alloca (sizeof *s); \
4749 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4750 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4751 s->cmp = cmp; \
4752 s->gidx = n; \
4753 s->x = (X); \
4754 \
4755 if (n == 0) \
4756 first_s = s; \
4757 \
4758 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4759 } \
4760 \
4761 ++START; \
4762 s = first_s; \
4763 } while (0)
4764
4765
4766 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4767 of AREA of glyph row ROW on window W between indices START and END.
4768 HL overrides the face for drawing glyph strings, e.g. it is
4769 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4770 x-positions of the drawing area.
4771
4772 This is an ugly monster macro construct because we must use alloca
4773 to allocate glyph strings (because x_draw_glyphs can be called
4774 asynchronously). */
4775
4776 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4777 do \
4778 { \
4779 HEAD = TAIL = NULL; \
4780 while (START < END) \
4781 { \
4782 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4783 switch (first_glyph->type) \
4784 { \
4785 case CHAR_GLYPH: \
4786 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4787 TAIL, HL, X, LAST_X, \
4788 OVERLAPS_P); \
4789 break; \
4790 \
4791 case COMPOSITE_GLYPH: \
4792 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4793 HEAD, TAIL, HL, X, LAST_X,\
4794 OVERLAPS_P); \
4795 break; \
4796 \
4797 case STRETCH_GLYPH: \
4798 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4799 HEAD, TAIL, HL, X, LAST_X); \
4800 break; \
4801 \
4802 case IMAGE_GLYPH: \
4803 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4804 TAIL, HL, X, LAST_X); \
4805 break; \
4806 \
4807 default: \
4808 abort (); \
4809 } \
4810 \
4811 x_set_glyph_string_background_width (s, START, LAST_X); \
4812 (X) += s->width; \
4813 } \
4814 } \
4815 while (0)
4816
4817
4818 /* Draw glyphs between START and END in AREA of ROW on window W,
4819 starting at x-position X. X is relative to AREA in W. HL is a
4820 face-override with the following meaning:
4821
4822 DRAW_NORMAL_TEXT draw normally
4823 DRAW_CURSOR draw in cursor face
4824 DRAW_MOUSE_FACE draw in mouse face.
4825 DRAW_INVERSE_VIDEO draw in mode line face
4826 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4827 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4828
4829 If REAL_START is non-null, return in *REAL_START the real starting
4830 position for display. This can be different from START in case
4831 overlapping glyphs must be displayed. If REAL_END is non-null,
4832 return in *REAL_END the real end position for display. This can be
4833 different from END in case overlapping glyphs must be displayed.
4834
4835 If OVERLAPS_P is non-zero, draw only the foreground of characters
4836 and clip to the physical height of ROW.
4837
4838 Value is the x-position reached, relative to AREA of W. */
4839
4840 static int
4841 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4842 overlaps_p)
4843 struct window *w;
4844 int x;
4845 struct glyph_row *row;
4846 enum glyph_row_area area;
4847 int start, end;
4848 enum draw_glyphs_face hl;
4849 int *real_start, *real_end;
4850 int overlaps_p;
4851 {
4852 struct glyph_string *head, *tail;
4853 struct glyph_string *s;
4854 int last_x, area_width;
4855 int x_reached;
4856 int i, j;
4857
4858 /* Let's rather be paranoid than getting a SEGV. */
4859 end = min (end, row->used[area]);
4860 start = max (0, start);
4861 start = min (end, start);
4862 if (real_start)
4863 *real_start = start;
4864 if (real_end)
4865 *real_end = end;
4866
4867 /* Translate X to frame coordinates. Set last_x to the right
4868 end of the drawing area. */
4869 if (row->full_width_p)
4870 {
4871 /* X is relative to the left edge of W, without scroll bars
4872 or flag areas. */
4873 struct frame *f = XFRAME (w->frame);
4874 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4875 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4876
4877 x += window_left_x;
4878 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4879 last_x = window_left_x + area_width;
4880
4881 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4882 {
4883 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4884 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4885 last_x += width;
4886 else
4887 x -= width;
4888 }
4889
4890 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4891 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4892 }
4893 else
4894 {
4895 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4896 area_width = window_box_width (w, area);
4897 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4898 }
4899
4900 /* Build a doubly-linked list of glyph_string structures between
4901 head and tail from what we have to draw. Note that the macro
4902 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4903 the reason we use a separate variable `i'. */
4904 i = start;
4905 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4906 overlaps_p);
4907 if (tail)
4908 x_reached = tail->x + tail->background_width;
4909 else
4910 x_reached = x;
4911
4912 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4913 the row, redraw some glyphs in front or following the glyph
4914 strings built above. */
4915 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4916 {
4917 int dummy_x = 0;
4918 struct glyph_string *h, *t;
4919
4920 /* Compute overhangs for all glyph strings. */
4921 for (s = head; s; s = s->next)
4922 x_compute_glyph_string_overhangs (s);
4923
4924 /* Prepend glyph strings for glyphs in front of the first glyph
4925 string that are overwritten because of the first glyph
4926 string's left overhang. The background of all strings
4927 prepended must be drawn because the first glyph string
4928 draws over it. */
4929 i = x_left_overwritten (head);
4930 if (i >= 0)
4931 {
4932 j = i;
4933 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4934 DRAW_NORMAL_TEXT, dummy_x, last_x,
4935 overlaps_p);
4936 start = i;
4937 if (real_start)
4938 *real_start = start;
4939 x_compute_overhangs_and_x (t, head->x, 1);
4940 x_prepend_glyph_string_lists (&head, &tail, h, t);
4941 }
4942
4943 /* Prepend glyph strings for glyphs in front of the first glyph
4944 string that overwrite that glyph string because of their
4945 right overhang. For these strings, only the foreground must
4946 be drawn, because it draws over the glyph string at `head'.
4947 The background must not be drawn because this would overwrite
4948 right overhangs of preceding glyphs for which no glyph
4949 strings exist. */
4950 i = x_left_overwriting (head);
4951 if (i >= 0)
4952 {
4953 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4954 DRAW_NORMAL_TEXT, dummy_x, last_x,
4955 overlaps_p);
4956 for (s = h; s; s = s->next)
4957 s->background_filled_p = 1;
4958 if (real_start)
4959 *real_start = i;
4960 x_compute_overhangs_and_x (t, head->x, 1);
4961 x_prepend_glyph_string_lists (&head, &tail, h, t);
4962 }
4963
4964 /* Append glyphs strings for glyphs following the last glyph
4965 string tail that are overwritten by tail. The background of
4966 these strings has to be drawn because tail's foreground draws
4967 over it. */
4968 i = x_right_overwritten (tail);
4969 if (i >= 0)
4970 {
4971 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4972 DRAW_NORMAL_TEXT, x, last_x,
4973 overlaps_p);
4974 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4975 x_append_glyph_string_lists (&head, &tail, h, t);
4976 if (real_end)
4977 *real_end = i;
4978 }
4979
4980 /* Append glyph strings for glyphs following the last glyph
4981 string tail that overwrite tail. The foreground of such
4982 glyphs has to be drawn because it writes into the background
4983 of tail. The background must not be drawn because it could
4984 paint over the foreground of following glyphs. */
4985 i = x_right_overwriting (tail);
4986 if (i >= 0)
4987 {
4988 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4989 DRAW_NORMAL_TEXT, x, last_x,
4990 overlaps_p);
4991 for (s = h; s; s = s->next)
4992 s->background_filled_p = 1;
4993 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4994 x_append_glyph_string_lists (&head, &tail, h, t);
4995 if (real_end)
4996 *real_end = i;
4997 }
4998 }
4999
5000 /* Draw all strings. */
5001 for (s = head; s; s = s->next)
5002 x_draw_glyph_string (s);
5003
5004 /* Value is the x-position up to which drawn, relative to AREA of W.
5005 This doesn't include parts drawn because of overhangs. */
5006 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5007 if (!row->full_width_p)
5008 {
5009 if (area > LEFT_MARGIN_AREA)
5010 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5011 if (area > TEXT_AREA)
5012 x_reached -= window_box_width (w, TEXT_AREA);
5013 }
5014
5015 return x_reached;
5016 }
5017
5018
5019 /* Fix the display of area AREA of overlapping row ROW in window W. */
5020
5021 static void
5022 x_fix_overlapping_area (w, row, area)
5023 struct window *w;
5024 struct glyph_row *row;
5025 enum glyph_row_area area;
5026 {
5027 int i, x;
5028
5029 BLOCK_INPUT;
5030
5031 if (area == LEFT_MARGIN_AREA)
5032 x = 0;
5033 else if (area == TEXT_AREA)
5034 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5035 else
5036 x = (window_box_width (w, LEFT_MARGIN_AREA)
5037 + window_box_width (w, TEXT_AREA));
5038
5039 for (i = 0; i < row->used[area];)
5040 {
5041 if (row->glyphs[area][i].overlaps_vertically_p)
5042 {
5043 int start = i, start_x = x;
5044
5045 do
5046 {
5047 x += row->glyphs[area][i].pixel_width;
5048 ++i;
5049 }
5050 while (i < row->used[area]
5051 && row->glyphs[area][i].overlaps_vertically_p);
5052
5053 x_draw_glyphs (w, start_x, row, area, start, i,
5054 (row->inverse_p
5055 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5056 NULL, NULL, 1);
5057 }
5058 else
5059 {
5060 x += row->glyphs[area][i].pixel_width;
5061 ++i;
5062 }
5063 }
5064
5065 UNBLOCK_INPUT;
5066 }
5067
5068
5069 /* Output LEN glyphs starting at START at the nominal cursor position.
5070 Advance the nominal cursor over the text. The global variable
5071 updated_window contains the window being updated, updated_row is
5072 the glyph row being updated, and updated_area is the area of that
5073 row being updated. */
5074
5075 static void
5076 x_write_glyphs (start, len)
5077 struct glyph *start;
5078 int len;
5079 {
5080 int x, hpos, real_start, real_end;
5081
5082 xassert (updated_window && updated_row);
5083 BLOCK_INPUT;
5084
5085 /* Write glyphs. */
5086
5087 hpos = start - updated_row->glyphs[updated_area];
5088 x = x_draw_glyphs (updated_window, output_cursor.x,
5089 updated_row, updated_area,
5090 hpos, hpos + len,
5091 (updated_row->inverse_p
5092 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5093 &real_start, &real_end, 0);
5094
5095 /* If we drew over the cursor, note that it is not visible any more. */
5096 note_overwritten_text_cursor (updated_window, real_start,
5097 real_end - real_start);
5098
5099 UNBLOCK_INPUT;
5100
5101 /* Advance the output cursor. */
5102 output_cursor.hpos += len;
5103 output_cursor.x = x;
5104 }
5105
5106
5107 /* Insert LEN glyphs from START at the nominal cursor position. */
5108
5109 static void
5110 x_insert_glyphs (start, len)
5111 struct glyph *start;
5112 register int len;
5113 {
5114 struct frame *f;
5115 struct window *w;
5116 int line_height, shift_by_width, shifted_region_width;
5117 struct glyph_row *row;
5118 struct glyph *glyph;
5119 int frame_x, frame_y, hpos, real_start, real_end;
5120
5121 xassert (updated_window && updated_row);
5122 BLOCK_INPUT;
5123 w = updated_window;
5124 f = XFRAME (WINDOW_FRAME (w));
5125
5126 /* Get the height of the line we are in. */
5127 row = updated_row;
5128 line_height = row->height;
5129
5130 /* Get the width of the glyphs to insert. */
5131 shift_by_width = 0;
5132 for (glyph = start; glyph < start + len; ++glyph)
5133 shift_by_width += glyph->pixel_width;
5134
5135 /* Get the width of the region to shift right. */
5136 shifted_region_width = (window_box_width (w, updated_area)
5137 - output_cursor.x
5138 - shift_by_width);
5139
5140 /* Shift right. */
5141 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
5142 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5143 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5144 f->output_data.x->normal_gc,
5145 frame_x, frame_y,
5146 shifted_region_width, line_height,
5147 frame_x + shift_by_width, frame_y);
5148
5149 /* Write the glyphs. */
5150 hpos = start - row->glyphs[updated_area];
5151 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5152 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
5153 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5154
5155 /* Advance the output cursor. */
5156 output_cursor.hpos += len;
5157 output_cursor.x += shift_by_width;
5158 UNBLOCK_INPUT;
5159 }
5160
5161
5162 /* Delete N glyphs at the nominal cursor position. Not implemented
5163 for X frames. */
5164
5165 static void
5166 x_delete_glyphs (n)
5167 register int n;
5168 {
5169 abort ();
5170 }
5171
5172
5173 /* Erase the current text line from the nominal cursor position
5174 (inclusive) to pixel column TO_X (exclusive). The idea is that
5175 everything from TO_X onward is already erased.
5176
5177 TO_X is a pixel position relative to updated_area of
5178 updated_window. TO_X == -1 means clear to the end of this area. */
5179
5180 static void
5181 x_clear_end_of_line (to_x)
5182 int to_x;
5183 {
5184 struct frame *f;
5185 struct window *w = updated_window;
5186 int max_x, min_y, max_y;
5187 int from_x, from_y, to_y;
5188
5189 xassert (updated_window && updated_row);
5190 f = XFRAME (w->frame);
5191
5192 if (updated_row->full_width_p)
5193 {
5194 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5195 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5196 && !w->pseudo_window_p)
5197 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5198 }
5199 else
5200 max_x = window_box_width (w, updated_area);
5201 max_y = window_text_bottom_y (w);
5202
5203 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5204 of window. For TO_X > 0, truncate to end of drawing area. */
5205 if (to_x == 0)
5206 return;
5207 else if (to_x < 0)
5208 to_x = max_x;
5209 else
5210 to_x = min (to_x, max_x);
5211
5212 to_y = min (max_y, output_cursor.y + updated_row->height);
5213
5214 /* Notice if the cursor will be cleared by this operation. */
5215 if (!updated_row->full_width_p)
5216 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
5217
5218 from_x = output_cursor.x;
5219
5220 /* Translate to frame coordinates. */
5221 if (updated_row->full_width_p)
5222 {
5223 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5224 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5225 }
5226 else
5227 {
5228 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5229 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5230 }
5231
5232 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5233 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5234 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5235
5236 /* Prevent inadvertently clearing to end of the X window. */
5237 if (to_x > from_x && to_y > from_y)
5238 {
5239 BLOCK_INPUT;
5240 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5241 from_x, from_y, to_x - from_x, to_y - from_y,
5242 False);
5243 UNBLOCK_INPUT;
5244 }
5245 }
5246
5247
5248 /* Clear entire frame. If updating_frame is non-null, clear that
5249 frame. Otherwise clear the selected frame. */
5250
5251 static void
5252 x_clear_frame ()
5253 {
5254 struct frame *f;
5255
5256 if (updating_frame)
5257 f = updating_frame;
5258 else
5259 f = SELECTED_FRAME ();
5260
5261 /* Clearing the frame will erase any cursor, so mark them all as no
5262 longer visible. */
5263 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5264 output_cursor.hpos = output_cursor.vpos = 0;
5265 output_cursor.x = -1;
5266
5267 /* We don't set the output cursor here because there will always
5268 follow an explicit cursor_to. */
5269 BLOCK_INPUT;
5270 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5271
5272 /* We have to clear the scroll bars, too. If we have changed
5273 colors or something like that, then they should be notified. */
5274 x_scroll_bar_clear (f);
5275
5276 XFlush (FRAME_X_DISPLAY (f));
5277 UNBLOCK_INPUT;
5278 }
5279
5280
5281 \f
5282 /* Invert the middle quarter of the frame for .15 sec. */
5283
5284 /* We use the select system call to do the waiting, so we have to make
5285 sure it's available. If it isn't, we just won't do visual bells. */
5286
5287 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5288
5289
5290 /* Subtract the `struct timeval' values X and Y, storing the result in
5291 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5292
5293 static int
5294 timeval_subtract (result, x, y)
5295 struct timeval *result, x, y;
5296 {
5297 /* Perform the carry for the later subtraction by updating y. This
5298 is safer because on some systems the tv_sec member is unsigned. */
5299 if (x.tv_usec < y.tv_usec)
5300 {
5301 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5302 y.tv_usec -= 1000000 * nsec;
5303 y.tv_sec += nsec;
5304 }
5305
5306 if (x.tv_usec - y.tv_usec > 1000000)
5307 {
5308 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5309 y.tv_usec += 1000000 * nsec;
5310 y.tv_sec -= nsec;
5311 }
5312
5313 /* Compute the time remaining to wait. tv_usec is certainly
5314 positive. */
5315 result->tv_sec = x.tv_sec - y.tv_sec;
5316 result->tv_usec = x.tv_usec - y.tv_usec;
5317
5318 /* Return indication of whether the result should be considered
5319 negative. */
5320 return x.tv_sec < y.tv_sec;
5321 }
5322
5323 void
5324 XTflash (f)
5325 struct frame *f;
5326 {
5327 BLOCK_INPUT;
5328
5329 {
5330 GC gc;
5331
5332 /* Create a GC that will use the GXxor function to flip foreground
5333 pixels into background pixels. */
5334 {
5335 XGCValues values;
5336
5337 values.function = GXxor;
5338 values.foreground = (f->output_data.x->foreground_pixel
5339 ^ f->output_data.x->background_pixel);
5340
5341 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5342 GCFunction | GCForeground, &values);
5343 }
5344
5345 {
5346 /* Get the height not including a menu bar widget. */
5347 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5348 /* Height of each line to flash. */
5349 int flash_height = FRAME_LINE_HEIGHT (f);
5350 /* These will be the left and right margins of the rectangles. */
5351 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5352 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5353
5354 int width;
5355
5356 /* Don't flash the area between a scroll bar and the frame
5357 edge it is next to. */
5358 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5359 {
5360 case vertical_scroll_bar_left:
5361 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5362 break;
5363
5364 case vertical_scroll_bar_right:
5365 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5366 break;
5367
5368 default:
5369 break;
5370 }
5371
5372 width = flash_right - flash_left;
5373
5374 /* If window is tall, flash top and bottom line. */
5375 if (height > 3 * FRAME_LINE_HEIGHT (f))
5376 {
5377 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5378 flash_left,
5379 (FRAME_INTERNAL_BORDER_WIDTH (f)
5380 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5381 width, flash_height);
5382 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5383 flash_left,
5384 (height - flash_height
5385 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5386 width, flash_height);
5387 }
5388 else
5389 /* If it is short, flash it all. */
5390 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5391 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5392 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5393
5394 x_flush (f);
5395
5396 {
5397 struct timeval wakeup;
5398
5399 EMACS_GET_TIME (wakeup);
5400
5401 /* Compute time to wait until, propagating carry from usecs. */
5402 wakeup.tv_usec += 150000;
5403 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5404 wakeup.tv_usec %= 1000000;
5405
5406 /* Keep waiting until past the time wakeup. */
5407 while (1)
5408 {
5409 struct timeval timeout;
5410
5411 EMACS_GET_TIME (timeout);
5412
5413 /* In effect, timeout = wakeup - timeout.
5414 Break if result would be negative. */
5415 if (timeval_subtract (&timeout, wakeup, timeout))
5416 break;
5417
5418 /* Try to wait that long--but we might wake up sooner. */
5419 select (0, NULL, NULL, NULL, &timeout);
5420 }
5421 }
5422
5423 /* If window is tall, flash top and bottom line. */
5424 if (height > 3 * FRAME_LINE_HEIGHT (f))
5425 {
5426 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5427 flash_left,
5428 (FRAME_INTERNAL_BORDER_WIDTH (f)
5429 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5430 width, flash_height);
5431 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5432 flash_left,
5433 (height - flash_height
5434 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5435 width, flash_height);
5436 }
5437 else
5438 /* If it is short, flash it all. */
5439 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5440 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5441 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5442
5443 XFreeGC (FRAME_X_DISPLAY (f), gc);
5444 x_flush (f);
5445 }
5446 }
5447
5448 UNBLOCK_INPUT;
5449 }
5450
5451 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5452
5453
5454 /* Make audible bell. */
5455
5456 void
5457 XTring_bell ()
5458 {
5459 struct frame *f = SELECTED_FRAME ();
5460
5461 if (FRAME_X_DISPLAY (f))
5462 {
5463 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5464 if (visible_bell)
5465 XTflash (f);
5466 else
5467 #endif
5468 {
5469 BLOCK_INPUT;
5470 XBell (FRAME_X_DISPLAY (f), 0);
5471 XFlush (FRAME_X_DISPLAY (f));
5472 UNBLOCK_INPUT;
5473 }
5474 }
5475 }
5476
5477 \f
5478 /* Specify how many text lines, from the top of the window,
5479 should be affected by insert-lines and delete-lines operations.
5480 This, and those operations, are used only within an update
5481 that is bounded by calls to x_update_begin and x_update_end. */
5482
5483 static void
5484 XTset_terminal_window (n)
5485 register int n;
5486 {
5487 /* This function intentionally left blank. */
5488 }
5489
5490
5491 \f
5492 /***********************************************************************
5493 Line Dance
5494 ***********************************************************************/
5495
5496 /* Perform an insert-lines or delete-lines operation, inserting N
5497 lines or deleting -N lines at vertical position VPOS. */
5498
5499 static void
5500 x_ins_del_lines (vpos, n)
5501 int vpos, n;
5502 {
5503 abort ();
5504 }
5505
5506
5507 /* Scroll part of the display as described by RUN. */
5508
5509 static void
5510 x_scroll_run (w, run)
5511 struct window *w;
5512 struct run *run;
5513 {
5514 struct frame *f = XFRAME (w->frame);
5515 int x, y, width, height, from_y, to_y, bottom_y;
5516
5517 /* Get frame-relative bounding box of the text display area of W,
5518 without mode lines. Include in this box the flags areas to the
5519 left and right of W. */
5520 window_box (w, -1, &x, &y, &width, &height);
5521 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5522 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5523
5524 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5525 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5526 bottom_y = y + height;
5527
5528 if (to_y < from_y)
5529 {
5530 /* Scrolling up. Make sure we don't copy part of the mode
5531 line at the bottom. */
5532 if (from_y + run->height > bottom_y)
5533 height = bottom_y - from_y;
5534 else
5535 height = run->height;
5536 }
5537 else
5538 {
5539 /* Scolling down. Make sure we don't copy over the mode line.
5540 at the bottom. */
5541 if (to_y + run->height > bottom_y)
5542 height = bottom_y - to_y;
5543 else
5544 height = run->height;
5545 }
5546
5547 BLOCK_INPUT;
5548
5549 /* Cursor off. Will be switched on again in x_update_window_end. */
5550 updated_window = w;
5551 x_clear_cursor (w);
5552
5553 XCopyArea (FRAME_X_DISPLAY (f),
5554 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5555 f->output_data.x->normal_gc,
5556 x, from_y,
5557 width, height,
5558 x, to_y);
5559
5560 UNBLOCK_INPUT;
5561 }
5562
5563
5564 \f
5565 /***********************************************************************
5566 Exposure Events
5567 ***********************************************************************/
5568
5569 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5570 corner of the exposed rectangle. W and H are width and height of
5571 the exposed area. All are pixel values. W or H zero means redraw
5572 the entire frame. */
5573
5574 static void
5575 expose_frame (f, x, y, w, h)
5576 struct frame *f;
5577 int x, y, w, h;
5578 {
5579 XRectangle r;
5580
5581 TRACE ((stderr, "expose_frame "));
5582
5583 /* No need to redraw if frame will be redrawn soon. */
5584 if (FRAME_GARBAGED_P (f))
5585 {
5586 TRACE ((stderr, " garbaged\n"));
5587 return;
5588 }
5589
5590 /* If basic faces haven't been realized yet, there is no point in
5591 trying to redraw anything. This can happen when we get an expose
5592 event while Emacs is starting, e.g. by moving another window. */
5593 if (FRAME_FACE_CACHE (f) == NULL
5594 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5595 {
5596 TRACE ((stderr, " no faces\n"));
5597 return;
5598 }
5599
5600 if (w == 0 || h == 0)
5601 {
5602 r.x = r.y = 0;
5603 r.width = CANON_X_UNIT (f) * f->width;
5604 r.height = CANON_Y_UNIT (f) * f->height;
5605 }
5606 else
5607 {
5608 r.x = x;
5609 r.y = y;
5610 r.width = w;
5611 r.height = h;
5612 }
5613
5614 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5615 expose_window_tree (XWINDOW (f->root_window), &r);
5616
5617 if (WINDOWP (f->tool_bar_window))
5618 {
5619 struct window *w = XWINDOW (f->tool_bar_window);
5620 XRectangle window_rect;
5621 XRectangle intersection_rect;
5622 int window_x, window_y, window_width, window_height;
5623
5624
5625 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5626 window_rect.x = window_x;
5627 window_rect.y = window_y;
5628 window_rect.width = window_width;
5629 window_rect.height = window_height;
5630
5631 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5632 expose_window (w, &intersection_rect);
5633 }
5634
5635 #ifndef USE_X_TOOLKIT
5636 if (WINDOWP (f->menu_bar_window))
5637 {
5638 struct window *w = XWINDOW (f->menu_bar_window);
5639 XRectangle window_rect;
5640 XRectangle intersection_rect;
5641 int window_x, window_y, window_width, window_height;
5642
5643
5644 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5645 window_rect.x = window_x;
5646 window_rect.y = window_y;
5647 window_rect.width = window_width;
5648 window_rect.height = window_height;
5649
5650 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5651 expose_window (w, &intersection_rect);
5652 }
5653 #endif /* not USE_X_TOOLKIT */
5654 }
5655
5656
5657 /* Redraw (parts) of all windows in the window tree rooted at W that
5658 intersect R. R contains frame pixel coordinates. */
5659
5660 static void
5661 expose_window_tree (w, r)
5662 struct window *w;
5663 XRectangle *r;
5664 {
5665 while (w)
5666 {
5667 if (!NILP (w->hchild))
5668 expose_window_tree (XWINDOW (w->hchild), r);
5669 else if (!NILP (w->vchild))
5670 expose_window_tree (XWINDOW (w->vchild), r);
5671 else
5672 {
5673 XRectangle window_rect;
5674 XRectangle intersection_rect;
5675 struct frame *f = XFRAME (w->frame);
5676 int window_x, window_y, window_width, window_height;
5677
5678 /* Frame-relative pixel rectangle of W. */
5679 window_box (w, -1, &window_x, &window_y, &window_width,
5680 &window_height);
5681 window_rect.x
5682 = (window_x
5683 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5684 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5685 window_rect.y = window_y;
5686 window_rect.width
5687 = (window_width
5688 + FRAME_X_FLAGS_AREA_WIDTH (f)
5689 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5690 window_rect.height
5691 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5692
5693 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5694 expose_window (w, &intersection_rect);
5695 }
5696
5697 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5698 }
5699 }
5700
5701
5702 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5703 which intersects rectangle R. R is in window-relative coordinates. */
5704
5705 static void
5706 expose_area (w, row, r, area)
5707 struct window *w;
5708 struct glyph_row *row;
5709 XRectangle *r;
5710 enum glyph_row_area area;
5711 {
5712 int x;
5713 struct glyph *first = row->glyphs[area];
5714 struct glyph *end = row->glyphs[area] + row->used[area];
5715 struct glyph *last;
5716 int first_x;
5717
5718 /* Set x to the window-relative start position for drawing glyphs of
5719 AREA. The first glyph of the text area can be partially visible.
5720 The first glyphs of other areas cannot. */
5721 if (area == LEFT_MARGIN_AREA)
5722 x = 0;
5723 else if (area == TEXT_AREA)
5724 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5725 else
5726 x = (window_box_width (w, LEFT_MARGIN_AREA)
5727 + window_box_width (w, TEXT_AREA));
5728
5729 if (area == TEXT_AREA && row->fill_line_p)
5730 /* If row extends face to end of line write the whole line. */
5731 x_draw_glyphs (w, x, row, area,
5732 0, row->used[area],
5733 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5734 NULL, NULL, 0);
5735 else
5736 {
5737 /* Find the first glyph that must be redrawn. */
5738 while (first < end
5739 && x + first->pixel_width < r->x)
5740 {
5741 x += first->pixel_width;
5742 ++first;
5743 }
5744
5745 /* Find the last one. */
5746 last = first;
5747 first_x = x;
5748 while (last < end
5749 && x < r->x + r->width)
5750 {
5751 x += last->pixel_width;
5752 ++last;
5753 }
5754
5755 /* Repaint. */
5756 if (last > first)
5757 x_draw_glyphs (w, first_x, row, area,
5758 first - row->glyphs[area],
5759 last - row->glyphs[area],
5760 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5761 NULL, NULL, 0);
5762 }
5763 }
5764
5765
5766 /* Redraw the parts of the glyph row ROW on window W intersecting
5767 rectangle R. R is in window-relative coordinates. */
5768
5769 static void
5770 expose_line (w, row, r)
5771 struct window *w;
5772 struct glyph_row *row;
5773 XRectangle *r;
5774 {
5775 xassert (row->enabled_p);
5776
5777 if (row->mode_line_p || w->pseudo_window_p)
5778 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5779 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5780 NULL, NULL, 0);
5781 else
5782 {
5783 if (row->used[LEFT_MARGIN_AREA])
5784 expose_area (w, row, r, LEFT_MARGIN_AREA);
5785 if (row->used[TEXT_AREA])
5786 expose_area (w, row, r, TEXT_AREA);
5787 if (row->used[RIGHT_MARGIN_AREA])
5788 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5789 x_draw_row_bitmaps (w, row);
5790 }
5791 }
5792
5793
5794 /* Return non-zero if W's cursor intersects rectangle R. */
5795
5796 static int
5797 x_phys_cursor_in_rect_p (w, r)
5798 struct window *w;
5799 XRectangle *r;
5800 {
5801 XRectangle cr, result;
5802 struct glyph *cursor_glyph;
5803
5804 cursor_glyph = get_phys_cursor_glyph (w);
5805 if (cursor_glyph)
5806 {
5807 cr.x = w->phys_cursor.x;
5808 cr.y = w->phys_cursor.y;
5809 cr.width = cursor_glyph->pixel_width;
5810 cr.height = w->phys_cursor_height;
5811 return x_intersect_rectangles (&cr, r, &result);
5812 }
5813 else
5814 return 0;
5815 }
5816
5817
5818 /* Redraw a rectangle of window W. R is a rectangle in window
5819 relative coordinates. Call this function with input blocked. */
5820
5821 static void
5822 expose_window (w, r)
5823 struct window *w;
5824 XRectangle *r;
5825 {
5826 struct glyph_row *row;
5827 int y;
5828 int yb = window_text_bottom_y (w);
5829 int cursor_cleared_p;
5830
5831 /* If window is not yet fully initialized, do nothing. This can
5832 happen when toolkit scroll bars are used and a window is split.
5833 Reconfiguring the scroll bar will generate an expose for a newly
5834 created window. */
5835 if (w->current_matrix == NULL)
5836 return;
5837
5838 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5839 r->x, r->y, r->width, r->height));
5840
5841 /* Convert to window coordinates. */
5842 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5843 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5844
5845 /* Turn off the cursor. */
5846 if (!w->pseudo_window_p
5847 && x_phys_cursor_in_rect_p (w, r))
5848 {
5849 x_clear_cursor (w);
5850 cursor_cleared_p = 1;
5851 }
5852 else
5853 cursor_cleared_p = 0;
5854
5855 /* Find the first row intersecting the rectangle R. */
5856 row = w->current_matrix->rows;
5857 y = 0;
5858 while (row->enabled_p
5859 && y < yb
5860 && y + row->height < r->y)
5861 {
5862 y += row->height;
5863 ++row;
5864 }
5865
5866 /* Display the text in the rectangle, one text line at a time. */
5867 while (row->enabled_p
5868 && y < yb
5869 && y < r->y + r->height)
5870 {
5871 expose_line (w, row, r);
5872 y += row->height;
5873 ++row;
5874 }
5875
5876 /* Display the mode line if there is one. */
5877 if (WINDOW_WANTS_MODELINE_P (w)
5878 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5879 row->enabled_p)
5880 && row->y < r->y + r->height)
5881 expose_line (w, row, r);
5882
5883 if (!w->pseudo_window_p)
5884 {
5885 /* Draw border between windows. */
5886 x_draw_vertical_border (w);
5887
5888 /* Turn the cursor on again. */
5889 if (cursor_cleared_p)
5890 x_update_window_cursor (w, 1);
5891 }
5892 }
5893
5894
5895 /* Determine the intersection of two rectangles R1 and R2. Return
5896 the intersection in *RESULT. Value is non-zero if RESULT is not
5897 empty. */
5898
5899 static int
5900 x_intersect_rectangles (r1, r2, result)
5901 XRectangle *r1, *r2, *result;
5902 {
5903 XRectangle *left, *right;
5904 XRectangle *upper, *lower;
5905 int intersection_p = 0;
5906
5907 /* Rearrange so that R1 is the left-most rectangle. */
5908 if (r1->x < r2->x)
5909 left = r1, right = r2;
5910 else
5911 left = r2, right = r1;
5912
5913 /* X0 of the intersection is right.x0, if this is inside R1,
5914 otherwise there is no intersection. */
5915 if (right->x <= left->x + left->width)
5916 {
5917 result->x = right->x;
5918
5919 /* The right end of the intersection is the minimum of the
5920 the right ends of left and right. */
5921 result->width = (min (left->x + left->width, right->x + right->width)
5922 - result->x);
5923
5924 /* Same game for Y. */
5925 if (r1->y < r2->y)
5926 upper = r1, lower = r2;
5927 else
5928 upper = r2, lower = r1;
5929
5930 /* The upper end of the intersection is lower.y0, if this is inside
5931 of upper. Otherwise, there is no intersection. */
5932 if (lower->y <= upper->y + upper->height)
5933 {
5934 result->y = lower->y;
5935
5936 /* The lower end of the intersection is the minimum of the lower
5937 ends of upper and lower. */
5938 result->height = (min (lower->y + lower->height,
5939 upper->y + upper->height)
5940 - result->y);
5941 intersection_p = 1;
5942 }
5943 }
5944
5945 return intersection_p;
5946 }
5947
5948
5949
5950
5951 \f
5952 static void
5953 frame_highlight (f)
5954 struct frame *f;
5955 {
5956 /* We used to only do this if Vx_no_window_manager was non-nil, but
5957 the ICCCM (section 4.1.6) says that the window's border pixmap
5958 and border pixel are window attributes which are "private to the
5959 client", so we can always change it to whatever we want. */
5960 BLOCK_INPUT;
5961 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5962 f->output_data.x->border_pixel);
5963 UNBLOCK_INPUT;
5964 x_update_cursor (f, 1);
5965 }
5966
5967 static void
5968 frame_unhighlight (f)
5969 struct frame *f;
5970 {
5971 /* We used to only do this if Vx_no_window_manager was non-nil, but
5972 the ICCCM (section 4.1.6) says that the window's border pixmap
5973 and border pixel are window attributes which are "private to the
5974 client", so we can always change it to whatever we want. */
5975 BLOCK_INPUT;
5976 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5977 f->output_data.x->border_tile);
5978 UNBLOCK_INPUT;
5979 x_update_cursor (f, 1);
5980 }
5981
5982 /* The focus has changed. Update the frames as necessary to reflect
5983 the new situation. Note that we can't change the selected frame
5984 here, because the Lisp code we are interrupting might become confused.
5985 Each event gets marked with the frame in which it occurred, so the
5986 Lisp code can tell when the switch took place by examining the events. */
5987
5988 static void
5989 x_new_focus_frame (dpyinfo, frame)
5990 struct x_display_info *dpyinfo;
5991 struct frame *frame;
5992 {
5993 struct frame *old_focus = dpyinfo->x_focus_frame;
5994
5995 if (frame != dpyinfo->x_focus_frame)
5996 {
5997 /* Set this before calling other routines, so that they see
5998 the correct value of x_focus_frame. */
5999 dpyinfo->x_focus_frame = frame;
6000
6001 if (old_focus && old_focus->auto_lower)
6002 x_lower_frame (old_focus);
6003
6004 #if 0
6005 selected_frame = frame;
6006 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6007 selected_frame);
6008 Fselect_window (selected_frame->selected_window);
6009 choose_minibuf_frame ();
6010 #endif /* ! 0 */
6011
6012 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6013 pending_autoraise_frame = dpyinfo->x_focus_frame;
6014 else
6015 pending_autoraise_frame = 0;
6016 }
6017
6018 x_frame_rehighlight (dpyinfo);
6019 }
6020
6021 /* Handle an event saying the mouse has moved out of an Emacs frame. */
6022
6023 void
6024 x_mouse_leave (dpyinfo)
6025 struct x_display_info *dpyinfo;
6026 {
6027 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
6028 }
6029
6030 /* The focus has changed, or we have redirected a frame's focus to
6031 another frame (this happens when a frame uses a surrogate
6032 mini-buffer frame). Shift the highlight as appropriate.
6033
6034 The FRAME argument doesn't necessarily have anything to do with which
6035 frame is being highlighted or un-highlighted; we only use it to find
6036 the appropriate X display info. */
6037
6038 static void
6039 XTframe_rehighlight (frame)
6040 struct frame *frame;
6041 {
6042 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6043 }
6044
6045 static void
6046 x_frame_rehighlight (dpyinfo)
6047 struct x_display_info *dpyinfo;
6048 {
6049 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6050
6051 if (dpyinfo->x_focus_frame)
6052 {
6053 dpyinfo->x_highlight_frame
6054 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6055 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6056 : dpyinfo->x_focus_frame);
6057 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
6058 {
6059 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6060 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
6061 }
6062 }
6063 else
6064 dpyinfo->x_highlight_frame = 0;
6065
6066 if (dpyinfo->x_highlight_frame != old_highlight)
6067 {
6068 if (old_highlight)
6069 frame_unhighlight (old_highlight);
6070 if (dpyinfo->x_highlight_frame)
6071 frame_highlight (dpyinfo->x_highlight_frame);
6072 }
6073 }
6074
6075
6076 \f
6077 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
6078
6079 /* Initialize mode_switch_bit and modifier_meaning. */
6080 static void
6081 x_find_modifier_meanings (dpyinfo)
6082 struct x_display_info *dpyinfo;
6083 {
6084 int min_code, max_code;
6085 KeySym *syms;
6086 int syms_per_code;
6087 XModifierKeymap *mods;
6088
6089 dpyinfo->meta_mod_mask = 0;
6090 dpyinfo->shift_lock_mask = 0;
6091 dpyinfo->alt_mod_mask = 0;
6092 dpyinfo->super_mod_mask = 0;
6093 dpyinfo->hyper_mod_mask = 0;
6094
6095 #ifdef HAVE_X11R4
6096 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
6097 #else
6098 min_code = dpyinfo->display->min_keycode;
6099 max_code = dpyinfo->display->max_keycode;
6100 #endif
6101
6102 syms = XGetKeyboardMapping (dpyinfo->display,
6103 min_code, max_code - min_code + 1,
6104 &syms_per_code);
6105 mods = XGetModifierMapping (dpyinfo->display);
6106
6107 /* Scan the modifier table to see which modifier bits the Meta and
6108 Alt keysyms are on. */
6109 {
6110 int row, col; /* The row and column in the modifier table. */
6111
6112 for (row = 3; row < 8; row++)
6113 for (col = 0; col < mods->max_keypermod; col++)
6114 {
6115 KeyCode code
6116 = mods->modifiermap[(row * mods->max_keypermod) + col];
6117
6118 /* Zeroes are used for filler. Skip them. */
6119 if (code == 0)
6120 continue;
6121
6122 /* Are any of this keycode's keysyms a meta key? */
6123 {
6124 int code_col;
6125
6126 for (code_col = 0; code_col < syms_per_code; code_col++)
6127 {
6128 int sym = syms[((code - min_code) * syms_per_code) + code_col];
6129
6130 switch (sym)
6131 {
6132 case XK_Meta_L:
6133 case XK_Meta_R:
6134 dpyinfo->meta_mod_mask |= (1 << row);
6135 break;
6136
6137 case XK_Alt_L:
6138 case XK_Alt_R:
6139 dpyinfo->alt_mod_mask |= (1 << row);
6140 break;
6141
6142 case XK_Hyper_L:
6143 case XK_Hyper_R:
6144 dpyinfo->hyper_mod_mask |= (1 << row);
6145 break;
6146
6147 case XK_Super_L:
6148 case XK_Super_R:
6149 dpyinfo->super_mod_mask |= (1 << row);
6150 break;
6151
6152 case XK_Shift_Lock:
6153 /* Ignore this if it's not on the lock modifier. */
6154 if ((1 << row) == LockMask)
6155 dpyinfo->shift_lock_mask = LockMask;
6156 break;
6157 }
6158 }
6159 }
6160 }
6161 }
6162
6163 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
6164 if (! dpyinfo->meta_mod_mask)
6165 {
6166 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6167 dpyinfo->alt_mod_mask = 0;
6168 }
6169
6170 /* If some keys are both alt and meta,
6171 make them just meta, not alt. */
6172 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
6173 {
6174 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
6175 }
6176
6177 XFree ((char *) syms);
6178 XFreeModifiermap (mods);
6179 }
6180
6181 /* Convert between the modifier bits X uses and the modifier bits
6182 Emacs uses. */
6183
6184 static unsigned int
6185 x_x_to_emacs_modifiers (dpyinfo, state)
6186 struct x_display_info *dpyinfo;
6187 unsigned int state;
6188 {
6189 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6190 | ((state & ControlMask) ? ctrl_modifier : 0)
6191 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6192 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6193 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6194 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
6195 }
6196
6197 static unsigned int
6198 x_emacs_to_x_modifiers (dpyinfo, state)
6199 struct x_display_info *dpyinfo;
6200 unsigned int state;
6201 {
6202 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6203 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6204 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6205 | ((state & shift_modifier) ? ShiftMask : 0)
6206 | ((state & ctrl_modifier) ? ControlMask : 0)
6207 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
6208 }
6209
6210 /* Convert a keysym to its name. */
6211
6212 char *
6213 x_get_keysym_name (keysym)
6214 KeySym keysym;
6215 {
6216 char *value;
6217
6218 BLOCK_INPUT;
6219 value = XKeysymToString (keysym);
6220 UNBLOCK_INPUT;
6221
6222 return value;
6223 }
6224
6225
6226 \f
6227 /* Mouse clicks and mouse movement. Rah. */
6228
6229 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6230 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6231 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6232 not force the value into range. */
6233
6234 void
6235 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6236 FRAME_PTR f;
6237 register int pix_x, pix_y;
6238 register int *x, *y;
6239 XRectangle *bounds;
6240 int noclip;
6241 {
6242 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6243 even for negative values. */
6244 if (pix_x < 0)
6245 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6246 if (pix_y < 0)
6247 pix_y -= (f)->output_data.x->line_height - 1;
6248
6249 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6250 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6251
6252 if (bounds)
6253 {
6254 bounds->width = FONT_WIDTH (f->output_data.x->font);
6255 bounds->height = f->output_data.x->line_height;
6256 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6257 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6258 }
6259
6260 if (!noclip)
6261 {
6262 if (pix_x < 0)
6263 pix_x = 0;
6264 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6265 pix_x = FRAME_WINDOW_WIDTH (f);
6266
6267 if (pix_y < 0)
6268 pix_y = 0;
6269 else if (pix_y > f->height)
6270 pix_y = f->height;
6271 }
6272
6273 *x = pix_x;
6274 *y = pix_y;
6275 }
6276
6277
6278 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6279 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6280 can't tell the positions because W's display is not up to date,
6281 return 0. */
6282
6283 int
6284 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6285 struct window *w;
6286 int hpos, vpos;
6287 int *frame_x, *frame_y;
6288 {
6289 int success_p;
6290
6291 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6292 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6293
6294 if (display_completed)
6295 {
6296 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6297 struct glyph *glyph = row->glyphs[TEXT_AREA];
6298 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6299
6300 *frame_y = row->y;
6301 *frame_x = row->x;
6302 while (glyph < end)
6303 {
6304 *frame_x += glyph->pixel_width;
6305 ++glyph;
6306 }
6307
6308 success_p = 1;
6309 }
6310 else
6311 {
6312 *frame_y = *frame_x = 0;
6313 success_p = 0;
6314 }
6315
6316 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6317 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6318 return success_p;
6319 }
6320
6321
6322 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6323
6324 If the event is a button press, then note that we have grabbed
6325 the mouse. */
6326
6327 static Lisp_Object
6328 construct_mouse_click (result, event, f)
6329 struct input_event *result;
6330 XButtonEvent *event;
6331 struct frame *f;
6332 {
6333 /* Make the event type no_event; we'll change that when we decide
6334 otherwise. */
6335 result->kind = mouse_click;
6336 result->code = event->button - Button1;
6337 result->timestamp = event->time;
6338 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6339 event->state)
6340 | (event->type == ButtonRelease
6341 ? up_modifier
6342 : down_modifier));
6343
6344 XSETINT (result->x, event->x);
6345 XSETINT (result->y, event->y);
6346 XSETFRAME (result->frame_or_window, f);
6347 result->arg = Qnil;
6348 return Qnil;
6349 }
6350
6351 \f
6352 /* Function to report a mouse movement to the mainstream Emacs code.
6353 The input handler calls this.
6354
6355 We have received a mouse movement event, which is given in *event.
6356 If the mouse is over a different glyph than it was last time, tell
6357 the mainstream emacs code by setting mouse_moved. If not, ask for
6358 another motion event, so we can check again the next time it moves. */
6359
6360 static XMotionEvent last_mouse_motion_event;
6361 static Lisp_Object last_mouse_motion_frame;
6362
6363 static void
6364 note_mouse_movement (frame, event)
6365 FRAME_PTR frame;
6366 XMotionEvent *event;
6367 {
6368 last_mouse_movement_time = event->time;
6369 last_mouse_motion_event = *event;
6370 XSETFRAME (last_mouse_motion_frame, frame);
6371
6372 if (event->window != FRAME_X_WINDOW (frame))
6373 {
6374 frame->mouse_moved = 1;
6375 last_mouse_scroll_bar = Qnil;
6376 note_mouse_highlight (frame, -1, -1);
6377 }
6378
6379 /* Has the mouse moved off the glyph it was on at the last sighting? */
6380 else if (event->x < last_mouse_glyph.x
6381 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6382 || event->y < last_mouse_glyph.y
6383 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6384 {
6385 frame->mouse_moved = 1;
6386 last_mouse_scroll_bar = Qnil;
6387 note_mouse_highlight (frame, event->x, event->y);
6388 }
6389 }
6390
6391 /* This is used for debugging, to turn off note_mouse_highlight. */
6392
6393 int disable_mouse_highlight;
6394
6395
6396 \f
6397 /************************************************************************
6398 Mouse Face
6399 ************************************************************************/
6400
6401 /* Find the glyph under window-relative coordinates X/Y in window W.
6402 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6403 strings. Return in *HPOS and *VPOS the row and column number of
6404 the glyph found. Return in *AREA the glyph area containing X.
6405 Value is a pointer to the glyph found or null if X/Y is not on
6406 text, or we can't tell because W's current matrix is not up to
6407 date. */
6408
6409 static struct glyph *
6410 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6411 struct window *w;
6412 int x, y;
6413 int *hpos, *vpos, *area;
6414 {
6415 struct glyph *glyph, *end;
6416 struct glyph_row *row = NULL;
6417 int x0, i, left_area_width;
6418
6419 /* Find row containing Y. Give up if some row is not enabled. */
6420 for (i = 0; i < w->current_matrix->nrows; ++i)
6421 {
6422 row = MATRIX_ROW (w->current_matrix, i);
6423 if (!row->enabled_p)
6424 return NULL;
6425 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6426 break;
6427 }
6428
6429 *vpos = i;
6430 *hpos = 0;
6431
6432 /* Give up if Y is not in the window. */
6433 if (i == w->current_matrix->nrows)
6434 return NULL;
6435
6436 /* Get the glyph area containing X. */
6437 if (w->pseudo_window_p)
6438 {
6439 *area = TEXT_AREA;
6440 x0 = 0;
6441 }
6442 else
6443 {
6444 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6445 if (x < left_area_width)
6446 {
6447 *area = LEFT_MARGIN_AREA;
6448 x0 = 0;
6449 }
6450 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6451 {
6452 *area = TEXT_AREA;
6453 x0 = row->x + left_area_width;
6454 }
6455 else
6456 {
6457 *area = RIGHT_MARGIN_AREA;
6458 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6459 }
6460 }
6461
6462 /* Find glyph containing X. */
6463 glyph = row->glyphs[*area];
6464 end = glyph + row->used[*area];
6465 while (glyph < end)
6466 {
6467 if (x < x0 + glyph->pixel_width)
6468 {
6469 if (w->pseudo_window_p)
6470 break;
6471 else if (BUFFERP (glyph->object))
6472 break;
6473 }
6474
6475 x0 += glyph->pixel_width;
6476 ++glyph;
6477 }
6478
6479 if (glyph == end)
6480 return NULL;
6481
6482 *hpos = glyph - row->glyphs[*area];
6483 return glyph;
6484 }
6485
6486
6487 /* Convert frame-relative x/y to coordinates relative to window W.
6488 Takes pseudo-windows into account. */
6489
6490 static void
6491 frame_to_window_pixel_xy (w, x, y)
6492 struct window *w;
6493 int *x, *y;
6494 {
6495 if (w->pseudo_window_p)
6496 {
6497 /* A pseudo-window is always full-width, and starts at the
6498 left edge of the frame, plus a frame border. */
6499 struct frame *f = XFRAME (w->frame);
6500 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6501 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6502 }
6503 else
6504 {
6505 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6506 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6507 }
6508 }
6509
6510
6511 /* Take proper action when mouse has moved to the mode or header line of
6512 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6513 mode line. X is relative to the start of the text display area of
6514 W, so the width of bitmap areas and scroll bars must be subtracted
6515 to get a position relative to the start of the mode line. */
6516
6517 static void
6518 note_mode_line_highlight (w, x, mode_line_p)
6519 struct window *w;
6520 int x, mode_line_p;
6521 {
6522 struct frame *f = XFRAME (w->frame);
6523 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6524 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6525 struct glyph_row *row;
6526
6527 if (mode_line_p)
6528 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6529 else
6530 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6531
6532 if (row->enabled_p)
6533 {
6534 struct glyph *glyph, *end;
6535 Lisp_Object help, map;
6536 int x0;
6537
6538 /* Find the glyph under X. */
6539 glyph = row->glyphs[TEXT_AREA];
6540 end = glyph + row->used[TEXT_AREA];
6541 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6542 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6543
6544 while (glyph < end
6545 && x >= x0 + glyph->pixel_width)
6546 {
6547 x0 += glyph->pixel_width;
6548 ++glyph;
6549 }
6550
6551 if (glyph < end
6552 && STRINGP (glyph->object)
6553 && XSTRING (glyph->object)->intervals
6554 && glyph->charpos >= 0
6555 && glyph->charpos < XSTRING (glyph->object)->size)
6556 {
6557 /* If we're on a string with `help-echo' text property,
6558 arrange for the help to be displayed. This is done by
6559 setting the global variable help_echo to the help string. */
6560 help = Fget_text_property (make_number (glyph->charpos),
6561 Qhelp_echo, glyph->object);
6562 if (!NILP (help))
6563 {
6564 help_echo = help;
6565 XSETWINDOW (help_echo_window, w);
6566 help_echo_object = glyph->object;
6567 help_echo_pos = glyph->charpos;
6568 }
6569
6570 /* Change the mouse pointer according to what is under X/Y. */
6571 map = Fget_text_property (make_number (glyph->charpos),
6572 Qlocal_map, glyph->object);
6573 if (KEYMAPP (map))
6574 cursor = f->output_data.x->nontext_cursor;
6575 else
6576 {
6577 map = Fget_text_property (make_number (glyph->charpos),
6578 Qkeymap, glyph->object);
6579 if (KEYMAPP (map))
6580 cursor = f->output_data.x->nontext_cursor;
6581 }
6582 }
6583 }
6584
6585 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6586 }
6587
6588
6589 /* Take proper action when the mouse has moved to position X, Y on
6590 frame F as regards highlighting characters that have mouse-face
6591 properties. Also de-highlighting chars where the mouse was before.
6592 X and Y can be negative or out of range. */
6593
6594 static void
6595 note_mouse_highlight (f, x, y)
6596 struct frame *f;
6597 int x, y;
6598 {
6599 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6600 int portion;
6601 Lisp_Object window;
6602 struct window *w;
6603
6604 /* When a menu is active, don't highlight because this looks odd. */
6605 #ifdef USE_X_TOOLKIT
6606 if (popup_activated ())
6607 return;
6608 #endif
6609
6610 if (disable_mouse_highlight
6611 || !f->glyphs_initialized_p)
6612 return;
6613
6614 dpyinfo->mouse_face_mouse_x = x;
6615 dpyinfo->mouse_face_mouse_y = y;
6616 dpyinfo->mouse_face_mouse_frame = f;
6617
6618 if (dpyinfo->mouse_face_defer)
6619 return;
6620
6621 if (gc_in_progress)
6622 {
6623 dpyinfo->mouse_face_deferred_gc = 1;
6624 return;
6625 }
6626
6627 /* Which window is that in? */
6628 window = window_from_coordinates (f, x, y, &portion, 1);
6629
6630 /* If we were displaying active text in another window, clear that. */
6631 if (! EQ (window, dpyinfo->mouse_face_window))
6632 clear_mouse_face (dpyinfo);
6633
6634 /* Not on a window -> return. */
6635 if (!WINDOWP (window))
6636 return;
6637
6638 /* Convert to window-relative pixel coordinates. */
6639 w = XWINDOW (window);
6640 frame_to_window_pixel_xy (w, &x, &y);
6641
6642 /* Handle tool-bar window differently since it doesn't display a
6643 buffer. */
6644 if (EQ (window, f->tool_bar_window))
6645 {
6646 note_tool_bar_highlight (f, x, y);
6647 return;
6648 }
6649
6650 if (portion == 1 || portion == 3)
6651 {
6652 /* Mouse is on the mode or top line. */
6653 note_mode_line_highlight (w, x, portion == 1);
6654 return;
6655 }
6656 else if (portion == 2)
6657 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6658 f->output_data.x->horizontal_drag_cursor);
6659 else
6660 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6661 f->output_data.x->text_cursor);
6662
6663 /* Are we in a window whose display is up to date?
6664 And verify the buffer's text has not changed. */
6665 if (/* Within text portion of the window. */
6666 portion == 0
6667 && EQ (w->window_end_valid, w->buffer)
6668 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6669 && (XFASTINT (w->last_overlay_modified)
6670 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6671 {
6672 int hpos, vpos, pos, i, area;
6673 struct glyph *glyph;
6674
6675 /* Find the glyph under X/Y. */
6676 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6677
6678 /* Clear mouse face if X/Y not over text. */
6679 if (glyph == NULL
6680 || area != TEXT_AREA
6681 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6682 {
6683 clear_mouse_face (dpyinfo);
6684 return;
6685 }
6686
6687 pos = glyph->charpos;
6688 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6689
6690 /* Check for mouse-face and help-echo. */
6691 {
6692 Lisp_Object mouse_face, overlay, position;
6693 Lisp_Object *overlay_vec;
6694 int len, noverlays;
6695 struct buffer *obuf;
6696 int obegv, ozv;
6697
6698 /* If we get an out-of-range value, return now; avoid an error. */
6699 if (pos > BUF_Z (XBUFFER (w->buffer)))
6700 return;
6701
6702 /* Make the window's buffer temporarily current for
6703 overlays_at and compute_char_face. */
6704 obuf = current_buffer;
6705 current_buffer = XBUFFER (w->buffer);
6706 obegv = BEGV;
6707 ozv = ZV;
6708 BEGV = BEG;
6709 ZV = Z;
6710
6711 /* Is this char mouse-active or does it have help-echo? */
6712 XSETINT (position, pos);
6713
6714 /* Put all the overlays we want in a vector in overlay_vec.
6715 Store the length in len. If there are more than 10, make
6716 enough space for all, and try again. */
6717 len = 10;
6718 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6719 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6720 if (noverlays > len)
6721 {
6722 len = noverlays;
6723 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6724 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6725 }
6726
6727 /* Sort overlays into increasing priority order. */
6728 noverlays = sort_overlays (overlay_vec, noverlays, w);
6729
6730 /* Check mouse-face highlighting. */
6731 if (! (EQ (window, dpyinfo->mouse_face_window)
6732 && vpos >= dpyinfo->mouse_face_beg_row
6733 && vpos <= dpyinfo->mouse_face_end_row
6734 && (vpos > dpyinfo->mouse_face_beg_row
6735 || hpos >= dpyinfo->mouse_face_beg_col)
6736 && (vpos < dpyinfo->mouse_face_end_row
6737 || hpos < dpyinfo->mouse_face_end_col
6738 || dpyinfo->mouse_face_past_end)))
6739 {
6740 /* Clear the display of the old active region, if any. */
6741 clear_mouse_face (dpyinfo);
6742
6743 /* Find the highest priority overlay that has a mouse-face prop. */
6744 overlay = Qnil;
6745 for (i = noverlays - 1; i >= 0; --i)
6746 {
6747 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6748 if (!NILP (mouse_face))
6749 {
6750 overlay = overlay_vec[i];
6751 break;
6752 }
6753 }
6754
6755 /* If no overlay applies, get a text property. */
6756 if (NILP (overlay))
6757 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6758
6759 /* Handle the overlay case. */
6760 if (! NILP (overlay))
6761 {
6762 /* Find the range of text around this char that
6763 should be active. */
6764 Lisp_Object before, after;
6765 int ignore;
6766
6767 before = Foverlay_start (overlay);
6768 after = Foverlay_end (overlay);
6769 /* Record this as the current active region. */
6770 fast_find_position (w, XFASTINT (before),
6771 &dpyinfo->mouse_face_beg_col,
6772 &dpyinfo->mouse_face_beg_row,
6773 &dpyinfo->mouse_face_beg_x,
6774 &dpyinfo->mouse_face_beg_y);
6775 dpyinfo->mouse_face_past_end
6776 = !fast_find_position (w, XFASTINT (after),
6777 &dpyinfo->mouse_face_end_col,
6778 &dpyinfo->mouse_face_end_row,
6779 &dpyinfo->mouse_face_end_x,
6780 &dpyinfo->mouse_face_end_y);
6781 dpyinfo->mouse_face_window = window;
6782 dpyinfo->mouse_face_face_id
6783 = face_at_buffer_position (w, pos, 0, 0,
6784 &ignore, pos + 1, 1);
6785
6786 /* Display it as active. */
6787 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6788 }
6789 /* Handle the text property case. */
6790 else if (! NILP (mouse_face))
6791 {
6792 /* Find the range of text around this char that
6793 should be active. */
6794 Lisp_Object before, after, beginning, end;
6795 int ignore;
6796
6797 beginning = Fmarker_position (w->start);
6798 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6799 - XFASTINT (w->window_end_pos)));
6800 before
6801 = Fprevious_single_property_change (make_number (pos + 1),
6802 Qmouse_face,
6803 w->buffer, beginning);
6804 after
6805 = Fnext_single_property_change (position, Qmouse_face,
6806 w->buffer, end);
6807 /* Record this as the current active region. */
6808 fast_find_position (w, XFASTINT (before),
6809 &dpyinfo->mouse_face_beg_col,
6810 &dpyinfo->mouse_face_beg_row,
6811 &dpyinfo->mouse_face_beg_x,
6812 &dpyinfo->mouse_face_beg_y);
6813 dpyinfo->mouse_face_past_end
6814 = !fast_find_position (w, XFASTINT (after),
6815 &dpyinfo->mouse_face_end_col,
6816 &dpyinfo->mouse_face_end_row,
6817 &dpyinfo->mouse_face_end_x,
6818 &dpyinfo->mouse_face_end_y);
6819 dpyinfo->mouse_face_window = window;
6820 dpyinfo->mouse_face_face_id
6821 = face_at_buffer_position (w, pos, 0, 0,
6822 &ignore, pos + 1, 1);
6823
6824 /* Display it as active. */
6825 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6826 }
6827 }
6828
6829 /* Look for a `help-echo' property. */
6830 {
6831 Lisp_Object help, overlay;
6832
6833 /* Check overlays first. */
6834 help = overlay = Qnil;
6835 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6836 {
6837 overlay = overlay_vec[i];
6838 help = Foverlay_get (overlay, Qhelp_echo);
6839 }
6840
6841 if (!NILP (help))
6842 {
6843 help_echo = help;
6844 help_echo_window = window;
6845 help_echo_object = overlay;
6846 help_echo_pos = pos;
6847 }
6848 else
6849 {
6850 /* Try text properties. */
6851 if ((STRINGP (glyph->object)
6852 && glyph->charpos >= 0
6853 && glyph->charpos < XSTRING (glyph->object)->size)
6854 || (BUFFERP (glyph->object)
6855 && glyph->charpos >= BEGV
6856 && glyph->charpos < ZV))
6857 help = Fget_text_property (make_number (glyph->charpos),
6858 Qhelp_echo, glyph->object);
6859
6860 if (!NILP (help))
6861 {
6862 help_echo = help;
6863 help_echo_window = window;
6864 help_echo_object = glyph->object;
6865 help_echo_pos = glyph->charpos;
6866 }
6867 }
6868 }
6869
6870 BEGV = obegv;
6871 ZV = ozv;
6872 current_buffer = obuf;
6873 }
6874 }
6875 }
6876
6877 static void
6878 redo_mouse_highlight ()
6879 {
6880 if (!NILP (last_mouse_motion_frame)
6881 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6882 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6883 last_mouse_motion_event.x,
6884 last_mouse_motion_event.y);
6885 }
6886
6887
6888 \f
6889 /***********************************************************************
6890 Tool-bars
6891 ***********************************************************************/
6892
6893 static int x_tool_bar_item P_ ((struct frame *, int, int,
6894 struct glyph **, int *, int *, int *));
6895
6896 /* Tool-bar item index of the item on which a mouse button was pressed
6897 or -1. */
6898
6899 static int last_tool_bar_item;
6900
6901
6902 /* Get information about the tool-bar item at position X/Y on frame F.
6903 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6904 the current matrix of the tool-bar window of F, or NULL if not
6905 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6906 item in F->tool_bar_items. Value is
6907
6908 -1 if X/Y is not on a tool-bar item
6909 0 if X/Y is on the same item that was highlighted before.
6910 1 otherwise. */
6911
6912 static int
6913 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6914 struct frame *f;
6915 int x, y;
6916 struct glyph **glyph;
6917 int *hpos, *vpos, *prop_idx;
6918 {
6919 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6920 struct window *w = XWINDOW (f->tool_bar_window);
6921 int area;
6922
6923 /* Find the glyph under X/Y. */
6924 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6925 if (*glyph == NULL)
6926 return -1;
6927
6928 /* Get the start of this tool-bar item's properties in
6929 f->tool_bar_items. */
6930 if (!tool_bar_item_info (f, *glyph, prop_idx))
6931 return -1;
6932
6933 /* Is mouse on the highlighted item? */
6934 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6935 && *vpos >= dpyinfo->mouse_face_beg_row
6936 && *vpos <= dpyinfo->mouse_face_end_row
6937 && (*vpos > dpyinfo->mouse_face_beg_row
6938 || *hpos >= dpyinfo->mouse_face_beg_col)
6939 && (*vpos < dpyinfo->mouse_face_end_row
6940 || *hpos < dpyinfo->mouse_face_end_col
6941 || dpyinfo->mouse_face_past_end))
6942 return 0;
6943
6944 return 1;
6945 }
6946
6947
6948 /* Handle mouse button event on the tool-bar of frame F, at
6949 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6950 or ButtonRelase. */
6951
6952 static void
6953 x_handle_tool_bar_click (f, button_event)
6954 struct frame *f;
6955 XButtonEvent *button_event;
6956 {
6957 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6958 struct window *w = XWINDOW (f->tool_bar_window);
6959 int hpos, vpos, prop_idx;
6960 struct glyph *glyph;
6961 Lisp_Object enabled_p;
6962 int x = button_event->x;
6963 int y = button_event->y;
6964
6965 /* If not on the highlighted tool-bar item, return. */
6966 frame_to_window_pixel_xy (w, &x, &y);
6967 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6968 return;
6969
6970 /* If item is disabled, do nothing. */
6971 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
6972 if (NILP (enabled_p))
6973 return;
6974
6975 if (button_event->type == ButtonPress)
6976 {
6977 /* Show item in pressed state. */
6978 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6979 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6980 last_tool_bar_item = prop_idx;
6981 }
6982 else
6983 {
6984 Lisp_Object key, frame;
6985 struct input_event event;
6986
6987 /* Show item in released state. */
6988 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6989 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6990
6991 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
6992
6993 XSETFRAME (frame, f);
6994 event.kind = TOOL_BAR_EVENT;
6995 event.frame_or_window = frame;
6996 event.arg = frame;
6997 kbd_buffer_store_event (&event);
6998
6999 event.kind = TOOL_BAR_EVENT;
7000 event.frame_or_window = frame;
7001 event.arg = key;
7002 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7003 button_event->state);
7004 kbd_buffer_store_event (&event);
7005 last_tool_bar_item = -1;
7006 }
7007 }
7008
7009
7010 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7011 tool-bar window-relative coordinates X/Y. Called from
7012 note_mouse_highlight. */
7013
7014 static void
7015 note_tool_bar_highlight (f, x, y)
7016 struct frame *f;
7017 int x, y;
7018 {
7019 Lisp_Object window = f->tool_bar_window;
7020 struct window *w = XWINDOW (window);
7021 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7022 int hpos, vpos;
7023 struct glyph *glyph;
7024 struct glyph_row *row;
7025 int i;
7026 Lisp_Object enabled_p;
7027 int prop_idx;
7028 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7029 int mouse_down_p, rc;
7030
7031 /* Function note_mouse_highlight is called with negative x(y
7032 values when mouse moves outside of the frame. */
7033 if (x <= 0 || y <= 0)
7034 {
7035 clear_mouse_face (dpyinfo);
7036 return;
7037 }
7038
7039 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7040 if (rc < 0)
7041 {
7042 /* Not on tool-bar item. */
7043 clear_mouse_face (dpyinfo);
7044 return;
7045 }
7046 else if (rc == 0)
7047 /* On same tool-bar item as before. */
7048 goto set_help_echo;
7049
7050 clear_mouse_face (dpyinfo);
7051
7052 /* Mouse is down, but on different tool-bar item? */
7053 mouse_down_p = (dpyinfo->grabbed
7054 && f == last_mouse_frame
7055 && FRAME_LIVE_P (f));
7056 if (mouse_down_p
7057 && last_tool_bar_item != prop_idx)
7058 return;
7059
7060 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7061 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7062
7063 /* If tool-bar item is not enabled, don't highlight it. */
7064 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7065 if (!NILP (enabled_p))
7066 {
7067 /* Compute the x-position of the glyph. In front and past the
7068 image is a space. We include this is the highlighted area. */
7069 row = MATRIX_ROW (w->current_matrix, vpos);
7070 for (i = x = 0; i < hpos; ++i)
7071 x += row->glyphs[TEXT_AREA][i].pixel_width;
7072
7073 /* Record this as the current active region. */
7074 dpyinfo->mouse_face_beg_col = hpos;
7075 dpyinfo->mouse_face_beg_row = vpos;
7076 dpyinfo->mouse_face_beg_x = x;
7077 dpyinfo->mouse_face_beg_y = row->y;
7078 dpyinfo->mouse_face_past_end = 0;
7079
7080 dpyinfo->mouse_face_end_col = hpos + 1;
7081 dpyinfo->mouse_face_end_row = vpos;
7082 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7083 dpyinfo->mouse_face_end_y = row->y;
7084 dpyinfo->mouse_face_window = window;
7085 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7086
7087 /* Display it as active. */
7088 show_mouse_face (dpyinfo, draw);
7089 dpyinfo->mouse_face_image_state = draw;
7090 }
7091
7092 set_help_echo:
7093
7094 /* Set help_echo to a help string.to display for this tool-bar item.
7095 XTread_socket does the rest. */
7096 help_echo_object = help_echo_window = Qnil;
7097 help_echo_pos = -1;
7098 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7099 if (NILP (help_echo))
7100 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7101 }
7102
7103
7104 \f
7105 /* Find the glyph matrix position of buffer position POS in window W.
7106 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7107 current glyphs must be up to date. If POS is above window start
7108 return (0, 0, 0, 0). If POS is after end of W, return end of
7109 last line in W. */
7110
7111 static int
7112 fast_find_position (w, pos, hpos, vpos, x, y)
7113 struct window *w;
7114 int pos;
7115 int *hpos, *vpos, *x, *y;
7116 {
7117 int i;
7118 int lastcol;
7119 int maybe_next_line_p = 0;
7120 int line_start_position;
7121 int yb = window_text_bottom_y (w);
7122 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
7123 struct glyph_row *best_row = row;
7124 int row_vpos = 0, best_row_vpos = 0;
7125 int current_x;
7126
7127 while (row->y < yb)
7128 {
7129 if (row->used[TEXT_AREA])
7130 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7131 else
7132 line_start_position = 0;
7133
7134 if (line_start_position > pos)
7135 break;
7136 /* If the position sought is the end of the buffer,
7137 don't include the blank lines at the bottom of the window. */
7138 else if (line_start_position == pos
7139 && pos == BUF_ZV (XBUFFER (w->buffer)))
7140 {
7141 maybe_next_line_p = 1;
7142 break;
7143 }
7144 else if (line_start_position > 0)
7145 {
7146 best_row = row;
7147 best_row_vpos = row_vpos;
7148 }
7149
7150 if (row->y + row->height >= yb)
7151 break;
7152
7153 ++row;
7154 ++row_vpos;
7155 }
7156
7157 /* Find the right column within BEST_ROW. */
7158 lastcol = 0;
7159 current_x = best_row->x;
7160 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7161 {
7162 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7163 int charpos;
7164
7165 charpos = glyph->charpos;
7166 if (charpos == pos)
7167 {
7168 *hpos = i;
7169 *vpos = best_row_vpos;
7170 *x = current_x;
7171 *y = best_row->y;
7172 return 1;
7173 }
7174 else if (charpos > pos)
7175 break;
7176 else if (charpos > 0)
7177 lastcol = i;
7178
7179 current_x += glyph->pixel_width;
7180 }
7181
7182 /* If we're looking for the end of the buffer,
7183 and we didn't find it in the line we scanned,
7184 use the start of the following line. */
7185 if (maybe_next_line_p)
7186 {
7187 ++best_row;
7188 ++best_row_vpos;
7189 lastcol = 0;
7190 current_x = best_row->x;
7191 }
7192
7193 *vpos = best_row_vpos;
7194 *hpos = lastcol + 1;
7195 *x = current_x;
7196 *y = best_row->y;
7197 return 0;
7198 }
7199
7200
7201 /* Display the active region described by mouse_face_*
7202 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7203
7204 static void
7205 show_mouse_face (dpyinfo, draw)
7206 struct x_display_info *dpyinfo;
7207 enum draw_glyphs_face draw;
7208 {
7209 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7210 struct frame *f = XFRAME (WINDOW_FRAME (w));
7211 int i;
7212 int cursor_off_p = 0;
7213 struct cursor_pos saved_cursor;
7214
7215 saved_cursor = output_cursor;
7216
7217 /* If window is in the process of being destroyed, don't bother
7218 to do anything. */
7219 if (w->current_matrix == NULL)
7220 goto set_x_cursor;
7221
7222 /* Recognize when we are called to operate on rows that don't exist
7223 anymore. This can happen when a window is split. */
7224 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7225 goto set_x_cursor;
7226
7227 set_output_cursor (&w->phys_cursor);
7228
7229 /* Note that mouse_face_beg_row etc. are window relative. */
7230 for (i = dpyinfo->mouse_face_beg_row;
7231 i <= dpyinfo->mouse_face_end_row;
7232 i++)
7233 {
7234 int start_hpos, end_hpos, start_x;
7235 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7236
7237 /* Don't do anything if row doesn't have valid contents. */
7238 if (!row->enabled_p)
7239 continue;
7240
7241 /* For all but the first row, the highlight starts at column 0. */
7242 if (i == dpyinfo->mouse_face_beg_row)
7243 {
7244 start_hpos = dpyinfo->mouse_face_beg_col;
7245 start_x = dpyinfo->mouse_face_beg_x;
7246 }
7247 else
7248 {
7249 start_hpos = 0;
7250 start_x = 0;
7251 }
7252
7253 if (i == dpyinfo->mouse_face_end_row)
7254 end_hpos = dpyinfo->mouse_face_end_col;
7255 else
7256 end_hpos = row->used[TEXT_AREA];
7257
7258 /* If the cursor's in the text we are about to rewrite, turn the
7259 cursor off. */
7260 if (!w->pseudo_window_p
7261 && i == output_cursor.vpos
7262 && output_cursor.hpos >= start_hpos - 1
7263 && output_cursor.hpos <= end_hpos)
7264 {
7265 x_update_window_cursor (w, 0);
7266 cursor_off_p = 1;
7267 }
7268
7269 if (end_hpos > start_hpos)
7270 {
7271 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7272 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7273 start_hpos, end_hpos, draw, NULL, NULL, 0);
7274 }
7275 }
7276
7277 /* If we turned the cursor off, turn it back on. */
7278 if (cursor_off_p)
7279 x_display_cursor (w, 1,
7280 output_cursor.hpos, output_cursor.vpos,
7281 output_cursor.x, output_cursor.y);
7282
7283 output_cursor = saved_cursor;
7284
7285 set_x_cursor:
7286
7287 /* Change the mouse cursor. */
7288 if (draw == DRAW_NORMAL_TEXT)
7289 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7290 f->output_data.x->text_cursor);
7291 else if (draw == DRAW_MOUSE_FACE)
7292 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7293 f->output_data.x->cross_cursor);
7294 else
7295 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7296 f->output_data.x->nontext_cursor);
7297 }
7298
7299 /* Clear out the mouse-highlighted active region.
7300 Redraw it un-highlighted first. */
7301
7302 void
7303 clear_mouse_face (dpyinfo)
7304 struct x_display_info *dpyinfo;
7305 {
7306 if (tip_frame)
7307 return;
7308
7309 if (! NILP (dpyinfo->mouse_face_window))
7310 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7311
7312 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7313 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7314 dpyinfo->mouse_face_window = Qnil;
7315 }
7316
7317
7318 /* Clear any mouse-face on window W. This function is part of the
7319 redisplay interface, and is called from try_window_id and similar
7320 functions to ensure the mouse-highlight is off. */
7321
7322 static void
7323 x_clear_mouse_face (w)
7324 struct window *w;
7325 {
7326 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7327 Lisp_Object window;
7328
7329 BLOCK_INPUT;
7330 XSETWINDOW (window, w);
7331 if (EQ (window, dpyinfo->mouse_face_window))
7332 clear_mouse_face (dpyinfo);
7333 UNBLOCK_INPUT;
7334 }
7335
7336
7337 /* Just discard the mouse face information for frame F, if any.
7338 This is used when the size of F is changed. */
7339
7340 void
7341 cancel_mouse_face (f)
7342 FRAME_PTR f;
7343 {
7344 Lisp_Object window;
7345 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7346
7347 window = dpyinfo->mouse_face_window;
7348 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7349 {
7350 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7351 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7352 dpyinfo->mouse_face_window = Qnil;
7353 }
7354 }
7355 \f
7356 static struct scroll_bar *x_window_to_scroll_bar ();
7357 static void x_scroll_bar_report_motion ();
7358
7359 /* Return the current position of the mouse.
7360 *fp should be a frame which indicates which display to ask about.
7361
7362 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7363 and *part to the frame, window, and scroll bar part that the mouse
7364 is over. Set *x and *y to the portion and whole of the mouse's
7365 position on the scroll bar.
7366
7367 If the mouse movement started elsewhere, set *fp to the frame the
7368 mouse is on, *bar_window to nil, and *x and *y to the character cell
7369 the mouse is over.
7370
7371 Set *time to the server time-stamp for the time at which the mouse
7372 was at this position.
7373
7374 Don't store anything if we don't have a valid set of values to report.
7375
7376 This clears the mouse_moved flag, so we can wait for the next mouse
7377 movement. */
7378
7379 static void
7380 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7381 FRAME_PTR *fp;
7382 int insist;
7383 Lisp_Object *bar_window;
7384 enum scroll_bar_part *part;
7385 Lisp_Object *x, *y;
7386 unsigned long *time;
7387 {
7388 FRAME_PTR f1;
7389
7390 BLOCK_INPUT;
7391
7392 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7393 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7394 else
7395 {
7396 Window root;
7397 int root_x, root_y;
7398
7399 Window dummy_window;
7400 int dummy;
7401
7402 Lisp_Object frame, tail;
7403
7404 /* Clear the mouse-moved flag for every frame on this display. */
7405 FOR_EACH_FRAME (tail, frame)
7406 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7407 XFRAME (frame)->mouse_moved = 0;
7408
7409 last_mouse_scroll_bar = Qnil;
7410
7411 /* Figure out which root window we're on. */
7412 XQueryPointer (FRAME_X_DISPLAY (*fp),
7413 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7414
7415 /* The root window which contains the pointer. */
7416 &root,
7417
7418 /* Trash which we can't trust if the pointer is on
7419 a different screen. */
7420 &dummy_window,
7421
7422 /* The position on that root window. */
7423 &root_x, &root_y,
7424
7425 /* More trash we can't trust. */
7426 &dummy, &dummy,
7427
7428 /* Modifier keys and pointer buttons, about which
7429 we don't care. */
7430 (unsigned int *) &dummy);
7431
7432 /* Now we have a position on the root; find the innermost window
7433 containing the pointer. */
7434 {
7435 Window win, child;
7436 int win_x, win_y;
7437 int parent_x = 0, parent_y = 0;
7438 int count;
7439
7440 win = root;
7441
7442 /* XTranslateCoordinates can get errors if the window
7443 structure is changing at the same time this function
7444 is running. So at least we must not crash from them. */
7445
7446 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7447
7448 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7449 && FRAME_LIVE_P (last_mouse_frame))
7450 {
7451 /* If mouse was grabbed on a frame, give coords for that frame
7452 even if the mouse is now outside it. */
7453 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7454
7455 /* From-window, to-window. */
7456 root, FRAME_X_WINDOW (last_mouse_frame),
7457
7458 /* From-position, to-position. */
7459 root_x, root_y, &win_x, &win_y,
7460
7461 /* Child of win. */
7462 &child);
7463 f1 = last_mouse_frame;
7464 }
7465 else
7466 {
7467 while (1)
7468 {
7469 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7470
7471 /* From-window, to-window. */
7472 root, win,
7473
7474 /* From-position, to-position. */
7475 root_x, root_y, &win_x, &win_y,
7476
7477 /* Child of win. */
7478 &child);
7479
7480 if (child == None || child == win)
7481 break;
7482
7483 win = child;
7484 parent_x = win_x;
7485 parent_y = win_y;
7486 }
7487
7488 /* Now we know that:
7489 win is the innermost window containing the pointer
7490 (XTC says it has no child containing the pointer),
7491 win_x and win_y are the pointer's position in it
7492 (XTC did this the last time through), and
7493 parent_x and parent_y are the pointer's position in win's parent.
7494 (They are what win_x and win_y were when win was child.
7495 If win is the root window, it has no parent, and
7496 parent_{x,y} are invalid, but that's okay, because we'll
7497 never use them in that case.) */
7498
7499 /* Is win one of our frames? */
7500 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7501
7502 #ifdef USE_X_TOOLKIT
7503 /* If we end up with the menu bar window, say it's not
7504 on the frame. */
7505 if (f1 != NULL
7506 && f1->output_data.x->menubar_widget
7507 && win == XtWindow (f1->output_data.x->menubar_widget))
7508 f1 = NULL;
7509 #endif /* USE_X_TOOLKIT */
7510 }
7511
7512 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7513 f1 = 0;
7514
7515 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7516
7517 /* If not, is it one of our scroll bars? */
7518 if (! f1)
7519 {
7520 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7521
7522 if (bar)
7523 {
7524 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7525 win_x = parent_x;
7526 win_y = parent_y;
7527 }
7528 }
7529
7530 if (f1 == 0 && insist > 0)
7531 f1 = SELECTED_FRAME ();
7532
7533 if (f1)
7534 {
7535 /* Ok, we found a frame. Store all the values.
7536 last_mouse_glyph is a rectangle used to reduce the
7537 generation of mouse events. To not miss any motion
7538 events, we must divide the frame into rectangles of the
7539 size of the smallest character that could be displayed
7540 on it, i.e. into the same rectangles that matrices on
7541 the frame are divided into. */
7542
7543 #if OLD_REDISPLAY_CODE
7544 int ignore1, ignore2;
7545 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7546 &last_mouse_glyph,
7547 FRAME_X_DISPLAY_INFO (f1)->grabbed
7548 || insist);
7549 #else
7550 {
7551 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7552 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7553 int x = win_x;
7554 int y = win_y;
7555
7556 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7557 round down even for negative values. */
7558 if (x < 0)
7559 x -= width - 1;
7560 if (y < 0)
7561 y -= height - 1;
7562
7563 last_mouse_glyph.width = width;
7564 last_mouse_glyph.height = height;
7565 last_mouse_glyph.x = (x + width - 1) / width * width;
7566 last_mouse_glyph.y = (y + height - 1) / height * height;
7567 }
7568 #endif
7569
7570 *bar_window = Qnil;
7571 *part = 0;
7572 *fp = f1;
7573 XSETINT (*x, win_x);
7574 XSETINT (*y, win_y);
7575 *time = last_mouse_movement_time;
7576 }
7577 }
7578 }
7579
7580 UNBLOCK_INPUT;
7581 }
7582
7583
7584 #ifdef USE_X_TOOLKIT
7585
7586 /* Atimer callback function for TIMER. Called every 0.1s to process
7587 Xt timeouts, if needed. We must avoid calling XtAppPending as
7588 much as possible because that function does an implicit XFlush
7589 that slows us down. */
7590
7591 static void
7592 x_process_timeouts (timer)
7593 struct atimer *timer;
7594 {
7595 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7596 {
7597 BLOCK_INPUT;
7598 while (XtAppPending (Xt_app_con) & XtIMTimer)
7599 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7600 UNBLOCK_INPUT;
7601 }
7602 }
7603
7604 #endif /* USE_X_TOOLKIT */
7605
7606 \f
7607 /* Scroll bar support. */
7608
7609 /* Given an X window ID, find the struct scroll_bar which manages it.
7610 This can be called in GC, so we have to make sure to strip off mark
7611 bits. */
7612
7613 static struct scroll_bar *
7614 x_window_to_scroll_bar (window_id)
7615 Window window_id;
7616 {
7617 Lisp_Object tail;
7618
7619 for (tail = Vframe_list;
7620 XGCTYPE (tail) == Lisp_Cons;
7621 tail = XCDR (tail))
7622 {
7623 Lisp_Object frame, bar, condemned;
7624
7625 frame = XCAR (tail);
7626 /* All elements of Vframe_list should be frames. */
7627 if (! GC_FRAMEP (frame))
7628 abort ();
7629
7630 /* Scan this frame's scroll bar list for a scroll bar with the
7631 right window ID. */
7632 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7633 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7634 /* This trick allows us to search both the ordinary and
7635 condemned scroll bar lists with one loop. */
7636 ! GC_NILP (bar) || (bar = condemned,
7637 condemned = Qnil,
7638 ! GC_NILP (bar));
7639 bar = XSCROLL_BAR (bar)->next)
7640 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7641 return XSCROLL_BAR (bar);
7642 }
7643
7644 return 0;
7645 }
7646
7647
7648 \f
7649 /************************************************************************
7650 Toolkit scroll bars
7651 ************************************************************************/
7652
7653 #if USE_TOOLKIT_SCROLL_BARS
7654
7655 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7656 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7657 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7658 struct scroll_bar *));
7659 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7660 int, int, int));
7661
7662
7663 /* Id of action hook installed for scroll bars. */
7664
7665 static XtActionHookId action_hook_id;
7666
7667 /* Lisp window being scrolled. Set when starting to interact with
7668 a toolkit scroll bar, reset to nil when ending the interaction. */
7669
7670 static Lisp_Object window_being_scrolled;
7671
7672 /* Last scroll bar part sent in xm_scroll_callback. */
7673
7674 static int last_scroll_bar_part;
7675
7676 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7677 that movements of 1/20 of the screen size are mapped to up/down. */
7678
7679 static Boolean xaw3d_arrow_scroll;
7680
7681 /* Whether the drag scrolling maintains the mouse at the top of the
7682 thumb. If not, resizing the thumb needs to be done more carefully
7683 to avoid jerkyness. */
7684
7685 static Boolean xaw3d_pick_top;
7686
7687
7688 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7689 bars are used.. The hook is responsible for detecting when
7690 the user ends an interaction with the scroll bar, and generates
7691 a `end-scroll' scroll_bar_click' event if so. */
7692
7693 static void
7694 xt_action_hook (widget, client_data, action_name, event, params,
7695 num_params)
7696 Widget widget;
7697 XtPointer client_data;
7698 String action_name;
7699 XEvent *event;
7700 String *params;
7701 Cardinal *num_params;
7702 {
7703 int scroll_bar_p;
7704 char *end_action;
7705
7706 #ifdef USE_MOTIF
7707 scroll_bar_p = XmIsScrollBar (widget);
7708 end_action = "Release";
7709 #else /* !USE_MOTIF i.e. use Xaw */
7710 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7711 end_action = "EndScroll";
7712 #endif /* USE_MOTIF */
7713
7714 if (scroll_bar_p
7715 && strcmp (action_name, end_action) == 0
7716 && WINDOWP (window_being_scrolled))
7717 {
7718 struct window *w;
7719
7720 x_send_scroll_bar_event (window_being_scrolled,
7721 scroll_bar_end_scroll, 0, 0);
7722 w = XWINDOW (window_being_scrolled);
7723 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7724 window_being_scrolled = Qnil;
7725 last_scroll_bar_part = -1;
7726
7727 /* Xt timeouts no longer needed. */
7728 toolkit_scroll_bar_interaction = 0;
7729 }
7730 }
7731
7732 /* A vector of windows used for communication between
7733 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
7734
7735 static struct window **scroll_bar_windows;
7736 static int scroll_bar_windows_size;
7737
7738
7739 /* Send a client message with message type Xatom_Scrollbar for a
7740 scroll action to the frame of WINDOW. PART is a value identifying
7741 the part of the scroll bar that was clicked on. PORTION is the
7742 amount to scroll of a whole of WHOLE. */
7743
7744 static void
7745 x_send_scroll_bar_event (window, part, portion, whole)
7746 Lisp_Object window;
7747 int part, portion, whole;
7748 {
7749 XEvent event;
7750 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7751 struct window *w = XWINDOW (window);
7752 struct frame *f = XFRAME (w->frame);
7753 int i;
7754
7755 BLOCK_INPUT;
7756
7757 /* Construct a ClientMessage event to send to the frame. */
7758 ev->type = ClientMessage;
7759 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7760 ev->display = FRAME_X_DISPLAY (f);
7761 ev->window = FRAME_X_WINDOW (f);
7762 ev->format = 32;
7763
7764 /* We can only transfer 32 bits in the XClientMessageEvent, which is
7765 not enough to store a pointer or Lisp_Object on a 64 bit system.
7766 So, store the window in scroll_bar_windows and pass the index
7767 into that array in the event. */
7768 for (i = 0; i < scroll_bar_windows_size; ++i)
7769 if (scroll_bar_windows[i] == NULL)
7770 break;
7771
7772 if (i == scroll_bar_windows_size)
7773 {
7774 int new_size = max (10, 2 * scroll_bar_windows_size);
7775 size_t nbytes = new_size * sizeof *scroll_bar_windows;
7776 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
7777
7778 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
7779 nbytes);
7780 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
7781 scroll_bar_windows_size = new_size;
7782 }
7783
7784 scroll_bar_windows[i] = w;
7785 ev->data.l[0] = (long) i;
7786 ev->data.l[1] = (long) part;
7787 ev->data.l[2] = (long) 0;
7788 ev->data.l[3] = (long) portion;
7789 ev->data.l[4] = (long) whole;
7790
7791 /* Make Xt timeouts work while the scroll bar is active. */
7792 toolkit_scroll_bar_interaction = 1;
7793
7794 /* Setting the event mask to zero means that the message will
7795 be sent to the client that created the window, and if that
7796 window no longer exists, no event will be sent. */
7797 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7798 UNBLOCK_INPUT;
7799 }
7800
7801
7802 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7803 in *IEVENT. */
7804
7805 static void
7806 x_scroll_bar_to_input_event (event, ievent)
7807 XEvent *event;
7808 struct input_event *ievent;
7809 {
7810 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7811 Lisp_Object window;
7812 struct frame *f;
7813 struct window *w;
7814
7815 w = scroll_bar_windows[ev->data.l[0]];
7816 scroll_bar_windows[ev->data.l[0]] = NULL;
7817
7818 XSETWINDOW (window, w);
7819 f = XFRAME (w->frame);
7820
7821 ievent->kind = scroll_bar_click;
7822 ievent->frame_or_window = window;
7823 ievent->arg = Qnil;
7824 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7825 ievent->part = ev->data.l[1];
7826 ievent->code = ev->data.l[2];
7827 ievent->x = make_number ((int) ev->data.l[3]);
7828 ievent->y = make_number ((int) ev->data.l[4]);
7829 ievent->modifiers = 0;
7830 }
7831
7832
7833 #ifdef USE_MOTIF
7834
7835 /* Minimum and maximum values used for Motif scroll bars. */
7836
7837 #define XM_SB_MIN 1
7838 #define XM_SB_MAX 10000000
7839 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7840
7841
7842 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7843 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7844 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7845
7846 static void
7847 xm_scroll_callback (widget, client_data, call_data)
7848 Widget widget;
7849 XtPointer client_data, call_data;
7850 {
7851 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7852 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7853 double percent;
7854 int part = -1, whole = 0, portion = 0;
7855
7856 switch (cs->reason)
7857 {
7858 case XmCR_DECREMENT:
7859 bar->dragging = Qnil;
7860 part = scroll_bar_up_arrow;
7861 break;
7862
7863 case XmCR_INCREMENT:
7864 bar->dragging = Qnil;
7865 part = scroll_bar_down_arrow;
7866 break;
7867
7868 case XmCR_PAGE_DECREMENT:
7869 bar->dragging = Qnil;
7870 part = scroll_bar_above_handle;
7871 break;
7872
7873 case XmCR_PAGE_INCREMENT:
7874 bar->dragging = Qnil;
7875 part = scroll_bar_below_handle;
7876 break;
7877
7878 case XmCR_TO_TOP:
7879 bar->dragging = Qnil;
7880 part = scroll_bar_to_top;
7881 break;
7882
7883 case XmCR_TO_BOTTOM:
7884 bar->dragging = Qnil;
7885 part = scroll_bar_to_bottom;
7886 break;
7887
7888 case XmCR_DRAG:
7889 {
7890 int slider_size;
7891 int dragging_down_p = (INTEGERP (bar->dragging)
7892 && XINT (bar->dragging) <= cs->value);
7893
7894 /* Get the slider size. */
7895 BLOCK_INPUT;
7896 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7897 UNBLOCK_INPUT;
7898
7899 /* At the max position of the scroll bar, do a line-wise
7900 movement. Without doing anything, the LessTif scroll bar
7901 calls us with the same cs->value again and again. If we
7902 want to make sure that we can reach the end of the buffer,
7903 we have to do something.
7904
7905 Implementation note: setting bar->dragging always to
7906 cs->value gives a smoother movement at the max position.
7907 Setting it to nil when doing line-wise movement gives
7908 a better slider behavior. */
7909
7910 if (cs->value + slider_size == XM_SB_MAX
7911 || (dragging_down_p
7912 && last_scroll_bar_part == scroll_bar_down_arrow))
7913 {
7914 part = scroll_bar_down_arrow;
7915 bar->dragging = Qnil;
7916 }
7917 else
7918 {
7919 whole = XM_SB_RANGE;
7920 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7921 part = scroll_bar_handle;
7922 bar->dragging = make_number (cs->value);
7923 }
7924 }
7925 break;
7926
7927 case XmCR_VALUE_CHANGED:
7928 break;
7929 };
7930
7931 if (part >= 0)
7932 {
7933 window_being_scrolled = bar->window;
7934 last_scroll_bar_part = part;
7935 x_send_scroll_bar_event (bar->window, part, portion, whole);
7936 }
7937 }
7938
7939
7940 #else /* !USE_MOTIF, i.e. Xaw. */
7941
7942
7943 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7944 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7945 scroll bar struct. CALL_DATA is a pointer to a float saying where
7946 the thumb is. */
7947
7948 static void
7949 xaw_jump_callback (widget, client_data, call_data)
7950 Widget widget;
7951 XtPointer client_data, call_data;
7952 {
7953 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7954 float top = *(float *) call_data;
7955 float shown;
7956 int whole, portion, height;
7957 int part;
7958
7959 /* Get the size of the thumb, a value between 0 and 1. */
7960 BLOCK_INPUT;
7961 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7962 UNBLOCK_INPUT;
7963
7964 whole = 10000000;
7965 portion = shown < 1 ? top * whole : 0;
7966
7967 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7968 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7969 the bottom, so we force the scrolling whenever we see that we're
7970 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7971 we try to ensure that we always stay two pixels away from the
7972 bottom). */
7973 part = scroll_bar_down_arrow;
7974 else
7975 part = scroll_bar_handle;
7976
7977 window_being_scrolled = bar->window;
7978 bar->dragging = make_number (portion);
7979 last_scroll_bar_part = part;
7980 x_send_scroll_bar_event (bar->window, part, portion, whole);
7981 }
7982
7983
7984 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7985 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7986 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7987 the scroll bar. CALL_DATA is an integer specifying the action that
7988 has taken place. It's magnitude is in the range 0..height of the
7989 scroll bar. Negative values mean scroll towards buffer start.
7990 Values < height of scroll bar mean line-wise movement. */
7991
7992 static void
7993 xaw_scroll_callback (widget, client_data, call_data)
7994 Widget widget;
7995 XtPointer client_data, call_data;
7996 {
7997 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7998 int position = (int) call_data;
7999 Dimension height;
8000 int part;
8001
8002 /* Get the height of the scroll bar. */
8003 BLOCK_INPUT;
8004 XtVaGetValues (widget, XtNheight, &height, NULL);
8005 UNBLOCK_INPUT;
8006
8007 if (abs (position) >= height)
8008 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8009
8010 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8011 it maps line-movement to call_data = max(5, height/20). */
8012 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8013 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
8014 else
8015 part = scroll_bar_move_ratio;
8016
8017 window_being_scrolled = bar->window;
8018 bar->dragging = Qnil;
8019 last_scroll_bar_part = part;
8020 x_send_scroll_bar_event (bar->window, part, position, height);
8021 }
8022
8023
8024 #endif /* not USE_MOTIF */
8025
8026
8027 /* Create the widget for scroll bar BAR on frame F. Record the widget
8028 and X window of the scroll bar in BAR. */
8029
8030 static void
8031 x_create_toolkit_scroll_bar (f, bar)
8032 struct frame *f;
8033 struct scroll_bar *bar;
8034 {
8035 Window xwindow;
8036 Widget widget;
8037 Arg av[20];
8038 int ac = 0;
8039 char *scroll_bar_name = "verticalScrollBar";
8040 unsigned long pixel;
8041
8042 BLOCK_INPUT;
8043
8044 #ifdef USE_MOTIF
8045 /* LessTif 0.85, problems:
8046
8047 1. When the mouse if over the scroll bar, the scroll bar will
8048 get keyboard events. I didn't find a way to turn this off.
8049
8050 2. Do we have to explicitly set the cursor to get an arrow
8051 cursor (see below)? */
8052
8053 /* Set resources. Create the widget. */
8054 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8055 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8056 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8057 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8058 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8059 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8060 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8061
8062 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8063 if (pixel != -1)
8064 {
8065 XtSetArg (av[ac], XmNforeground, pixel);
8066 ++ac;
8067 }
8068
8069 pixel = f->output_data.x->scroll_bar_background_pixel;
8070 if (pixel != -1)
8071 {
8072 XtSetArg (av[ac], XmNbackground, pixel);
8073 ++ac;
8074 }
8075
8076 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8077 scroll_bar_name, av, ac);
8078
8079 /* Add one callback for everything that can happen. */
8080 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8081 (XtPointer) bar);
8082 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8083 (XtPointer) bar);
8084 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8085 (XtPointer) bar);
8086 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8087 (XtPointer) bar);
8088 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8089 (XtPointer) bar);
8090 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8091 (XtPointer) bar);
8092 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8093 (XtPointer) bar);
8094
8095 /* Realize the widget. Only after that is the X window created. */
8096 XtRealizeWidget (widget);
8097
8098 /* Set the cursor to an arrow. I didn't find a resource to do that.
8099 And I'm wondering why it hasn't an arrow cursor by default. */
8100 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8101 f->output_data.x->nontext_cursor);
8102
8103 #else /* !USE_MOTIF i.e. use Xaw */
8104
8105 /* Set resources. Create the widget. The background of the
8106 Xaw3d scroll bar widget is a little bit light for my taste.
8107 We don't alter it here to let users change it according
8108 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8109 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8110 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
8111 /* For smoother scrolling with Xaw3d -sm */
8112 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8113 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
8114
8115 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8116 if (pixel != -1)
8117 {
8118 XtSetArg (av[ac], XtNforeground, pixel);
8119 ++ac;
8120 }
8121
8122 pixel = f->output_data.x->scroll_bar_background_pixel;
8123 if (pixel != -1)
8124 {
8125 XtSetArg (av[ac], XtNbackground, pixel);
8126 ++ac;
8127 }
8128
8129 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8130 f->output_data.x->edit_widget, av, ac);
8131
8132 {
8133 char *initial = "";
8134 char *val = initial;
8135 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8136 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8137 if (val == initial)
8138 { /* ARROW_SCROLL */
8139 xaw3d_arrow_scroll = True;
8140 /* Isn't that just a personal preference ? -sm */
8141 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8142 }
8143 }
8144
8145 /* Define callbacks. */
8146 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8147 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
8148 (XtPointer) bar);
8149
8150 /* Realize the widget. Only after that is the X window created. */
8151 XtRealizeWidget (widget);
8152
8153 #endif /* !USE_MOTIF */
8154
8155 /* Install an action hook that let's us detect when the user
8156 finishes interacting with a scroll bar. */
8157 if (action_hook_id == 0)
8158 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8159
8160 /* Remember X window and widget in the scroll bar vector. */
8161 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8162 xwindow = XtWindow (widget);
8163 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8164
8165 UNBLOCK_INPUT;
8166 }
8167
8168
8169 /* Set the thumb size and position of scroll bar BAR. We are currently
8170 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8171
8172 static void
8173 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8174 struct scroll_bar *bar;
8175 int portion, position, whole;
8176 {
8177 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8178 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8179 float top, shown;
8180
8181 if (whole == 0)
8182 top = 0, shown = 1;
8183 else
8184 {
8185 top = (float) position / whole;
8186 shown = (float) portion / whole;
8187 }
8188
8189 BLOCK_INPUT;
8190
8191 #ifdef USE_MOTIF
8192 {
8193 int size, value;
8194 Boolean arrow1_selected, arrow2_selected;
8195 unsigned char flags;
8196 XmScrollBarWidget sb;
8197
8198 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
8199 is the scroll bar's maximum and MIN is the scroll bar's minimum
8200 value. */
8201 size = shown * XM_SB_RANGE;
8202 size = min (size, XM_SB_RANGE);
8203 size = max (size, 1);
8204
8205 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8206 value = top * XM_SB_RANGE;
8207 value = min (value, XM_SB_MAX - size);
8208 value = max (value, XM_SB_MIN);
8209
8210 /* LessTif: Calling XmScrollBarSetValues after an increment or
8211 decrement turns off auto-repeat LessTif-internally. This can
8212 be seen in ScrollBar.c which resets Arrow1Selected and
8213 Arrow2Selected. It also sets internal flags so that LessTif
8214 believes the mouse is in the slider. We either have to change
8215 our code, or work around that by accessing private data. */
8216
8217 sb = (XmScrollBarWidget) widget;
8218 arrow1_selected = sb->scrollBar.arrow1_selected;
8219 arrow2_selected = sb->scrollBar.arrow2_selected;
8220 flags = sb->scrollBar.flags;
8221
8222 if (NILP (bar->dragging))
8223 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8224 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8225 /* This has the negative side effect that the slider value is
8226 not what it would be if we scrolled here using line-wise or
8227 page-wise movement. */
8228 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8229 else
8230 {
8231 /* If currently dragging, only update the slider size.
8232 This reduces flicker effects. */
8233 int old_value, old_size, increment, page_increment;
8234
8235 XmScrollBarGetValues (widget, &old_value, &old_size,
8236 &increment, &page_increment);
8237 XmScrollBarSetValues (widget, old_value,
8238 min (size, XM_SB_RANGE - old_value),
8239 0, 0, False);
8240 }
8241
8242 sb->scrollBar.arrow1_selected = arrow1_selected;
8243 sb->scrollBar.arrow2_selected = arrow2_selected;
8244 sb->scrollBar.flags = flags;
8245 }
8246 #else /* !USE_MOTIF i.e. use Xaw */
8247 {
8248 float old_top, old_shown;
8249 Dimension height;
8250 XtVaGetValues (widget,
8251 XtNtopOfThumb, &old_top,
8252 XtNshown, &old_shown,
8253 XtNheight, &height,
8254 NULL);
8255
8256 /* Massage the top+shown values. */
8257 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8258 top = max (0, min (1, top));
8259 else
8260 top = old_top;
8261 /* Keep two pixels available for moving the thumb down. */
8262 shown = max (0, min (1 - top - (2.0 / height), shown));
8263
8264 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8265 check that your system's configuration file contains a define
8266 for `NARROWPROTO'. See s/freebsd.h for an example. */
8267 if (top != old_top || shown != old_shown)
8268 {
8269 if (NILP (bar->dragging))
8270 XawScrollbarSetThumb (widget, top, shown);
8271 else
8272 {
8273 #ifdef HAVE_XAW3D
8274 ScrollbarWidget sb = (ScrollbarWidget) widget;
8275 int scroll_mode = 0;
8276
8277 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8278 if (xaw3d_arrow_scroll)
8279 {
8280 /* Xaw3d stupidly ignores resize requests while dragging
8281 so we have to make it believe it's not in dragging mode. */
8282 scroll_mode = sb->scrollbar.scroll_mode;
8283 if (scroll_mode == 2)
8284 sb->scrollbar.scroll_mode = 0;
8285 }
8286 #endif
8287 /* Try to make the scrolling a tad smoother. */
8288 if (!xaw3d_pick_top)
8289 shown = min (shown, old_shown);
8290
8291 XawScrollbarSetThumb (widget, top, shown);
8292
8293 #ifdef HAVE_XAW3D
8294 if (xaw3d_arrow_scroll && scroll_mode == 2)
8295 sb->scrollbar.scroll_mode = scroll_mode;
8296 #endif
8297 }
8298 }
8299 }
8300 #endif /* !USE_MOTIF */
8301
8302 UNBLOCK_INPUT;
8303 }
8304
8305 #endif /* USE_TOOLKIT_SCROLL_BARS */
8306
8307
8308 \f
8309 /************************************************************************
8310 Scroll bars, general
8311 ************************************************************************/
8312
8313 /* Create a scroll bar and return the scroll bar vector for it. W is
8314 the Emacs window on which to create the scroll bar. TOP, LEFT,
8315 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8316 scroll bar. */
8317
8318 static struct scroll_bar *
8319 x_scroll_bar_create (w, top, left, width, height)
8320 struct window *w;
8321 int top, left, width, height;
8322 {
8323 struct frame *f = XFRAME (w->frame);
8324 struct scroll_bar *bar
8325 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8326
8327 BLOCK_INPUT;
8328
8329 #if USE_TOOLKIT_SCROLL_BARS
8330 x_create_toolkit_scroll_bar (f, bar);
8331 #else /* not USE_TOOLKIT_SCROLL_BARS */
8332 {
8333 XSetWindowAttributes a;
8334 unsigned long mask;
8335 Window window;
8336
8337 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8338 if (a.background_pixel == -1)
8339 a.background_pixel = f->output_data.x->background_pixel;
8340
8341 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8342 | ButtonMotionMask | PointerMotionHintMask
8343 | ExposureMask);
8344 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8345
8346 mask = (CWBackPixel | CWEventMask | CWCursor);
8347
8348 /* Clear the area of W that will serve as a scroll bar. This is
8349 for the case that a window has been split horizontally. In
8350 this case, no clear_frame is generated to reduce flickering. */
8351 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8352 left, top, width,
8353 window_box_height (w), False);
8354
8355 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8356 /* Position and size of scroll bar. */
8357 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8358 top,
8359 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8360 height,
8361 /* Border width, depth, class, and visual. */
8362 0,
8363 CopyFromParent,
8364 CopyFromParent,
8365 CopyFromParent,
8366 /* Attributes. */
8367 mask, &a);
8368 SET_SCROLL_BAR_X_WINDOW (bar, window);
8369 }
8370 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8371
8372 XSETWINDOW (bar->window, w);
8373 XSETINT (bar->top, top);
8374 XSETINT (bar->left, left);
8375 XSETINT (bar->width, width);
8376 XSETINT (bar->height, height);
8377 XSETINT (bar->start, 0);
8378 XSETINT (bar->end, 0);
8379 bar->dragging = Qnil;
8380
8381 /* Add bar to its frame's list of scroll bars. */
8382 bar->next = FRAME_SCROLL_BARS (f);
8383 bar->prev = Qnil;
8384 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8385 if (!NILP (bar->next))
8386 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8387
8388 /* Map the window/widget. */
8389 #if USE_TOOLKIT_SCROLL_BARS
8390 {
8391 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8392 XtConfigureWidget (scroll_bar,
8393 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8394 top,
8395 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8396 height, 0);
8397 XtMapWidget (scroll_bar);
8398 }
8399 #else /* not USE_TOOLKIT_SCROLL_BARS */
8400 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8401 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8402
8403 UNBLOCK_INPUT;
8404 return bar;
8405 }
8406
8407
8408 /* Draw BAR's handle in the proper position.
8409
8410 If the handle is already drawn from START to END, don't bother
8411 redrawing it, unless REBUILD is non-zero; in that case, always
8412 redraw it. (REBUILD is handy for drawing the handle after expose
8413 events.)
8414
8415 Normally, we want to constrain the start and end of the handle to
8416 fit inside its rectangle, but if the user is dragging the scroll
8417 bar handle, we want to let them drag it down all the way, so that
8418 the bar's top is as far down as it goes; otherwise, there's no way
8419 to move to the very end of the buffer. */
8420
8421 #ifndef USE_TOOLKIT_SCROLL_BARS
8422
8423 static void
8424 x_scroll_bar_set_handle (bar, start, end, rebuild)
8425 struct scroll_bar *bar;
8426 int start, end;
8427 int rebuild;
8428 {
8429 int dragging = ! NILP (bar->dragging);
8430 Window w = SCROLL_BAR_X_WINDOW (bar);
8431 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8432 GC gc = f->output_data.x->normal_gc;
8433
8434 /* If the display is already accurate, do nothing. */
8435 if (! rebuild
8436 && start == XINT (bar->start)
8437 && end == XINT (bar->end))
8438 return;
8439
8440 BLOCK_INPUT;
8441
8442 {
8443 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8444 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8445 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8446
8447 /* Make sure the values are reasonable, and try to preserve
8448 the distance between start and end. */
8449 {
8450 int length = end - start;
8451
8452 if (start < 0)
8453 start = 0;
8454 else if (start > top_range)
8455 start = top_range;
8456 end = start + length;
8457
8458 if (end < start)
8459 end = start;
8460 else if (end > top_range && ! dragging)
8461 end = top_range;
8462 }
8463
8464 /* Store the adjusted setting in the scroll bar. */
8465 XSETINT (bar->start, start);
8466 XSETINT (bar->end, end);
8467
8468 /* Clip the end position, just for display. */
8469 if (end > top_range)
8470 end = top_range;
8471
8472 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8473 below top positions, to make sure the handle is always at least
8474 that many pixels tall. */
8475 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8476
8477 /* Draw the empty space above the handle. Note that we can't clear
8478 zero-height areas; that means "clear to end of window." */
8479 if (0 < start)
8480 XClearArea (FRAME_X_DISPLAY (f), w,
8481
8482 /* x, y, width, height, and exposures. */
8483 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8484 VERTICAL_SCROLL_BAR_TOP_BORDER,
8485 inside_width, start,
8486 False);
8487
8488 /* Change to proper foreground color if one is specified. */
8489 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8490 XSetForeground (FRAME_X_DISPLAY (f), gc,
8491 f->output_data.x->scroll_bar_foreground_pixel);
8492
8493 /* Draw the handle itself. */
8494 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8495
8496 /* x, y, width, height */
8497 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8498 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8499 inside_width, end - start);
8500
8501 /* Restore the foreground color of the GC if we changed it above. */
8502 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8503 XSetForeground (FRAME_X_DISPLAY (f), gc,
8504 f->output_data.x->foreground_pixel);
8505
8506 /* Draw the empty space below the handle. Note that we can't
8507 clear zero-height areas; that means "clear to end of window." */
8508 if (end < inside_height)
8509 XClearArea (FRAME_X_DISPLAY (f), w,
8510
8511 /* x, y, width, height, and exposures. */
8512 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8513 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8514 inside_width, inside_height - end,
8515 False);
8516
8517 }
8518
8519 UNBLOCK_INPUT;
8520 }
8521
8522 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8523
8524 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8525 nil. */
8526
8527 static void
8528 x_scroll_bar_remove (bar)
8529 struct scroll_bar *bar;
8530 {
8531 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8532 BLOCK_INPUT;
8533
8534 #if USE_TOOLKIT_SCROLL_BARS
8535 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8536 #else
8537 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8538 #endif
8539
8540 /* Disassociate this scroll bar from its window. */
8541 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8542
8543 UNBLOCK_INPUT;
8544 }
8545
8546
8547 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8548 that we are displaying PORTION characters out of a total of WHOLE
8549 characters, starting at POSITION. If WINDOW has no scroll bar,
8550 create one. */
8551
8552 static void
8553 XTset_vertical_scroll_bar (w, portion, whole, position)
8554 struct window *w;
8555 int portion, whole, position;
8556 {
8557 struct frame *f = XFRAME (w->frame);
8558 struct scroll_bar *bar;
8559 int top, height, left, sb_left, width, sb_width;
8560 int window_x, window_y, window_width, window_height;
8561
8562 /* Get window dimensions. */
8563 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8564 top = window_y;
8565 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8566 height = window_height;
8567
8568 /* Compute the left edge of the scroll bar area. */
8569 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8570 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8571 else
8572 left = XFASTINT (w->left);
8573 left *= CANON_X_UNIT (f);
8574 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8575
8576 /* Compute the width of the scroll bar which might be less than
8577 the width of the area reserved for the scroll bar. */
8578 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8579 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8580 else
8581 sb_width = width;
8582
8583 /* Compute the left edge of the scroll bar. */
8584 #ifdef USE_TOOLKIT_SCROLL_BARS
8585 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8586 sb_left = left + width - sb_width - (width - sb_width) / 2;
8587 else
8588 sb_left = left + (width - sb_width) / 2;
8589 #else
8590 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8591 sb_left = left + width - sb_width;
8592 else
8593 sb_left = left;
8594 #endif
8595
8596 /* Does the scroll bar exist yet? */
8597 if (NILP (w->vertical_scroll_bar))
8598 {
8599 BLOCK_INPUT;
8600 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8601 left, top, width, height, False);
8602 UNBLOCK_INPUT;
8603 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8604 }
8605 else
8606 {
8607 /* It may just need to be moved and resized. */
8608 unsigned int mask = 0;
8609
8610 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8611
8612 BLOCK_INPUT;
8613
8614 if (sb_left != XINT (bar->left))
8615 mask |= CWX;
8616 if (top != XINT (bar->top))
8617 mask |= CWY;
8618 if (sb_width != XINT (bar->width))
8619 mask |= CWWidth;
8620 if (height != XINT (bar->height))
8621 mask |= CWHeight;
8622
8623 #ifdef USE_TOOLKIT_SCROLL_BARS
8624
8625 /* Since toolkit scroll bars are smaller than the space reserved
8626 for them on the frame, we have to clear "under" them. */
8627 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8628 left, top, width, height, False);
8629
8630 /* Move/size the scroll bar widget. */
8631 if (mask)
8632 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
8633 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8634 top,
8635 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8636 height, 0);
8637
8638 #else /* not USE_TOOLKIT_SCROLL_BARS */
8639
8640 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8641 {
8642 /* Clear areas not covered by the scroll bar. This makes sure a
8643 previous mode line display is cleared after C-x 2 C-x 1, for
8644 example. Non-toolkit scroll bars are as wide as the area
8645 reserved for scroll bars - trim at both sides. */
8646 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8647 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8648 height, False);
8649 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8650 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8651 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8652 height, False);
8653 }
8654
8655 /* Move/size the scroll bar window. */
8656 if (mask)
8657 {
8658 XWindowChanges wc;
8659
8660 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8661 wc.y = top;
8662 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8663 wc.height = height;
8664 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8665 mask, &wc);
8666 }
8667
8668 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8669
8670 /* Remember new settings. */
8671 XSETINT (bar->left, sb_left);
8672 XSETINT (bar->top, top);
8673 XSETINT (bar->width, sb_width);
8674 XSETINT (bar->height, height);
8675
8676 UNBLOCK_INPUT;
8677 }
8678
8679 #if USE_TOOLKIT_SCROLL_BARS
8680 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8681 #else /* not USE_TOOLKIT_SCROLL_BARS */
8682 /* Set the scroll bar's current state, unless we're currently being
8683 dragged. */
8684 if (NILP (bar->dragging))
8685 {
8686 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8687
8688 if (whole == 0)
8689 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8690 else
8691 {
8692 int start = ((double) position * top_range) / whole;
8693 int end = ((double) (position + portion) * top_range) / whole;
8694 x_scroll_bar_set_handle (bar, start, end, 0);
8695 }
8696 }
8697 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8698
8699 XSETVECTOR (w->vertical_scroll_bar, bar);
8700 }
8701
8702
8703 /* The following three hooks are used when we're doing a thorough
8704 redisplay of the frame. We don't explicitly know which scroll bars
8705 are going to be deleted, because keeping track of when windows go
8706 away is a real pain - "Can you say set-window-configuration, boys
8707 and girls?" Instead, we just assert at the beginning of redisplay
8708 that *all* scroll bars are to be removed, and then save a scroll bar
8709 from the fiery pit when we actually redisplay its window. */
8710
8711 /* Arrange for all scroll bars on FRAME to be removed at the next call
8712 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8713 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8714
8715 static void
8716 XTcondemn_scroll_bars (frame)
8717 FRAME_PTR frame;
8718 {
8719 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8720 while (! NILP (FRAME_SCROLL_BARS (frame)))
8721 {
8722 Lisp_Object bar;
8723 bar = FRAME_SCROLL_BARS (frame);
8724 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8725 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8726 XSCROLL_BAR (bar)->prev = Qnil;
8727 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8728 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8729 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8730 }
8731 }
8732
8733
8734 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8735 Note that WINDOW isn't necessarily condemned at all. */
8736
8737 static void
8738 XTredeem_scroll_bar (window)
8739 struct window *window;
8740 {
8741 struct scroll_bar *bar;
8742 struct frame *f;
8743
8744 /* We can't redeem this window's scroll bar if it doesn't have one. */
8745 if (NILP (window->vertical_scroll_bar))
8746 abort ();
8747
8748 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8749
8750 /* Unlink it from the condemned list. */
8751 f = XFRAME (WINDOW_FRAME (window));
8752 if (NILP (bar->prev))
8753 {
8754 /* If the prev pointer is nil, it must be the first in one of
8755 the lists. */
8756 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8757 /* It's not condemned. Everything's fine. */
8758 return;
8759 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8760 window->vertical_scroll_bar))
8761 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8762 else
8763 /* If its prev pointer is nil, it must be at the front of
8764 one or the other! */
8765 abort ();
8766 }
8767 else
8768 XSCROLL_BAR (bar->prev)->next = bar->next;
8769
8770 if (! NILP (bar->next))
8771 XSCROLL_BAR (bar->next)->prev = bar->prev;
8772
8773 bar->next = FRAME_SCROLL_BARS (f);
8774 bar->prev = Qnil;
8775 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8776 if (! NILP (bar->next))
8777 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8778 }
8779
8780 /* Remove all scroll bars on FRAME that haven't been saved since the
8781 last call to `*condemn_scroll_bars_hook'. */
8782
8783 static void
8784 XTjudge_scroll_bars (f)
8785 FRAME_PTR f;
8786 {
8787 Lisp_Object bar, next;
8788
8789 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8790
8791 /* Clear out the condemned list now so we won't try to process any
8792 more events on the hapless scroll bars. */
8793 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8794
8795 for (; ! NILP (bar); bar = next)
8796 {
8797 struct scroll_bar *b = XSCROLL_BAR (bar);
8798
8799 x_scroll_bar_remove (b);
8800
8801 next = b->next;
8802 b->next = b->prev = Qnil;
8803 }
8804
8805 /* Now there should be no references to the condemned scroll bars,
8806 and they should get garbage-collected. */
8807 }
8808
8809
8810 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8811 is a no-op when using toolkit scroll bars.
8812
8813 This may be called from a signal handler, so we have to ignore GC
8814 mark bits. */
8815
8816 static void
8817 x_scroll_bar_expose (bar, event)
8818 struct scroll_bar *bar;
8819 XEvent *event;
8820 {
8821 #ifndef USE_TOOLKIT_SCROLL_BARS
8822
8823 Window w = SCROLL_BAR_X_WINDOW (bar);
8824 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8825 GC gc = f->output_data.x->normal_gc;
8826 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8827
8828 BLOCK_INPUT;
8829
8830 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8831
8832 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8833 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8834
8835 /* x, y, width, height */
8836 0, 0,
8837 XINT (bar->width) - 1 - width_trim - width_trim,
8838 XINT (bar->height) - 1);
8839
8840 UNBLOCK_INPUT;
8841
8842 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8843 }
8844
8845 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8846 is set to something other than no_event, it is enqueued.
8847
8848 This may be called from a signal handler, so we have to ignore GC
8849 mark bits. */
8850
8851 #ifndef USE_TOOLKIT_SCROLL_BARS
8852
8853 static void
8854 x_scroll_bar_handle_click (bar, event, emacs_event)
8855 struct scroll_bar *bar;
8856 XEvent *event;
8857 struct input_event *emacs_event;
8858 {
8859 if (! GC_WINDOWP (bar->window))
8860 abort ();
8861
8862 emacs_event->kind = scroll_bar_click;
8863 emacs_event->code = event->xbutton.button - Button1;
8864 emacs_event->modifiers
8865 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8866 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8867 event->xbutton.state)
8868 | (event->type == ButtonRelease
8869 ? up_modifier
8870 : down_modifier));
8871 emacs_event->frame_or_window = bar->window;
8872 emacs_event->arg = Qnil;
8873 emacs_event->timestamp = event->xbutton.time;
8874 {
8875 #if 0
8876 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8877 int internal_height
8878 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8879 #endif
8880 int top_range
8881 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8882 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8883
8884 if (y < 0) y = 0;
8885 if (y > top_range) y = top_range;
8886
8887 if (y < XINT (bar->start))
8888 emacs_event->part = scroll_bar_above_handle;
8889 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8890 emacs_event->part = scroll_bar_handle;
8891 else
8892 emacs_event->part = scroll_bar_below_handle;
8893
8894 /* Just because the user has clicked on the handle doesn't mean
8895 they want to drag it. Lisp code needs to be able to decide
8896 whether or not we're dragging. */
8897 #if 0
8898 /* If the user has just clicked on the handle, record where they're
8899 holding it. */
8900 if (event->type == ButtonPress
8901 && emacs_event->part == scroll_bar_handle)
8902 XSETINT (bar->dragging, y - XINT (bar->start));
8903 #endif
8904
8905 /* If the user has released the handle, set it to its final position. */
8906 if (event->type == ButtonRelease
8907 && ! NILP (bar->dragging))
8908 {
8909 int new_start = y - XINT (bar->dragging);
8910 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8911
8912 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8913 bar->dragging = Qnil;
8914 }
8915
8916 /* Same deal here as the other #if 0. */
8917 #if 0
8918 /* Clicks on the handle are always reported as occurring at the top of
8919 the handle. */
8920 if (emacs_event->part == scroll_bar_handle)
8921 emacs_event->x = bar->start;
8922 else
8923 XSETINT (emacs_event->x, y);
8924 #else
8925 XSETINT (emacs_event->x, y);
8926 #endif
8927
8928 XSETINT (emacs_event->y, top_range);
8929 }
8930 }
8931
8932 /* Handle some mouse motion while someone is dragging the scroll bar.
8933
8934 This may be called from a signal handler, so we have to ignore GC
8935 mark bits. */
8936
8937 static void
8938 x_scroll_bar_note_movement (bar, event)
8939 struct scroll_bar *bar;
8940 XEvent *event;
8941 {
8942 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8943
8944 last_mouse_movement_time = event->xmotion.time;
8945
8946 f->mouse_moved = 1;
8947 XSETVECTOR (last_mouse_scroll_bar, bar);
8948
8949 /* If we're dragging the bar, display it. */
8950 if (! GC_NILP (bar->dragging))
8951 {
8952 /* Where should the handle be now? */
8953 int new_start = event->xmotion.y - XINT (bar->dragging);
8954
8955 if (new_start != XINT (bar->start))
8956 {
8957 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8958
8959 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8960 }
8961 }
8962 }
8963
8964 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8965
8966 /* Return information to the user about the current position of the mouse
8967 on the scroll bar. */
8968
8969 static void
8970 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8971 FRAME_PTR *fp;
8972 Lisp_Object *bar_window;
8973 enum scroll_bar_part *part;
8974 Lisp_Object *x, *y;
8975 unsigned long *time;
8976 {
8977 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8978 Window w = SCROLL_BAR_X_WINDOW (bar);
8979 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8980 int win_x, win_y;
8981 Window dummy_window;
8982 int dummy_coord;
8983 unsigned int dummy_mask;
8984
8985 BLOCK_INPUT;
8986
8987 /* Get the mouse's position relative to the scroll bar window, and
8988 report that. */
8989 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8990
8991 /* Root, child, root x and root y. */
8992 &dummy_window, &dummy_window,
8993 &dummy_coord, &dummy_coord,
8994
8995 /* Position relative to scroll bar. */
8996 &win_x, &win_y,
8997
8998 /* Mouse buttons and modifier keys. */
8999 &dummy_mask))
9000 ;
9001 else
9002 {
9003 #if 0
9004 int inside_height
9005 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9006 #endif
9007 int top_range
9008 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
9009
9010 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9011
9012 if (! NILP (bar->dragging))
9013 win_y -= XINT (bar->dragging);
9014
9015 if (win_y < 0)
9016 win_y = 0;
9017 if (win_y > top_range)
9018 win_y = top_range;
9019
9020 *fp = f;
9021 *bar_window = bar->window;
9022
9023 if (! NILP (bar->dragging))
9024 *part = scroll_bar_handle;
9025 else if (win_y < XINT (bar->start))
9026 *part = scroll_bar_above_handle;
9027 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9028 *part = scroll_bar_handle;
9029 else
9030 *part = scroll_bar_below_handle;
9031
9032 XSETINT (*x, win_y);
9033 XSETINT (*y, top_range);
9034
9035 f->mouse_moved = 0;
9036 last_mouse_scroll_bar = Qnil;
9037 }
9038
9039 *time = last_mouse_movement_time;
9040
9041 UNBLOCK_INPUT;
9042 }
9043
9044
9045 /* The screen has been cleared so we may have changed foreground or
9046 background colors, and the scroll bars may need to be redrawn.
9047 Clear out the scroll bars, and ask for expose events, so we can
9048 redraw them. */
9049
9050 void
9051 x_scroll_bar_clear (f)
9052 FRAME_PTR f;
9053 {
9054 #ifndef USE_TOOLKIT_SCROLL_BARS
9055 Lisp_Object bar;
9056
9057 /* We can have scroll bars even if this is 0,
9058 if we just turned off scroll bar mode.
9059 But in that case we should not clear them. */
9060 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9061 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9062 bar = XSCROLL_BAR (bar)->next)
9063 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9064 0, 0, 0, 0, True);
9065 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9066 }
9067
9068 /* This processes Expose events from the menu-bar specific X event
9069 loop in xmenu.c. This allows to redisplay the frame if necessary
9070 when handling menu-bar or pop-up items. */
9071
9072 int
9073 process_expose_from_menu (event)
9074 XEvent event;
9075 {
9076 FRAME_PTR f;
9077 struct x_display_info *dpyinfo;
9078 int frame_exposed_p = 0;
9079
9080 BLOCK_INPUT;
9081
9082 dpyinfo = x_display_info_for_display (event.xexpose.display);
9083 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9084 if (f)
9085 {
9086 if (f->async_visible == 0)
9087 {
9088 f->async_visible = 1;
9089 f->async_iconified = 0;
9090 f->output_data.x->has_been_visible = 1;
9091 SET_FRAME_GARBAGED (f);
9092 }
9093 else
9094 {
9095 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9096 event.xexpose.x, event.xexpose.y,
9097 event.xexpose.width, event.xexpose.height);
9098 frame_exposed_p = 1;
9099 }
9100 }
9101 else
9102 {
9103 struct scroll_bar *bar
9104 = x_window_to_scroll_bar (event.xexpose.window);
9105
9106 if (bar)
9107 x_scroll_bar_expose (bar, &event);
9108 }
9109
9110 UNBLOCK_INPUT;
9111 return frame_exposed_p;
9112 }
9113 \f
9114 /* Define a queue to save up SelectionRequest events for later handling. */
9115
9116 struct selection_event_queue
9117 {
9118 XEvent event;
9119 struct selection_event_queue *next;
9120 };
9121
9122 static struct selection_event_queue *queue;
9123
9124 /* Nonzero means queue up certain events--don't process them yet. */
9125
9126 static int x_queue_selection_requests;
9127
9128 /* Queue up an X event *EVENT, to be processed later. */
9129
9130 static void
9131 x_queue_event (f, event)
9132 FRAME_PTR f;
9133 XEvent *event;
9134 {
9135 struct selection_event_queue *queue_tmp
9136 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
9137
9138 if (queue_tmp != NULL)
9139 {
9140 queue_tmp->event = *event;
9141 queue_tmp->next = queue;
9142 queue = queue_tmp;
9143 }
9144 }
9145
9146 /* Take all the queued events and put them back
9147 so that they get processed afresh. */
9148
9149 static void
9150 x_unqueue_events (display)
9151 Display *display;
9152 {
9153 while (queue != NULL)
9154 {
9155 struct selection_event_queue *queue_tmp = queue;
9156 XPutBackEvent (display, &queue_tmp->event);
9157 queue = queue_tmp->next;
9158 xfree ((char *)queue_tmp);
9159 }
9160 }
9161
9162 /* Start queuing SelectionRequest events. */
9163
9164 void
9165 x_start_queuing_selection_requests (display)
9166 Display *display;
9167 {
9168 x_queue_selection_requests++;
9169 }
9170
9171 /* Stop queuing SelectionRequest events. */
9172
9173 void
9174 x_stop_queuing_selection_requests (display)
9175 Display *display;
9176 {
9177 x_queue_selection_requests--;
9178 x_unqueue_events (display);
9179 }
9180 \f
9181 /* The main X event-reading loop - XTread_socket. */
9182
9183 /* Time stamp of enter window event. This is only used by XTread_socket,
9184 but we have to put it out here, since static variables within functions
9185 sometimes don't work. */
9186
9187 static Time enter_timestamp;
9188
9189 /* This holds the state XLookupString needs to implement dead keys
9190 and other tricks known as "compose processing". _X Window System_
9191 says that a portable program can't use this, but Stephen Gildea assures
9192 me that letting the compiler initialize it to zeros will work okay.
9193
9194 This must be defined outside of XTread_socket, for the same reasons
9195 given for enter_time stamp, above. */
9196
9197 static XComposeStatus compose_status;
9198
9199 /* Record the last 100 characters stored
9200 to help debug the loss-of-chars-during-GC problem. */
9201
9202 static int temp_index;
9203 static short temp_buffer[100];
9204
9205 /* Set this to nonzero to fake an "X I/O error"
9206 on a particular display. */
9207
9208 struct x_display_info *XTread_socket_fake_io_error;
9209
9210 /* When we find no input here, we occasionally do a no-op command
9211 to verify that the X server is still running and we can still talk with it.
9212 We try all the open displays, one by one.
9213 This variable is used for cycling thru the displays. */
9214
9215 static struct x_display_info *next_noop_dpyinfo;
9216
9217 #define SET_SAVED_MENU_EVENT(size) \
9218 do \
9219 { \
9220 if (f->output_data.x->saved_menu_event == 0) \
9221 f->output_data.x->saved_menu_event \
9222 = (XEvent *) xmalloc (sizeof (XEvent)); \
9223 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9224 if (numchars >= 1) \
9225 { \
9226 bufp->kind = menu_bar_activate_event; \
9227 XSETFRAME (bufp->frame_or_window, f); \
9228 bufp->arg = Qnil; \
9229 bufp++; \
9230 count++; \
9231 numchars--; \
9232 } \
9233 } \
9234 while (0)
9235
9236 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
9237 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
9238
9239 /* Read events coming from the X server.
9240 This routine is called by the SIGIO handler.
9241 We return as soon as there are no more events to be read.
9242
9243 Events representing keys are stored in buffer BUFP,
9244 which can hold up to NUMCHARS characters.
9245 We return the number of characters stored into the buffer,
9246 thus pretending to be `read'.
9247
9248 EXPECTED is nonzero if the caller knows input is available. */
9249
9250 int
9251 XTread_socket (sd, bufp, numchars, expected)
9252 register int sd;
9253 /* register */ struct input_event *bufp;
9254 /* register */ int numchars;
9255 int expected;
9256 {
9257 int count = 0;
9258 int nbytes = 0;
9259 XEvent event;
9260 struct frame *f;
9261 int event_found = 0;
9262 struct x_display_info *dpyinfo;
9263 struct coding_system coding;
9264
9265 if (interrupt_input_blocked)
9266 {
9267 interrupt_input_pending = 1;
9268 return -1;
9269 }
9270
9271 interrupt_input_pending = 0;
9272 BLOCK_INPUT;
9273
9274 /* So people can tell when we have read the available input. */
9275 input_signal_count++;
9276
9277 if (numchars <= 0)
9278 abort (); /* Don't think this happens. */
9279
9280 ++handling_signal;
9281
9282 /* The input should be decoded if it is from XIM. Currently the
9283 locale of XIM is the same as that of the system. So, we can use
9284 Vlocale_coding_system which is initialized properly at Emacs
9285 startup time. */
9286 setup_coding_system (Vlocale_coding_system, &coding);
9287 coding.src_multibyte = 0;
9288 coding.dst_multibyte = 1;
9289 /* The input is converted to events, thus we can't handle
9290 composition. Anyway, there's no XIM that gives us composition
9291 information. */
9292 coding.composing = COMPOSITION_DISABLED;
9293
9294 /* Find the display we are supposed to read input for.
9295 It's the one communicating on descriptor SD. */
9296 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9297 {
9298 #if 0 /* This ought to be unnecessary; let's verify it. */
9299 #ifdef FIOSNBIO
9300 /* If available, Xlib uses FIOSNBIO to make the socket
9301 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
9302 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
9303 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
9304 fcntl (dpyinfo->connection, F_SETFL, 0);
9305 #endif /* ! defined (FIOSNBIO) */
9306 #endif
9307
9308 #if 0 /* This code can't be made to work, with multiple displays,
9309 and appears not to be used on any system any more.
9310 Also keyboard.c doesn't turn O_NDELAY on and off
9311 for X connections. */
9312 #ifndef SIGIO
9313 #ifndef HAVE_SELECT
9314 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9315 {
9316 extern int read_alarm_should_throw;
9317 read_alarm_should_throw = 1;
9318 XPeekEvent (dpyinfo->display, &event);
9319 read_alarm_should_throw = 0;
9320 }
9321 #endif /* HAVE_SELECT */
9322 #endif /* SIGIO */
9323 #endif
9324
9325 /* For debugging, this gives a way to fake an I/O error. */
9326 if (dpyinfo == XTread_socket_fake_io_error)
9327 {
9328 XTread_socket_fake_io_error = 0;
9329 x_io_error_quitter (dpyinfo->display);
9330 }
9331
9332 while (XPending (dpyinfo->display))
9333 {
9334 XNextEvent (dpyinfo->display, &event);
9335
9336 #ifdef HAVE_X_I18N
9337 {
9338 /* Filter events for the current X input method.
9339 XFilterEvent returns non-zero if the input method has
9340 consumed the event. We pass the frame's X window to
9341 XFilterEvent because that's the one for which the IC
9342 was created. */
9343 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9344 event.xclient.window);
9345 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9346 break;
9347 }
9348 #endif
9349 event_found = 1;
9350
9351 switch (event.type)
9352 {
9353 case ClientMessage:
9354 {
9355 if (event.xclient.message_type
9356 == dpyinfo->Xatom_wm_protocols
9357 && event.xclient.format == 32)
9358 {
9359 if (event.xclient.data.l[0]
9360 == dpyinfo->Xatom_wm_take_focus)
9361 {
9362 /* Use x_any_window_to_frame because this
9363 could be the shell widget window
9364 if the frame has no title bar. */
9365 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9366 #ifdef HAVE_X_I18N
9367 /* Not quite sure this is needed -pd */
9368 if (f && FRAME_XIC (f))
9369 XSetICFocus (FRAME_XIC (f));
9370 #endif
9371 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9372 instructs the WM to set the input focus automatically for
9373 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9374 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9375 it has set the focus. So, XSetInputFocus below is not
9376 needed.
9377
9378 The call to XSetInputFocus below has also caused trouble. In
9379 cases where the XSetInputFocus done by the WM and the one
9380 below are temporally close (on a fast machine), the call
9381 below can generate additional FocusIn events which confuse
9382 Emacs. */
9383
9384 /* Since we set WM_TAKE_FOCUS, we must call
9385 XSetInputFocus explicitly. But not if f is null,
9386 since that might be an event for a deleted frame. */
9387 if (f)
9388 {
9389 Display *d = event.xclient.display;
9390 /* Catch and ignore errors, in case window has been
9391 iconified by a window manager such as GWM. */
9392 int count = x_catch_errors (d);
9393 XSetInputFocus (d, event.xclient.window,
9394 /* The ICCCM says this is
9395 the only valid choice. */
9396 RevertToParent,
9397 event.xclient.data.l[1]);
9398 /* This is needed to detect the error
9399 if there is an error. */
9400 XSync (d, False);
9401 x_uncatch_errors (d, count);
9402 }
9403 /* Not certain about handling scroll bars here */
9404 #endif /* 0 */
9405 }
9406 else if (event.xclient.data.l[0]
9407 == dpyinfo->Xatom_wm_save_yourself)
9408 {
9409 /* Save state modify the WM_COMMAND property to
9410 something which can reinstate us. This notifies
9411 the session manager, who's looking for such a
9412 PropertyNotify. Can restart processing when
9413 a keyboard or mouse event arrives. */
9414 if (numchars > 0)
9415 {
9416 f = x_top_window_to_frame (dpyinfo,
9417 event.xclient.window);
9418
9419 /* This is just so we only give real data once
9420 for a single Emacs process. */
9421 if (f == SELECTED_FRAME ())
9422 XSetCommand (FRAME_X_DISPLAY (f),
9423 event.xclient.window,
9424 initial_argv, initial_argc);
9425 else if (f)
9426 XSetCommand (FRAME_X_DISPLAY (f),
9427 event.xclient.window,
9428 0, 0);
9429 }
9430 }
9431 else if (event.xclient.data.l[0]
9432 == dpyinfo->Xatom_wm_delete_window)
9433 {
9434 struct frame *f
9435 = x_any_window_to_frame (dpyinfo,
9436 event.xclient.window);
9437
9438 if (f)
9439 {
9440 if (numchars == 0)
9441 abort ();
9442
9443 bufp->kind = delete_window_event;
9444 XSETFRAME (bufp->frame_or_window, f);
9445 bufp->arg = Qnil;
9446 bufp++;
9447
9448 count += 1;
9449 numchars -= 1;
9450 }
9451 }
9452 }
9453 else if (event.xclient.message_type
9454 == dpyinfo->Xatom_wm_configure_denied)
9455 {
9456 }
9457 else if (event.xclient.message_type
9458 == dpyinfo->Xatom_wm_window_moved)
9459 {
9460 int new_x, new_y;
9461 struct frame *f
9462 = x_window_to_frame (dpyinfo, event.xclient.window);
9463
9464 new_x = event.xclient.data.s[0];
9465 new_y = event.xclient.data.s[1];
9466
9467 if (f)
9468 {
9469 f->output_data.x->left_pos = new_x;
9470 f->output_data.x->top_pos = new_y;
9471 }
9472 }
9473 #ifdef HACK_EDITRES
9474 else if (event.xclient.message_type
9475 == dpyinfo->Xatom_editres)
9476 {
9477 struct frame *f
9478 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9479 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9480 &event, NULL);
9481 }
9482 #endif /* HACK_EDITRES */
9483 else if ((event.xclient.message_type
9484 == dpyinfo->Xatom_DONE)
9485 || (event.xclient.message_type
9486 == dpyinfo->Xatom_PAGE))
9487 {
9488 /* Ghostview job completed. Kill it. We could
9489 reply with "Next" if we received "Page", but we
9490 currently never do because we are interested in
9491 images, only, which should have 1 page. */
9492 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9493 struct frame *f
9494 = x_window_to_frame (dpyinfo, event.xclient.window);
9495 x_kill_gs_process (pixmap, f);
9496 expose_frame (f, 0, 0, 0, 0);
9497 }
9498 #ifdef USE_TOOLKIT_SCROLL_BARS
9499 /* Scroll bar callbacks send a ClientMessage from which
9500 we construct an input_event. */
9501 else if (event.xclient.message_type
9502 == dpyinfo->Xatom_Scrollbar)
9503 {
9504 x_scroll_bar_to_input_event (&event, bufp);
9505 ++bufp, ++count, --numchars;
9506 goto out;
9507 }
9508 #endif /* USE_TOOLKIT_SCROLL_BARS */
9509 else
9510 goto OTHER;
9511 }
9512 break;
9513
9514 case SelectionNotify:
9515 #ifdef USE_X_TOOLKIT
9516 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9517 goto OTHER;
9518 #endif /* not USE_X_TOOLKIT */
9519 x_handle_selection_notify (&event.xselection);
9520 break;
9521
9522 case SelectionClear: /* Someone has grabbed ownership. */
9523 #ifdef USE_X_TOOLKIT
9524 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9525 goto OTHER;
9526 #endif /* USE_X_TOOLKIT */
9527 {
9528 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9529
9530 if (numchars == 0)
9531 abort ();
9532
9533 bufp->kind = selection_clear_event;
9534 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9535 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9536 SELECTION_EVENT_TIME (bufp) = eventp->time;
9537 bufp->frame_or_window = Qnil;
9538 bufp->arg = Qnil;
9539 bufp++;
9540
9541 count += 1;
9542 numchars -= 1;
9543 }
9544 break;
9545
9546 case SelectionRequest: /* Someone wants our selection. */
9547 #ifdef USE_X_TOOLKIT
9548 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9549 goto OTHER;
9550 #endif /* USE_X_TOOLKIT */
9551 if (x_queue_selection_requests)
9552 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9553 &event);
9554 else
9555 {
9556 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9557
9558 if (numchars == 0)
9559 abort ();
9560
9561 bufp->kind = selection_request_event;
9562 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9563 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9564 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9565 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9566 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9567 SELECTION_EVENT_TIME (bufp) = eventp->time;
9568 bufp->frame_or_window = Qnil;
9569 bufp->arg = Qnil;
9570 bufp++;
9571
9572 count += 1;
9573 numchars -= 1;
9574 }
9575 break;
9576
9577 case PropertyNotify:
9578 #ifdef USE_X_TOOLKIT
9579 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9580 goto OTHER;
9581 #endif /* not USE_X_TOOLKIT */
9582 x_handle_property_notify (&event.xproperty);
9583 break;
9584
9585 case ReparentNotify:
9586 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9587 if (f)
9588 {
9589 int x, y;
9590 f->output_data.x->parent_desc = event.xreparent.parent;
9591 x_real_positions (f, &x, &y);
9592 f->output_data.x->left_pos = x;
9593 f->output_data.x->top_pos = y;
9594 }
9595 break;
9596
9597 case Expose:
9598 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9599 if (f)
9600 {
9601 if (f->async_visible == 0)
9602 {
9603 f->async_visible = 1;
9604 f->async_iconified = 0;
9605 f->output_data.x->has_been_visible = 1;
9606 SET_FRAME_GARBAGED (f);
9607 }
9608 else
9609 expose_frame (x_window_to_frame (dpyinfo,
9610 event.xexpose.window),
9611 event.xexpose.x, event.xexpose.y,
9612 event.xexpose.width, event.xexpose.height);
9613 }
9614 else
9615 {
9616 #ifdef USE_TOOLKIT_SCROLL_BARS
9617 /* Dispatch event to the widget. */
9618 goto OTHER;
9619 #else /* not USE_TOOLKIT_SCROLL_BARS */
9620 struct scroll_bar *bar
9621 = x_window_to_scroll_bar (event.xexpose.window);
9622
9623 if (bar)
9624 x_scroll_bar_expose (bar, &event);
9625 #ifdef USE_X_TOOLKIT
9626 else
9627 goto OTHER;
9628 #endif /* USE_X_TOOLKIT */
9629 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9630 }
9631 break;
9632
9633 case GraphicsExpose: /* This occurs when an XCopyArea's
9634 source area was obscured or not
9635 available.*/
9636 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9637 if (f)
9638 {
9639 expose_frame (f,
9640 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9641 event.xgraphicsexpose.width,
9642 event.xgraphicsexpose.height);
9643 }
9644 #ifdef USE_X_TOOLKIT
9645 else
9646 goto OTHER;
9647 #endif /* USE_X_TOOLKIT */
9648 break;
9649
9650 case NoExpose: /* This occurs when an XCopyArea's
9651 source area was completely
9652 available */
9653 break;
9654
9655 case UnmapNotify:
9656 /* Redo the mouse-highlight after the tooltip has gone. */
9657 if (event.xmap.window == tip_window)
9658 {
9659 tip_window = 0;
9660 redo_mouse_highlight ();
9661 }
9662
9663 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9664 if (f) /* F may no longer exist if
9665 the frame was deleted. */
9666 {
9667 /* While a frame is unmapped, display generation is
9668 disabled; you don't want to spend time updating a
9669 display that won't ever be seen. */
9670 f->async_visible = 0;
9671 /* We can't distinguish, from the event, whether the window
9672 has become iconified or invisible. So assume, if it
9673 was previously visible, than now it is iconified.
9674 But x_make_frame_invisible clears both
9675 the visible flag and the iconified flag;
9676 and that way, we know the window is not iconified now. */
9677 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9678 {
9679 f->async_iconified = 1;
9680
9681 bufp->kind = iconify_event;
9682 XSETFRAME (bufp->frame_or_window, f);
9683 bufp->arg = Qnil;
9684 bufp++;
9685 count++;
9686 numchars--;
9687 }
9688 }
9689 goto OTHER;
9690
9691 case MapNotify:
9692 if (event.xmap.window == tip_window)
9693 /* The tooltip has been drawn already. Avoid
9694 the SET_FRAME_GARBAGED below. */
9695 goto OTHER;
9696
9697 /* We use x_top_window_to_frame because map events can
9698 come for sub-windows and they don't mean that the
9699 frame is visible. */
9700 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9701 if (f)
9702 {
9703 f->async_visible = 1;
9704 f->async_iconified = 0;
9705 f->output_data.x->has_been_visible = 1;
9706
9707 /* wait_reading_process_input will notice this and update
9708 the frame's display structures. */
9709 SET_FRAME_GARBAGED (f);
9710
9711 if (f->iconified)
9712 {
9713 bufp->kind = deiconify_event;
9714 XSETFRAME (bufp->frame_or_window, f);
9715 bufp->arg = Qnil;
9716 bufp++;
9717 count++;
9718 numchars--;
9719 }
9720 else if (! NILP (Vframe_list)
9721 && ! NILP (XCDR (Vframe_list)))
9722 /* Force a redisplay sooner or later
9723 to update the frame titles
9724 in case this is the second frame. */
9725 record_asynch_buffer_change ();
9726 }
9727 goto OTHER;
9728
9729 case KeyPress:
9730 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9731
9732 #ifdef USE_MOTIF
9733 /* I couldn't find a way to prevent LessTif scroll bars
9734 from consuming key events. */
9735 if (f == 0)
9736 {
9737 Widget widget = XtWindowToWidget (dpyinfo->display,
9738 event.xkey.window);
9739 if (widget && XmIsScrollBar (widget))
9740 {
9741 widget = XtParent (widget);
9742 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9743 }
9744 }
9745 #endif /* USE_MOTIF */
9746
9747 if (f != 0)
9748 {
9749 KeySym keysym, orig_keysym;
9750 /* al%imercury@uunet.uu.net says that making this 81
9751 instead of 80 fixed a bug whereby meta chars made
9752 his Emacs hang.
9753
9754 It seems that some version of XmbLookupString has
9755 a bug of not returning XBufferOverflow in
9756 status_return even if the input is too long to
9757 fit in 81 bytes. So, we must prepare sufficient
9758 bytes for copy_buffer. 513 bytes (256 chars for
9759 two-byte character set) seems to be a faily good
9760 approximation. -- 2000.8.10 handa@etl.go.jp */
9761 unsigned char copy_buffer[513];
9762 unsigned char *copy_bufptr = copy_buffer;
9763 int copy_bufsiz = sizeof (copy_buffer);
9764 int modifiers;
9765
9766 event.xkey.state
9767 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9768 extra_keyboard_modifiers);
9769 modifiers = event.xkey.state;
9770
9771 /* This will have to go some day... */
9772
9773 /* make_lispy_event turns chars into control chars.
9774 Don't do it here because XLookupString is too eager. */
9775 event.xkey.state &= ~ControlMask;
9776 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9777 | dpyinfo->super_mod_mask
9778 | dpyinfo->hyper_mod_mask
9779 | dpyinfo->alt_mod_mask);
9780
9781 /* In case Meta is ComposeCharacter,
9782 clear its status. According to Markus Ehrnsperger
9783 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9784 this enables ComposeCharacter to work whether or
9785 not it is combined with Meta. */
9786 if (modifiers & dpyinfo->meta_mod_mask)
9787 bzero (&compose_status, sizeof (compose_status));
9788
9789 #ifdef HAVE_X_I18N
9790 if (FRAME_XIC (f))
9791 {
9792 Status status_return;
9793
9794 nbytes = XmbLookupString (FRAME_XIC (f),
9795 &event.xkey, copy_bufptr,
9796 copy_bufsiz, &keysym,
9797 &status_return);
9798 if (status_return == XBufferOverflow)
9799 {
9800 copy_bufsiz = nbytes + 1;
9801 copy_bufptr = (char *) alloca (copy_bufsiz);
9802 nbytes = XmbLookupString (FRAME_XIC (f),
9803 &event.xkey, copy_bufptr,
9804 copy_bufsiz, &keysym,
9805 &status_return);
9806 }
9807
9808 if (status_return == XLookupNone)
9809 break;
9810 else if (status_return == XLookupChars)
9811 {
9812 keysym = NoSymbol;
9813 modifiers = 0;
9814 }
9815 else if (status_return != XLookupKeySym
9816 && status_return != XLookupBoth)
9817 abort ();
9818 }
9819 else
9820 nbytes = XLookupString (&event.xkey, copy_bufptr,
9821 copy_bufsiz, &keysym,
9822 &compose_status);
9823 #else
9824 nbytes = XLookupString (&event.xkey, copy_bufptr,
9825 copy_bufsiz, &keysym,
9826 &compose_status);
9827 #endif
9828
9829 orig_keysym = keysym;
9830
9831 if (numchars > 1)
9832 {
9833 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9834 || keysym == XK_Delete
9835 #ifdef XK_ISO_Left_Tab
9836 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9837 #endif
9838 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9839 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9840 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9841 #ifdef HPUX
9842 /* This recognizes the "extended function keys".
9843 It seems there's no cleaner way.
9844 Test IsModifierKey to avoid handling mode_switch
9845 incorrectly. */
9846 || ((unsigned) (keysym) >= XK_Select
9847 && (unsigned)(keysym) < XK_KP_Space)
9848 #endif
9849 #ifdef XK_dead_circumflex
9850 || orig_keysym == XK_dead_circumflex
9851 #endif
9852 #ifdef XK_dead_grave
9853 || orig_keysym == XK_dead_grave
9854 #endif
9855 #ifdef XK_dead_tilde
9856 || orig_keysym == XK_dead_tilde
9857 #endif
9858 #ifdef XK_dead_diaeresis
9859 || orig_keysym == XK_dead_diaeresis
9860 #endif
9861 #ifdef XK_dead_macron
9862 || orig_keysym == XK_dead_macron
9863 #endif
9864 #ifdef XK_dead_degree
9865 || orig_keysym == XK_dead_degree
9866 #endif
9867 #ifdef XK_dead_acute
9868 || orig_keysym == XK_dead_acute
9869 #endif
9870 #ifdef XK_dead_cedilla
9871 || orig_keysym == XK_dead_cedilla
9872 #endif
9873 #ifdef XK_dead_breve
9874 || orig_keysym == XK_dead_breve
9875 #endif
9876 #ifdef XK_dead_ogonek
9877 || orig_keysym == XK_dead_ogonek
9878 #endif
9879 #ifdef XK_dead_caron
9880 || orig_keysym == XK_dead_caron
9881 #endif
9882 #ifdef XK_dead_doubleacute
9883 || orig_keysym == XK_dead_doubleacute
9884 #endif
9885 #ifdef XK_dead_abovedot
9886 || orig_keysym == XK_dead_abovedot
9887 #endif
9888 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9889 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9890 /* Any "vendor-specific" key is ok. */
9891 || (orig_keysym & (1 << 28)))
9892 && ! (IsModifierKey (orig_keysym)
9893 #ifndef HAVE_X11R5
9894 #ifdef XK_Mode_switch
9895 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9896 #endif
9897 #ifdef XK_Num_Lock
9898 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9899 #endif
9900 #endif /* not HAVE_X11R5 */
9901 ))
9902 {
9903 if (temp_index == sizeof temp_buffer / sizeof (short))
9904 temp_index = 0;
9905 temp_buffer[temp_index++] = keysym;
9906 bufp->kind = non_ascii_keystroke;
9907 bufp->code = keysym;
9908 XSETFRAME (bufp->frame_or_window, f);
9909 bufp->arg = Qnil;
9910 bufp->modifiers
9911 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9912 modifiers);
9913 bufp->timestamp = event.xkey.time;
9914 bufp++;
9915 count++;
9916 numchars--;
9917 }
9918 else if (numchars > nbytes)
9919 {
9920 register int i;
9921 register int c;
9922 unsigned char *p, *pend;
9923 int nchars, len;
9924
9925 for (i = 0; i < nbytes; i++)
9926 {
9927 if (temp_index == (sizeof temp_buffer
9928 / sizeof (short)))
9929 temp_index = 0;
9930 temp_buffer[temp_index++] = copy_bufptr[i];
9931 }
9932
9933 if (/* If the event is not from XIM, */
9934 event.xkey.keycode != 0
9935 /* or the current locale doesn't request
9936 decoding of the intup data, ... */
9937 || coding.type == coding_type_raw_text
9938 || coding.type == coding_type_no_conversion)
9939 {
9940 /* ... we can use the input data as is. */
9941 nchars = nbytes;
9942 }
9943 else
9944 {
9945 /* We have to decode the input data. */
9946 int require;
9947 unsigned char *p;
9948
9949 require = decoding_buffer_size (&coding, nbytes);
9950 p = (unsigned char *) alloca (require);
9951 coding.mode |= CODING_MODE_LAST_BLOCK;
9952 decode_coding (&coding, copy_bufptr, p,
9953 nbytes, require);
9954 nbytes = coding.produced;
9955 nchars = coding.produced_char;
9956 copy_bufptr = p;
9957 }
9958
9959 /* Convert the input data to a sequence of
9960 character events. */
9961 for (i = 0; i < nbytes; i += len)
9962 {
9963 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9964 nbytes - i, len);
9965 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9966 ? ascii_keystroke
9967 : multibyte_char_keystroke);
9968 bufp->code = c;
9969 XSETFRAME (bufp->frame_or_window, f);
9970 bufp->arg = Qnil;
9971 bufp->modifiers
9972 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9973 modifiers);
9974 bufp->timestamp = event.xkey.time;
9975 bufp++;
9976 }
9977
9978 count += nchars;
9979 numchars -= nchars;
9980
9981 if (keysym == NoSymbol)
9982 break;
9983 }
9984 else
9985 abort ();
9986 }
9987 else
9988 abort ();
9989 }
9990 #ifdef HAVE_X_I18N
9991 /* Don't dispatch this event since XtDispatchEvent calls
9992 XFilterEvent, and two calls in a row may freeze the
9993 client. */
9994 break;
9995 #else
9996 goto OTHER;
9997 #endif
9998
9999 case KeyRelease:
10000 #ifdef HAVE_X_I18N
10001 /* Don't dispatch this event since XtDispatchEvent calls
10002 XFilterEvent, and two calls in a row may freeze the
10003 client. */
10004 break;
10005 #else
10006 goto OTHER;
10007 #endif
10008
10009 /* Here's a possible interpretation of the whole
10010 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10011 you get a FocusIn event, you have to get a FocusOut
10012 event before you relinquish the focus. If you
10013 haven't received a FocusIn event, then a mere
10014 LeaveNotify is enough to free you. */
10015
10016 case EnterNotify:
10017 {
10018 int from_menu_bar_p = 0;
10019
10020 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10021
10022 #ifdef LESSTIF_VERSION
10023 /* When clicking outside of a menu bar popup to close
10024 it, we get a FocusIn/ EnterNotify sequence of
10025 events. The flag event.xcrossing.focus is not set
10026 in the EnterNotify event of that sequence because
10027 the focus is in the menu bar,
10028 event.xcrossing.window is the frame's X window.
10029 Unconditionally setting the focus frame to null in
10030 this case is not the right thing, because no event
10031 follows that could set the focus frame to the right
10032 value.
10033
10034 This could be a LessTif bug, but I wasn't able to
10035 reproduce the behavior in a simple test program.
10036
10037 (gerd, LessTif 0.88.1). */
10038
10039 if (!event.xcrossing.focus
10040 && f
10041 && f->output_data.x->menubar_widget)
10042 {
10043 Window focus;
10044 int revert;
10045
10046 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10047 if (focus == XtWindow (f->output_data.x->menubar_widget))
10048 from_menu_bar_p = 1;
10049 }
10050 #endif /* LESSTIF_VERSION */
10051
10052 if (event.xcrossing.focus || from_menu_bar_p)
10053 {
10054 /* Avoid nasty pop/raise loops. */
10055 if (f && (!(f->auto_raise)
10056 || !(f->auto_lower)
10057 || (event.xcrossing.time - enter_timestamp) > 500))
10058 {
10059 x_new_focus_frame (dpyinfo, f);
10060 enter_timestamp = event.xcrossing.time;
10061 }
10062 }
10063 else if (f == dpyinfo->x_focus_frame)
10064 x_new_focus_frame (dpyinfo, 0);
10065
10066 /* EnterNotify counts as mouse movement,
10067 so update things that depend on mouse position. */
10068 if (f && !f->output_data.x->busy_p)
10069 note_mouse_movement (f, &event.xmotion);
10070 goto OTHER;
10071 }
10072
10073 case FocusIn:
10074 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10075 if (event.xfocus.detail != NotifyPointer)
10076 dpyinfo->x_focus_event_frame = f;
10077 if (f)
10078 {
10079 x_new_focus_frame (dpyinfo, f);
10080
10081 /* Don't stop displaying the initial startup message
10082 for a switch-frame event we don't need. */
10083 if (GC_NILP (Vterminal_frame)
10084 && GC_CONSP (Vframe_list)
10085 && !GC_NILP (XCDR (Vframe_list)))
10086 {
10087 bufp->kind = FOCUS_IN_EVENT;
10088 XSETFRAME (bufp->frame_or_window, f);
10089 bufp->arg = Qnil;
10090 ++bufp, ++count, --numchars;
10091 }
10092 }
10093
10094 #ifdef HAVE_X_I18N
10095 if (f && FRAME_XIC (f))
10096 XSetICFocus (FRAME_XIC (f));
10097 #endif
10098
10099 goto OTHER;
10100
10101 case LeaveNotify:
10102 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
10103 if (f)
10104 {
10105 Lisp_Object frame;
10106 int from_menu_bar_p = 0;
10107
10108 if (f == dpyinfo->mouse_face_mouse_frame)
10109 {
10110 /* If we move outside the frame, then we're
10111 certainly no longer on any text in the frame. */
10112 clear_mouse_face (dpyinfo);
10113 dpyinfo->mouse_face_mouse_frame = 0;
10114 }
10115
10116 /* Generate a nil HELP_EVENT to cancel a help-echo.
10117 Do it only if there's something to cancel.
10118 Otherwise, the startup message is cleared when
10119 the mouse leaves the frame. */
10120 if (any_help_event_p)
10121 {
10122 Lisp_Object frame;
10123 int n;
10124
10125 XSETFRAME (frame, f);
10126 n = gen_help_event (bufp, numchars,
10127 Qnil, frame, Qnil, Qnil, 0);
10128 bufp += n, count += n, numchars -= n;
10129 }
10130
10131 #ifdef LESSTIF_VERSION
10132 /* Please see the comment at the start of the
10133 EnterNotify case. */
10134 if (!event.xcrossing.focus
10135 && f->output_data.x->menubar_widget)
10136 {
10137 Window focus;
10138 int revert;
10139 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10140 if (focus == XtWindow (f->output_data.x->menubar_widget))
10141 from_menu_bar_p = 1;
10142 }
10143 #endif /* LESSTIF_VERSION */
10144
10145 if (event.xcrossing.focus || from_menu_bar_p)
10146 x_mouse_leave (dpyinfo);
10147 else
10148 {
10149 if (f == dpyinfo->x_focus_event_frame)
10150 dpyinfo->x_focus_event_frame = 0;
10151 if (f == dpyinfo->x_focus_frame)
10152 x_new_focus_frame (dpyinfo, 0);
10153 }
10154 }
10155 goto OTHER;
10156
10157 case FocusOut:
10158 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
10159 if (event.xfocus.detail != NotifyPointer
10160 && f == dpyinfo->x_focus_event_frame)
10161 dpyinfo->x_focus_event_frame = 0;
10162 if (f && f == dpyinfo->x_focus_frame)
10163 x_new_focus_frame (dpyinfo, 0);
10164
10165 #ifdef HAVE_X_I18N
10166 if (f && FRAME_XIC (f))
10167 XUnsetICFocus (FRAME_XIC (f));
10168 #endif
10169
10170 goto OTHER;
10171
10172 case MotionNotify:
10173 {
10174 previous_help_echo = help_echo;
10175 help_echo = help_echo_object = help_echo_window = Qnil;
10176 help_echo_pos = -1;
10177
10178 if (dpyinfo->grabbed && last_mouse_frame
10179 && FRAME_LIVE_P (last_mouse_frame))
10180 f = last_mouse_frame;
10181 else
10182 f = x_window_to_frame (dpyinfo, event.xmotion.window);
10183
10184 if (f)
10185 note_mouse_movement (f, &event.xmotion);
10186 else
10187 {
10188 #ifndef USE_TOOLKIT_SCROLL_BARS
10189 struct scroll_bar *bar
10190 = x_window_to_scroll_bar (event.xmotion.window);
10191
10192 if (bar)
10193 x_scroll_bar_note_movement (bar, &event);
10194 #endif /* USE_TOOLKIT_SCROLL_BARS */
10195
10196 /* If we move outside the frame, then we're
10197 certainly no longer on any text in the frame. */
10198 clear_mouse_face (dpyinfo);
10199 }
10200
10201 /* If the contents of the global variable help_echo
10202 has changed, generate a HELP_EVENT. */
10203 if (!NILP (help_echo)
10204 || !NILP (previous_help_echo))
10205 {
10206 Lisp_Object frame;
10207 int n;
10208
10209 if (f)
10210 XSETFRAME (frame, f);
10211 else
10212 frame = Qnil;
10213
10214 any_help_event_p = 1;
10215 n = gen_help_event (bufp, numchars, help_echo, frame,
10216 help_echo_window, help_echo_object,
10217 help_echo_pos);
10218 bufp += n, count += n, numchars -= n;
10219 }
10220
10221 goto OTHER;
10222 }
10223
10224 case ConfigureNotify:
10225 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10226 if (f)
10227 {
10228 #ifndef USE_X_TOOLKIT
10229 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10230 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
10231
10232 /* In the toolkit version, change_frame_size
10233 is called by the code that handles resizing
10234 of the EmacsFrame widget. */
10235
10236 /* Even if the number of character rows and columns has
10237 not changed, the font size may have changed, so we need
10238 to check the pixel dimensions as well. */
10239 if (columns != f->width
10240 || rows != f->height
10241 || event.xconfigure.width != f->output_data.x->pixel_width
10242 || event.xconfigure.height != f->output_data.x->pixel_height)
10243 {
10244 change_frame_size (f, rows, columns, 0, 1, 0);
10245 SET_FRAME_GARBAGED (f);
10246 cancel_mouse_face (f);
10247 }
10248 #endif
10249
10250 f->output_data.x->pixel_width = event.xconfigure.width;
10251 f->output_data.x->pixel_height = event.xconfigure.height;
10252
10253 /* What we have now is the position of Emacs's own window.
10254 Convert that to the position of the window manager window. */
10255 x_real_positions (f, &f->output_data.x->left_pos,
10256 &f->output_data.x->top_pos);
10257
10258 #ifdef HAVE_X_I18N
10259 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10260 xic_set_statusarea (f);
10261 #endif
10262
10263 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10264 {
10265 /* Since the WM decorations come below top_pos now,
10266 we must put them below top_pos in the future. */
10267 f->output_data.x->win_gravity = NorthWestGravity;
10268 x_wm_set_size_hint (f, (long) 0, 0);
10269 }
10270 #ifdef USE_MOTIF
10271 /* Some window managers pass (0,0) as the location of
10272 the window, and the Motif event handler stores it
10273 in the emacs widget, which messes up Motif menus. */
10274 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10275 {
10276 event.xconfigure.x = f->output_data.x->widget->core.x;
10277 event.xconfigure.y = f->output_data.x->widget->core.y;
10278 }
10279 #endif /* USE_MOTIF */
10280 }
10281 goto OTHER;
10282
10283 case ButtonPress:
10284 case ButtonRelease:
10285 {
10286 /* If we decide we want to generate an event to be seen
10287 by the rest of Emacs, we put it here. */
10288 struct input_event emacs_event;
10289 int tool_bar_p = 0;
10290
10291 emacs_event.kind = no_event;
10292 bzero (&compose_status, sizeof (compose_status));
10293
10294 if (dpyinfo->grabbed
10295 && last_mouse_frame
10296 && FRAME_LIVE_P (last_mouse_frame))
10297 f = last_mouse_frame;
10298 else
10299 f = x_window_to_frame (dpyinfo, event.xbutton.window);
10300
10301 if (f)
10302 {
10303 /* Is this in the tool-bar? */
10304 if (WINDOWP (f->tool_bar_window)
10305 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
10306 {
10307 Lisp_Object window;
10308 int p, x, y;
10309
10310 x = event.xbutton.x;
10311 y = event.xbutton.y;
10312
10313 /* Set x and y. */
10314 window = window_from_coordinates (f, x, y, &p, 1);
10315 if (EQ (window, f->tool_bar_window))
10316 {
10317 x_handle_tool_bar_click (f, &event.xbutton);
10318 tool_bar_p = 1;
10319 }
10320 }
10321
10322 if (!tool_bar_p)
10323 if (!dpyinfo->x_focus_frame
10324 || f == dpyinfo->x_focus_frame)
10325 construct_mouse_click (&emacs_event, &event, f);
10326 }
10327 else
10328 {
10329 #ifndef USE_TOOLKIT_SCROLL_BARS
10330 struct scroll_bar *bar
10331 = x_window_to_scroll_bar (event.xbutton.window);
10332
10333 if (bar)
10334 x_scroll_bar_handle_click (bar, &event, &emacs_event);
10335 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10336 }
10337
10338 if (event.type == ButtonPress)
10339 {
10340 dpyinfo->grabbed |= (1 << event.xbutton.button);
10341 last_mouse_frame = f;
10342 /* Ignore any mouse motion that happened
10343 before this event; any subsequent mouse-movement
10344 Emacs events should reflect only motion after
10345 the ButtonPress. */
10346 if (f != 0)
10347 f->mouse_moved = 0;
10348
10349 if (!tool_bar_p)
10350 last_tool_bar_item = -1;
10351 }
10352 else
10353 {
10354 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
10355 }
10356
10357 if (numchars >= 1 && emacs_event.kind != no_event)
10358 {
10359 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10360 bufp++;
10361 count++;
10362 numchars--;
10363 }
10364
10365 #ifdef USE_X_TOOLKIT
10366 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10367 /* For a down-event in the menu bar,
10368 don't pass it to Xt right now.
10369 Instead, save it away
10370 and we will pass it to Xt from kbd_buffer_get_event.
10371 That way, we can run some Lisp code first. */
10372 if (f && event.type == ButtonPress
10373 /* Verify the event is really within the menu bar
10374 and not just sent to it due to grabbing. */
10375 && event.xbutton.x >= 0
10376 && event.xbutton.x < f->output_data.x->pixel_width
10377 && event.xbutton.y >= 0
10378 && event.xbutton.y < f->output_data.x->menubar_height
10379 && event.xbutton.same_screen)
10380 {
10381 SET_SAVED_BUTTON_EVENT;
10382 XSETFRAME (last_mouse_press_frame, f);
10383 }
10384 else if (event.type == ButtonPress)
10385 {
10386 last_mouse_press_frame = Qnil;
10387 goto OTHER;
10388 }
10389
10390 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10391 but I am trying to be cautious. */
10392 else if (event.type == ButtonRelease)
10393 {
10394 if (!NILP (last_mouse_press_frame))
10395 {
10396 f = XFRAME (last_mouse_press_frame);
10397 if (f->output_data.x)
10398 SET_SAVED_BUTTON_EVENT;
10399 }
10400 else
10401 goto OTHER;
10402 }
10403 #endif /* USE_MOTIF */
10404 else
10405 goto OTHER;
10406 #endif /* USE_X_TOOLKIT */
10407 }
10408 break;
10409
10410 case CirculateNotify:
10411 goto OTHER;
10412
10413 case CirculateRequest:
10414 goto OTHER;
10415
10416 case VisibilityNotify:
10417 goto OTHER;
10418
10419 case MappingNotify:
10420 /* Someone has changed the keyboard mapping - update the
10421 local cache. */
10422 switch (event.xmapping.request)
10423 {
10424 case MappingModifier:
10425 x_find_modifier_meanings (dpyinfo);
10426 /* This is meant to fall through. */
10427 case MappingKeyboard:
10428 XRefreshKeyboardMapping (&event.xmapping);
10429 }
10430 goto OTHER;
10431
10432 default:
10433 OTHER:
10434 #ifdef USE_X_TOOLKIT
10435 BLOCK_INPUT;
10436 XtDispatchEvent (&event);
10437 UNBLOCK_INPUT;
10438 #endif /* USE_X_TOOLKIT */
10439 break;
10440 }
10441 }
10442 }
10443
10444 out:;
10445
10446 /* On some systems, an X bug causes Emacs to get no more events
10447 when the window is destroyed. Detect that. (1994.) */
10448 if (! event_found)
10449 {
10450 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10451 One XNOOP in 100 loops will make Emacs terminate.
10452 B. Bretthauer, 1994 */
10453 x_noop_count++;
10454 if (x_noop_count >= 100)
10455 {
10456 x_noop_count=0;
10457
10458 if (next_noop_dpyinfo == 0)
10459 next_noop_dpyinfo = x_display_list;
10460
10461 XNoOp (next_noop_dpyinfo->display);
10462
10463 /* Each time we get here, cycle through the displays now open. */
10464 next_noop_dpyinfo = next_noop_dpyinfo->next;
10465 }
10466 }
10467
10468 /* If the focus was just given to an auto-raising frame,
10469 raise it now. */
10470 /* ??? This ought to be able to handle more than one such frame. */
10471 if (pending_autoraise_frame)
10472 {
10473 x_raise_frame (pending_autoraise_frame);
10474 pending_autoraise_frame = 0;
10475 }
10476
10477 UNBLOCK_INPUT;
10478 --handling_signal;
10479 return count;
10480 }
10481
10482
10483
10484 \f
10485 /***********************************************************************
10486 Text Cursor
10487 ***********************************************************************/
10488
10489 /* Note if the text cursor of window W has been overwritten by a
10490 drawing operation that outputs N glyphs starting at HPOS in the
10491 line given by output_cursor.vpos. N < 0 means all the rest of the
10492 line after HPOS has been written. */
10493
10494 static void
10495 note_overwritten_text_cursor (w, hpos, n)
10496 struct window *w;
10497 int hpos, n;
10498 {
10499 if (updated_area == TEXT_AREA
10500 && output_cursor.vpos == w->phys_cursor.vpos
10501 && hpos <= w->phys_cursor.hpos
10502 && (n < 0
10503 || hpos + n > w->phys_cursor.hpos))
10504 w->phys_cursor_on_p = 0;
10505 }
10506
10507
10508 /* Set clipping for output in glyph row ROW. W is the window in which
10509 we operate. GC is the graphics context to set clipping in.
10510 WHOLE_LINE_P non-zero means include the areas used for truncation
10511 mark display and alike in the clipping rectangle.
10512
10513 ROW may be a text row or, e.g., a mode line. Text rows must be
10514 clipped to the interior of the window dedicated to text display,
10515 mode lines must be clipped to the whole window. */
10516
10517 static void
10518 x_clip_to_row (w, row, gc, whole_line_p)
10519 struct window *w;
10520 struct glyph_row *row;
10521 GC gc;
10522 int whole_line_p;
10523 {
10524 struct frame *f = XFRAME (WINDOW_FRAME (w));
10525 XRectangle clip_rect;
10526 int window_x, window_y, window_width, window_height;
10527
10528 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10529
10530 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10531 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10532 clip_rect.y = max (clip_rect.y, window_y);
10533 clip_rect.width = window_width;
10534 clip_rect.height = row->visible_height;
10535
10536 /* If clipping to the whole line, including trunc marks, extend
10537 the rectangle to the left and increase its width. */
10538 if (whole_line_p)
10539 {
10540 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10541 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10542 }
10543
10544 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10545 }
10546
10547
10548 /* Draw a hollow box cursor on window W in glyph row ROW. */
10549
10550 static void
10551 x_draw_hollow_cursor (w, row)
10552 struct window *w;
10553 struct glyph_row *row;
10554 {
10555 struct frame *f = XFRAME (WINDOW_FRAME (w));
10556 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10557 Display *dpy = FRAME_X_DISPLAY (f);
10558 int x, y, wd, h;
10559 XGCValues xgcv;
10560 struct glyph *cursor_glyph;
10561 GC gc;
10562
10563 /* Compute frame-relative coordinates from window-relative
10564 coordinates. */
10565 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10566 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10567 + row->ascent - w->phys_cursor_ascent);
10568 h = row->height - 1;
10569
10570 /* Get the glyph the cursor is on. If we can't tell because
10571 the current matrix is invalid or such, give up. */
10572 cursor_glyph = get_phys_cursor_glyph (w);
10573 if (cursor_glyph == NULL)
10574 return;
10575
10576 /* Compute the width of the rectangle to draw. If on a stretch
10577 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10578 rectangle as wide as the glyph, but use a canonical character
10579 width instead. */
10580 wd = cursor_glyph->pixel_width - 1;
10581 if (cursor_glyph->type == STRETCH_GLYPH
10582 && !x_stretch_cursor_p)
10583 wd = min (CANON_X_UNIT (f), wd);
10584
10585 /* The foreground of cursor_gc is typically the same as the normal
10586 background color, which can cause the cursor box to be invisible. */
10587 xgcv.foreground = f->output_data.x->cursor_pixel;
10588 if (dpyinfo->scratch_cursor_gc)
10589 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10590 else
10591 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10592 GCForeground, &xgcv);
10593 gc = dpyinfo->scratch_cursor_gc;
10594
10595 /* Set clipping, draw the rectangle, and reset clipping again. */
10596 x_clip_to_row (w, row, gc, 0);
10597 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10598 XSetClipMask (dpy, gc, None);
10599 }
10600
10601
10602 /* Draw a bar cursor on window W in glyph row ROW.
10603
10604 Implementation note: One would like to draw a bar cursor with an
10605 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10606 Unfortunately, I didn't find a font yet that has this property set.
10607 --gerd. */
10608
10609 static void
10610 x_draw_bar_cursor (w, row, width)
10611 struct window *w;
10612 struct glyph_row *row;
10613 int width;
10614 {
10615 struct frame *f = XFRAME (w->frame);
10616 struct glyph *cursor_glyph;
10617 GC gc;
10618 int x;
10619 unsigned long mask;
10620 XGCValues xgcv;
10621 Display *dpy;
10622 Window window;
10623
10624 /* If cursor is out of bounds, don't draw garbage. This can happen
10625 in mini-buffer windows when switching between echo area glyphs
10626 and mini-buffer. */
10627 cursor_glyph = get_phys_cursor_glyph (w);
10628 if (cursor_glyph == NULL)
10629 return;
10630
10631 /* If on an image, draw like a normal cursor. That's usually better
10632 visible than drawing a bar, esp. if the image is large so that
10633 the bar might not be in the window. */
10634 if (cursor_glyph->type == IMAGE_GLYPH)
10635 {
10636 struct glyph_row *row;
10637 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10638 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10639 }
10640 else
10641 {
10642 xgcv.background = f->output_data.x->cursor_pixel;
10643 xgcv.foreground = f->output_data.x->cursor_pixel;
10644 xgcv.graphics_exposures = 0;
10645 mask = GCForeground | GCBackground | GCGraphicsExposures;
10646 dpy = FRAME_X_DISPLAY (f);
10647 window = FRAME_X_WINDOW (f);
10648 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10649
10650 if (gc)
10651 XChangeGC (dpy, gc, mask, &xgcv);
10652 else
10653 {
10654 gc = XCreateGC (dpy, window, mask, &xgcv);
10655 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10656 }
10657
10658 if (width < 0)
10659 width = f->output_data.x->cursor_width;
10660
10661 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10662 x_clip_to_row (w, row, gc, 0);
10663 XFillRectangle (dpy, window, gc,
10664 x,
10665 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10666 min (cursor_glyph->pixel_width, width),
10667 row->height);
10668 XSetClipMask (dpy, gc, None);
10669 }
10670 }
10671
10672
10673 /* Clear the cursor of window W to background color, and mark the
10674 cursor as not shown. This is used when the text where the cursor
10675 is is about to be rewritten. */
10676
10677 static void
10678 x_clear_cursor (w)
10679 struct window *w;
10680 {
10681 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10682 x_update_window_cursor (w, 0);
10683 }
10684
10685
10686 /* Draw the cursor glyph of window W in glyph row ROW. See the
10687 comment of x_draw_glyphs for the meaning of HL. */
10688
10689 static void
10690 x_draw_phys_cursor_glyph (w, row, hl)
10691 struct window *w;
10692 struct glyph_row *row;
10693 enum draw_glyphs_face hl;
10694 {
10695 /* If cursor hpos is out of bounds, don't draw garbage. This can
10696 happen in mini-buffer windows when switching between echo area
10697 glyphs and mini-buffer. */
10698 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10699 {
10700 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10701 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10702 hl, 0, 0, 0);
10703
10704 /* When we erase the cursor, and ROW is overlapped by other
10705 rows, make sure that these overlapping parts of other rows
10706 are redrawn. */
10707 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10708 {
10709 if (row > w->current_matrix->rows
10710 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10711 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10712
10713 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10714 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10715 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10716 }
10717 }
10718 }
10719
10720
10721 /* Erase the image of a cursor of window W from the screen. */
10722
10723 static void
10724 x_erase_phys_cursor (w)
10725 struct window *w;
10726 {
10727 struct frame *f = XFRAME (w->frame);
10728 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10729 int hpos = w->phys_cursor.hpos;
10730 int vpos = w->phys_cursor.vpos;
10731 int mouse_face_here_p = 0;
10732 struct glyph_matrix *active_glyphs = w->current_matrix;
10733 struct glyph_row *cursor_row;
10734 struct glyph *cursor_glyph;
10735 enum draw_glyphs_face hl;
10736
10737 /* No cursor displayed or row invalidated => nothing to do on the
10738 screen. */
10739 if (w->phys_cursor_type == NO_CURSOR)
10740 goto mark_cursor_off;
10741
10742 /* VPOS >= active_glyphs->nrows means that window has been resized.
10743 Don't bother to erase the cursor. */
10744 if (vpos >= active_glyphs->nrows)
10745 goto mark_cursor_off;
10746
10747 /* If row containing cursor is marked invalid, there is nothing we
10748 can do. */
10749 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10750 if (!cursor_row->enabled_p)
10751 goto mark_cursor_off;
10752
10753 /* This can happen when the new row is shorter than the old one.
10754 In this case, either x_draw_glyphs or clear_end_of_line
10755 should have cleared the cursor. Note that we wouldn't be
10756 able to erase the cursor in this case because we don't have a
10757 cursor glyph at hand. */
10758 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10759 goto mark_cursor_off;
10760
10761 /* If the cursor is in the mouse face area, redisplay that when
10762 we clear the cursor. */
10763 if (! NILP (dpyinfo->mouse_face_window)
10764 && w == XWINDOW (dpyinfo->mouse_face_window)
10765 && (vpos > dpyinfo->mouse_face_beg_row
10766 || (vpos == dpyinfo->mouse_face_beg_row
10767 && hpos >= dpyinfo->mouse_face_beg_col))
10768 && (vpos < dpyinfo->mouse_face_end_row
10769 || (vpos == dpyinfo->mouse_face_end_row
10770 && hpos < dpyinfo->mouse_face_end_col))
10771 /* Don't redraw the cursor's spot in mouse face if it is at the
10772 end of a line (on a newline). The cursor appears there, but
10773 mouse highlighting does not. */
10774 && cursor_row->used[TEXT_AREA] > hpos)
10775 mouse_face_here_p = 1;
10776
10777 /* Maybe clear the display under the cursor. */
10778 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10779 {
10780 int x;
10781 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10782
10783 cursor_glyph = get_phys_cursor_glyph (w);
10784 if (cursor_glyph == NULL)
10785 goto mark_cursor_off;
10786
10787 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10788
10789 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10790 x,
10791 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10792 cursor_row->y)),
10793 cursor_glyph->pixel_width,
10794 cursor_row->visible_height,
10795 False);
10796 }
10797
10798 /* Erase the cursor by redrawing the character underneath it. */
10799 if (mouse_face_here_p)
10800 hl = DRAW_MOUSE_FACE;
10801 else if (cursor_row->inverse_p)
10802 hl = DRAW_INVERSE_VIDEO;
10803 else
10804 hl = DRAW_NORMAL_TEXT;
10805 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10806
10807 mark_cursor_off:
10808 w->phys_cursor_on_p = 0;
10809 w->phys_cursor_type = NO_CURSOR;
10810 }
10811
10812
10813 /* Display or clear cursor of window W. If ON is zero, clear the
10814 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10815 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10816
10817 void
10818 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10819 struct window *w;
10820 int on, hpos, vpos, x, y;
10821 {
10822 struct frame *f = XFRAME (w->frame);
10823 int new_cursor_type;
10824 int new_cursor_width;
10825 struct glyph_matrix *current_glyphs;
10826 struct glyph_row *glyph_row;
10827 struct glyph *glyph;
10828
10829 /* This is pointless on invisible frames, and dangerous on garbaged
10830 windows and frames; in the latter case, the frame or window may
10831 be in the midst of changing its size, and x and y may be off the
10832 window. */
10833 if (! FRAME_VISIBLE_P (f)
10834 || FRAME_GARBAGED_P (f)
10835 || vpos >= w->current_matrix->nrows
10836 || hpos >= w->current_matrix->matrix_w)
10837 return;
10838
10839 /* If cursor is off and we want it off, return quickly. */
10840 if (!on && !w->phys_cursor_on_p)
10841 return;
10842
10843 current_glyphs = w->current_matrix;
10844 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10845 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10846
10847 /* If cursor row is not enabled, we don't really know where to
10848 display the cursor. */
10849 if (!glyph_row->enabled_p)
10850 {
10851 w->phys_cursor_on_p = 0;
10852 return;
10853 }
10854
10855 xassert (interrupt_input_blocked);
10856
10857 /* Set new_cursor_type to the cursor we want to be displayed. In a
10858 mini-buffer window, we want the cursor only to appear if we are
10859 reading input from this window. For the selected window, we want
10860 the cursor type given by the frame parameter. If explicitly
10861 marked off, draw no cursor. In all other cases, we want a hollow
10862 box cursor. */
10863 new_cursor_width = -1;
10864 if (cursor_in_echo_area
10865 && FRAME_HAS_MINIBUF_P (f)
10866 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10867 {
10868 if (w == XWINDOW (echo_area_window))
10869 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10870 else
10871 new_cursor_type = HOLLOW_BOX_CURSOR;
10872 }
10873 else
10874 {
10875 if (w != XWINDOW (selected_window)
10876 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10877 {
10878 extern int cursor_in_non_selected_windows;
10879
10880 if (MINI_WINDOW_P (w)
10881 || !cursor_in_non_selected_windows
10882 || NILP (XBUFFER (w->buffer)->cursor_type))
10883 new_cursor_type = NO_CURSOR;
10884 else
10885 new_cursor_type = HOLLOW_BOX_CURSOR;
10886 }
10887 else if (w->cursor_off_p)
10888 new_cursor_type = NO_CURSOR;
10889 else
10890 {
10891 struct buffer *b = XBUFFER (w->buffer);
10892
10893 if (EQ (b->cursor_type, Qt))
10894 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10895 else
10896 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10897 &new_cursor_width);
10898 }
10899 }
10900
10901 /* If cursor is currently being shown and we don't want it to be or
10902 it is in the wrong place, or the cursor type is not what we want,
10903 erase it. */
10904 if (w->phys_cursor_on_p
10905 && (!on
10906 || w->phys_cursor.x != x
10907 || w->phys_cursor.y != y
10908 || new_cursor_type != w->phys_cursor_type))
10909 x_erase_phys_cursor (w);
10910
10911 /* If the cursor is now invisible and we want it to be visible,
10912 display it. */
10913 if (on && !w->phys_cursor_on_p)
10914 {
10915 w->phys_cursor_ascent = glyph_row->ascent;
10916 w->phys_cursor_height = glyph_row->height;
10917
10918 /* Set phys_cursor_.* before x_draw_.* is called because some
10919 of them may need the information. */
10920 w->phys_cursor.x = x;
10921 w->phys_cursor.y = glyph_row->y;
10922 w->phys_cursor.hpos = hpos;
10923 w->phys_cursor.vpos = vpos;
10924 w->phys_cursor_type = new_cursor_type;
10925 w->phys_cursor_on_p = 1;
10926
10927 switch (new_cursor_type)
10928 {
10929 case HOLLOW_BOX_CURSOR:
10930 x_draw_hollow_cursor (w, glyph_row);
10931 break;
10932
10933 case FILLED_BOX_CURSOR:
10934 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10935 break;
10936
10937 case BAR_CURSOR:
10938 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
10939 break;
10940
10941 case NO_CURSOR:
10942 break;
10943
10944 default:
10945 abort ();
10946 }
10947
10948 #ifdef HAVE_X_I18N
10949 if (w == XWINDOW (f->selected_window))
10950 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10951 xic_set_preeditarea (w, x, y);
10952 #endif
10953 }
10954
10955 #ifndef XFlush
10956 if (updating_frame != f)
10957 XFlush (FRAME_X_DISPLAY (f));
10958 #endif
10959 }
10960
10961
10962 /* Display the cursor on window W, or clear it. X and Y are window
10963 relative pixel coordinates. HPOS and VPOS are glyph matrix
10964 positions. If W is not the selected window, display a hollow
10965 cursor. ON non-zero means display the cursor at X, Y which
10966 correspond to HPOS, VPOS, otherwise it is cleared. */
10967
10968 void
10969 x_display_cursor (w, on, hpos, vpos, x, y)
10970 struct window *w;
10971 int on, hpos, vpos, x, y;
10972 {
10973 BLOCK_INPUT;
10974 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10975 UNBLOCK_INPUT;
10976 }
10977
10978
10979 /* Display the cursor on window W, or clear it, according to ON_P.
10980 Don't change the cursor's position. */
10981
10982 void
10983 x_update_cursor (f, on_p)
10984 struct frame *f;
10985 {
10986 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10987 }
10988
10989
10990 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10991 in the window tree rooted at W. */
10992
10993 static void
10994 x_update_cursor_in_window_tree (w, on_p)
10995 struct window *w;
10996 int on_p;
10997 {
10998 while (w)
10999 {
11000 if (!NILP (w->hchild))
11001 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11002 else if (!NILP (w->vchild))
11003 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11004 else
11005 x_update_window_cursor (w, on_p);
11006
11007 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11008 }
11009 }
11010
11011
11012 /* Switch the display of W's cursor on or off, according to the value
11013 of ON. */
11014
11015 static void
11016 x_update_window_cursor (w, on)
11017 struct window *w;
11018 int on;
11019 {
11020 /* Don't update cursor in windows whose frame is in the process
11021 of being deleted. */
11022 if (w->current_matrix)
11023 {
11024 BLOCK_INPUT;
11025 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11026 w->phys_cursor.x, w->phys_cursor.y);
11027 UNBLOCK_INPUT;
11028 }
11029 }
11030
11031
11032
11033 \f
11034 /* Icons. */
11035
11036 /* Refresh bitmap kitchen sink icon for frame F
11037 when we get an expose event for it. */
11038
11039 void
11040 refreshicon (f)
11041 struct frame *f;
11042 {
11043 /* Normally, the window manager handles this function. */
11044 }
11045
11046 /* Make the x-window of frame F use the gnu icon bitmap. */
11047
11048 int
11049 x_bitmap_icon (f, file)
11050 struct frame *f;
11051 Lisp_Object file;
11052 {
11053 int bitmap_id;
11054
11055 if (FRAME_X_WINDOW (f) == 0)
11056 return 1;
11057
11058 /* Free up our existing icon bitmap if any. */
11059 if (f->output_data.x->icon_bitmap > 0)
11060 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11061 f->output_data.x->icon_bitmap = 0;
11062
11063 if (STRINGP (file))
11064 bitmap_id = x_create_bitmap_from_file (f, file);
11065 else
11066 {
11067 /* Create the GNU bitmap if necessary. */
11068 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
11069 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11070 = x_create_bitmap_from_data (f, gnu_bits,
11071 gnu_width, gnu_height);
11072
11073 /* The first time we create the GNU bitmap,
11074 this increments the ref-count one extra time.
11075 As a result, the GNU bitmap is never freed.
11076 That way, we don't have to worry about allocating it again. */
11077 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
11078
11079 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
11080 }
11081
11082 x_wm_set_icon_pixmap (f, bitmap_id);
11083 f->output_data.x->icon_bitmap = bitmap_id;
11084
11085 return 0;
11086 }
11087
11088
11089 /* Make the x-window of frame F use a rectangle with text.
11090 Use ICON_NAME as the text. */
11091
11092 int
11093 x_text_icon (f, icon_name)
11094 struct frame *f;
11095 char *icon_name;
11096 {
11097 if (FRAME_X_WINDOW (f) == 0)
11098 return 1;
11099
11100 #ifdef HAVE_X11R4
11101 {
11102 XTextProperty text;
11103 text.value = (unsigned char *) icon_name;
11104 text.encoding = XA_STRING;
11105 text.format = 8;
11106 text.nitems = strlen (icon_name);
11107 #ifdef USE_X_TOOLKIT
11108 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11109 &text);
11110 #else /* not USE_X_TOOLKIT */
11111 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11112 #endif /* not USE_X_TOOLKIT */
11113 }
11114 #else /* not HAVE_X11R4 */
11115 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11116 #endif /* not HAVE_X11R4 */
11117
11118 if (f->output_data.x->icon_bitmap > 0)
11119 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11120 f->output_data.x->icon_bitmap = 0;
11121 x_wm_set_icon_pixmap (f, 0);
11122
11123 return 0;
11124 }
11125 \f
11126 #define X_ERROR_MESSAGE_SIZE 200
11127
11128 /* If non-nil, this should be a string.
11129 It means catch X errors and store the error message in this string. */
11130
11131 static Lisp_Object x_error_message_string;
11132
11133 /* An X error handler which stores the error message in
11134 x_error_message_string. This is called from x_error_handler if
11135 x_catch_errors is in effect. */
11136
11137 static void
11138 x_error_catcher (display, error)
11139 Display *display;
11140 XErrorEvent *error;
11141 {
11142 XGetErrorText (display, error->error_code,
11143 XSTRING (x_error_message_string)->data,
11144 X_ERROR_MESSAGE_SIZE);
11145 }
11146
11147 /* Begin trapping X errors for display DPY. Actually we trap X errors
11148 for all displays, but DPY should be the display you are actually
11149 operating on.
11150
11151 After calling this function, X protocol errors no longer cause
11152 Emacs to exit; instead, they are recorded in the string
11153 stored in x_error_message_string.
11154
11155 Calling x_check_errors signals an Emacs error if an X error has
11156 occurred since the last call to x_catch_errors or x_check_errors.
11157
11158 Calling x_uncatch_errors resumes the normal error handling. */
11159
11160 void x_check_errors ();
11161 static Lisp_Object x_catch_errors_unwind ();
11162
11163 int
11164 x_catch_errors (dpy)
11165 Display *dpy;
11166 {
11167 int count = specpdl_ptr - specpdl;
11168
11169 /* Make sure any errors from previous requests have been dealt with. */
11170 XSync (dpy, False);
11171
11172 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11173
11174 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11175 XSTRING (x_error_message_string)->data[0] = 0;
11176
11177 return count;
11178 }
11179
11180 /* Unbind the binding that we made to check for X errors. */
11181
11182 static Lisp_Object
11183 x_catch_errors_unwind (old_val)
11184 Lisp_Object old_val;
11185 {
11186 x_error_message_string = old_val;
11187 return Qnil;
11188 }
11189
11190 /* If any X protocol errors have arrived since the last call to
11191 x_catch_errors or x_check_errors, signal an Emacs error using
11192 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11193
11194 void
11195 x_check_errors (dpy, format)
11196 Display *dpy;
11197 char *format;
11198 {
11199 /* Make sure to catch any errors incurred so far. */
11200 XSync (dpy, False);
11201
11202 if (XSTRING (x_error_message_string)->data[0])
11203 error (format, XSTRING (x_error_message_string)->data);
11204 }
11205
11206 /* Nonzero if we had any X protocol errors
11207 since we did x_catch_errors on DPY. */
11208
11209 int
11210 x_had_errors_p (dpy)
11211 Display *dpy;
11212 {
11213 /* Make sure to catch any errors incurred so far. */
11214 XSync (dpy, False);
11215
11216 return XSTRING (x_error_message_string)->data[0] != 0;
11217 }
11218
11219 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11220
11221 void
11222 x_clear_errors (dpy)
11223 Display *dpy;
11224 {
11225 XSTRING (x_error_message_string)->data[0] = 0;
11226 }
11227
11228 /* Stop catching X protocol errors and let them make Emacs die.
11229 DPY should be the display that was passed to x_catch_errors.
11230 COUNT should be the value that was returned by
11231 the corresponding call to x_catch_errors. */
11232
11233 void
11234 x_uncatch_errors (dpy, count)
11235 Display *dpy;
11236 int count;
11237 {
11238 unbind_to (count, Qnil);
11239 }
11240
11241 #if 0
11242 static unsigned int x_wire_count;
11243 x_trace_wire ()
11244 {
11245 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11246 }
11247 #endif /* ! 0 */
11248
11249 \f
11250 /* Handle SIGPIPE, which can happen when the connection to a server
11251 simply goes away. SIGPIPE is handled by x_connection_signal.
11252 Don't need to do anything, because the write which caused the
11253 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
11254 which will do the appropriate cleanup for us. */
11255
11256 static SIGTYPE
11257 x_connection_signal (signalnum) /* If we don't have an argument, */
11258 int signalnum; /* some compilers complain in signal calls. */
11259 {
11260 #ifdef USG
11261 /* USG systems forget handlers when they are used;
11262 must reestablish each time */
11263 signal (signalnum, x_connection_signal);
11264 #endif /* USG */
11265 }
11266 \f
11267 /* Handling X errors. */
11268
11269 /* Handle the loss of connection to display DISPLAY. */
11270
11271 static SIGTYPE
11272 x_connection_closed (display, error_message)
11273 Display *display;
11274 char *error_message;
11275 {
11276 struct x_display_info *dpyinfo = x_display_info_for_display (display);
11277 Lisp_Object frame, tail;
11278
11279 /* Indicate that this display is dead. */
11280
11281 #if 0 /* Closing the display caused a bus error on OpenWindows. */
11282 #ifdef USE_X_TOOLKIT
11283 XtCloseDisplay (display);
11284 #endif
11285 #endif
11286
11287 if (dpyinfo)
11288 dpyinfo->display = 0;
11289
11290 /* First delete frames whose mini-buffers are on frames
11291 that are on the dead display. */
11292 FOR_EACH_FRAME (tail, frame)
11293 {
11294 Lisp_Object minibuf_frame;
11295 minibuf_frame
11296 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
11297 if (FRAME_X_P (XFRAME (frame))
11298 && FRAME_X_P (XFRAME (minibuf_frame))
11299 && ! EQ (frame, minibuf_frame)
11300 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
11301 Fdelete_frame (frame, Qt);
11302 }
11303
11304 /* Now delete all remaining frames on the dead display.
11305 We are now sure none of these is used as the mini-buffer
11306 for another frame that we need to delete. */
11307 FOR_EACH_FRAME (tail, frame)
11308 if (FRAME_X_P (XFRAME (frame))
11309 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
11310 {
11311 /* Set this to t so that Fdelete_frame won't get confused
11312 trying to find a replacement. */
11313 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11314 Fdelete_frame (frame, Qt);
11315 }
11316
11317 if (dpyinfo)
11318 x_delete_display (dpyinfo);
11319
11320 if (x_display_list == 0)
11321 {
11322 fprintf (stderr, "%s\n", error_message);
11323 shut_down_emacs (0, 0, Qnil);
11324 exit (70);
11325 }
11326
11327 /* Ordinary stack unwind doesn't deal with these. */
11328 #ifdef SIGIO
11329 sigunblock (sigmask (SIGIO));
11330 #endif
11331 sigunblock (sigmask (SIGALRM));
11332 TOTALLY_UNBLOCK_INPUT;
11333
11334 clear_waiting_for_input ();
11335 handling_signal = 0;
11336 error ("%s", error_message);
11337 }
11338
11339 /* This is the usual handler for X protocol errors.
11340 It kills all frames on the display that we got the error for.
11341 If that was the only one, it prints an error message and kills Emacs. */
11342
11343 static void
11344 x_error_quitter (display, error)
11345 Display *display;
11346 XErrorEvent *error;
11347 {
11348 char buf[256], buf1[356];
11349
11350 /* Note that there is no real way portable across R3/R4 to get the
11351 original error handler. */
11352
11353 XGetErrorText (display, error->error_code, buf, sizeof (buf));
11354 sprintf (buf1, "X protocol error: %s on protocol request %d",
11355 buf, error->request_code);
11356 x_connection_closed (display, buf1);
11357 }
11358
11359 /* This is the first-level handler for X protocol errors.
11360 It calls x_error_quitter or x_error_catcher. */
11361
11362 static int
11363 x_error_handler (display, error)
11364 Display *display;
11365 XErrorEvent *error;
11366 {
11367 if (! NILP (x_error_message_string))
11368 x_error_catcher (display, error);
11369 else
11370 x_error_quitter (display, error);
11371 return 0;
11372 }
11373
11374 /* This is the handler for X IO errors, always.
11375 It kills all frames on the display that we lost touch with.
11376 If that was the only one, it prints an error message and kills Emacs. */
11377
11378 static int
11379 x_io_error_quitter (display)
11380 Display *display;
11381 {
11382 char buf[256];
11383
11384 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11385 x_connection_closed (display, buf);
11386 return 0;
11387 }
11388 \f
11389 /* Changing the font of the frame. */
11390
11391 /* Give frame F the font named FONTNAME as its default font, and
11392 return the full name of that font. FONTNAME may be a wildcard
11393 pattern; in that case, we choose some font that fits the pattern.
11394 The return value shows which font we chose. */
11395
11396 Lisp_Object
11397 x_new_font (f, fontname)
11398 struct frame *f;
11399 register char *fontname;
11400 {
11401 struct font_info *fontp
11402 = FS_LOAD_FONT (f, 0, fontname, -1);
11403
11404 if (!fontp)
11405 return Qnil;
11406
11407 f->output_data.x->font = (XFontStruct *) (fontp->font);
11408 f->output_data.x->baseline_offset = fontp->baseline_offset;
11409 f->output_data.x->fontset = -1;
11410
11411 /* Compute the scroll bar width in character columns. */
11412 if (f->scroll_bar_pixel_width > 0)
11413 {
11414 int wid = FONT_WIDTH (f->output_data.x->font);
11415 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11416 }
11417 else
11418 {
11419 int wid = FONT_WIDTH (f->output_data.x->font);
11420 f->scroll_bar_cols = (14 + wid - 1) / wid;
11421 }
11422
11423 /* Now make the frame display the given font. */
11424 if (FRAME_X_WINDOW (f) != 0)
11425 {
11426 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11427 f->output_data.x->font->fid);
11428 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11429 f->output_data.x->font->fid);
11430 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11431 f->output_data.x->font->fid);
11432
11433 frame_update_line_height (f);
11434 x_set_window_size (f, 0, f->width, f->height);
11435 }
11436 else
11437 /* If we are setting a new frame's font for the first time,
11438 there are no faces yet, so this font's height is the line height. */
11439 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11440
11441 return build_string (fontp->full_name);
11442 }
11443
11444 /* Give frame F the fontset named FONTSETNAME as its default font, and
11445 return the full name of that fontset. FONTSETNAME may be a wildcard
11446 pattern; in that case, we choose some fontset that fits the pattern.
11447 The return value shows which fontset we chose. */
11448
11449 Lisp_Object
11450 x_new_fontset (f, fontsetname)
11451 struct frame *f;
11452 char *fontsetname;
11453 {
11454 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11455 Lisp_Object result;
11456
11457 if (fontset < 0)
11458 return Qnil;
11459
11460 if (f->output_data.x->fontset == fontset)
11461 /* This fontset is already set in frame F. There's nothing more
11462 to do. */
11463 return fontset_name (fontset);
11464
11465 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11466
11467 if (!STRINGP (result))
11468 /* Can't load ASCII font. */
11469 return Qnil;
11470
11471 /* Since x_new_font doesn't update any fontset information, do it now. */
11472 f->output_data.x->fontset = fontset;
11473
11474 #ifdef HAVE_X_I18N
11475 if (FRAME_XIC (f)
11476 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11477 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11478 #endif
11479
11480 return build_string (fontsetname);
11481 }
11482
11483 \f
11484 /***********************************************************************
11485 X Input Methods
11486 ***********************************************************************/
11487
11488 #ifdef HAVE_X_I18N
11489
11490 #ifdef HAVE_X11R6
11491
11492 /* XIM destroy callback function, which is called whenever the
11493 connection to input method XIM dies. CLIENT_DATA contains a
11494 pointer to the x_display_info structure corresponding to XIM. */
11495
11496 static void
11497 xim_destroy_callback (xim, client_data, call_data)
11498 XIM xim;
11499 XPointer client_data;
11500 XPointer call_data;
11501 {
11502 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11503 Lisp_Object frame, tail;
11504
11505 BLOCK_INPUT;
11506
11507 /* No need to call XDestroyIC.. */
11508 FOR_EACH_FRAME (tail, frame)
11509 {
11510 struct frame *f = XFRAME (frame);
11511 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11512 {
11513 FRAME_XIC (f) = NULL;
11514 if (FRAME_XIC_FONTSET (f))
11515 {
11516 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11517 FRAME_XIC_FONTSET (f) = NULL;
11518 }
11519 }
11520 }
11521
11522 /* No need to call XCloseIM. */
11523 dpyinfo->xim = NULL;
11524 XFree (dpyinfo->xim_styles);
11525 UNBLOCK_INPUT;
11526 }
11527
11528 #endif /* HAVE_X11R6 */
11529
11530 /* Open the connection to the XIM server on display DPYINFO.
11531 RESOURCE_NAME is the resource name Emacs uses. */
11532
11533 static void
11534 xim_open_dpy (dpyinfo, resource_name)
11535 struct x_display_info *dpyinfo;
11536 char *resource_name;
11537 {
11538 #ifdef USE_XIM
11539 XIM xim;
11540
11541 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11542 dpyinfo->xim = xim;
11543
11544 if (xim)
11545 {
11546 #ifdef HAVE_X11R6
11547 XIMCallback destroy;
11548 #endif
11549
11550 /* Get supported styles and XIM values. */
11551 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11552
11553 #ifdef HAVE_X11R6
11554 destroy.callback = xim_destroy_callback;
11555 destroy.client_data = (XPointer)dpyinfo;
11556 /* This isn't prptotyped in OSF 5.0. */
11557 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11558 #endif
11559 }
11560
11561 #else /* not USE_XIM */
11562 dpyinfo->xim = NULL;
11563 #endif /* not USE_XIM */
11564 }
11565
11566
11567 #ifdef HAVE_X11R6_XIM
11568
11569 struct xim_inst_t
11570 {
11571 struct x_display_info *dpyinfo;
11572 char *resource_name;
11573 };
11574
11575 /* XIM instantiate callback function, which is called whenever an XIM
11576 server is available. DISPLAY is teh display of the XIM.
11577 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11578 when the callback was registered. */
11579
11580 static void
11581 xim_instantiate_callback (display, client_data, call_data)
11582 Display *display;
11583 XPointer client_data;
11584 XPointer call_data;
11585 {
11586 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11587 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11588
11589 /* We don't support multiple XIM connections. */
11590 if (dpyinfo->xim)
11591 return;
11592
11593 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11594
11595 /* Create XIC for the existing frames on the same display, as long
11596 as they have no XIC. */
11597 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11598 {
11599 Lisp_Object tail, frame;
11600
11601 BLOCK_INPUT;
11602 FOR_EACH_FRAME (tail, frame)
11603 {
11604 struct frame *f = XFRAME (frame);
11605
11606 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11607 if (FRAME_XIC (f) == NULL)
11608 {
11609 create_frame_xic (f);
11610 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11611 xic_set_statusarea (f);
11612 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11613 {
11614 struct window *w = XWINDOW (f->selected_window);
11615 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11616 }
11617 }
11618 }
11619
11620 UNBLOCK_INPUT;
11621 }
11622 }
11623
11624 #endif /* HAVE_X11R6_XIM */
11625
11626
11627 /* Open a connection to the XIM server on display DPYINFO.
11628 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11629 connection only at the first time. On X11R6, open the connection
11630 in the XIM instantiate callback function. */
11631
11632 static void
11633 xim_initialize (dpyinfo, resource_name)
11634 struct x_display_info *dpyinfo;
11635 char *resource_name;
11636 {
11637 #ifdef USE_XIM
11638 #ifdef HAVE_X11R6_XIM
11639 struct xim_inst_t *xim_inst;
11640 int len;
11641
11642 dpyinfo->xim = NULL;
11643 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11644 xim_inst->dpyinfo = dpyinfo;
11645 len = strlen (resource_name);
11646 xim_inst->resource_name = (char *) xmalloc (len + 1);
11647 bcopy (resource_name, xim_inst->resource_name, len + 1);
11648 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11649 resource_name, EMACS_CLASS,
11650 xim_instantiate_callback,
11651 /* Fixme: This is XPointer in
11652 XFree86 but (XPointer *) on
11653 Tru64, at least. */
11654 (XPointer) xim_inst);
11655 #else /* not HAVE_X11R6_XIM */
11656 dpyinfo->xim = NULL;
11657 xim_open_dpy (dpyinfo, resource_name);
11658 #endif /* not HAVE_X11R6_XIM */
11659
11660 #else /* not USE_XIM */
11661 dpyinfo->xim = NULL;
11662 #endif /* not USE_XIM */
11663 }
11664
11665
11666 /* Close the connection to the XIM server on display DPYINFO. */
11667
11668 static void
11669 xim_close_dpy (dpyinfo)
11670 struct x_display_info *dpyinfo;
11671 {
11672 #ifdef USE_XIM
11673 #ifdef HAVE_X11R6_XIM
11674 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11675 NULL, EMACS_CLASS,
11676 xim_instantiate_callback, NULL);
11677 #endif /* not HAVE_X11R6_XIM */
11678 XCloseIM (dpyinfo->xim);
11679 dpyinfo->xim = NULL;
11680 XFree (dpyinfo->xim_styles);
11681 #endif /* USE_XIM */
11682 }
11683
11684 #endif /* not HAVE_X11R6_XIM */
11685
11686
11687 \f
11688 /* Calculate the absolute position in frame F
11689 from its current recorded position values and gravity. */
11690
11691 void
11692 x_calc_absolute_position (f)
11693 struct frame *f;
11694 {
11695 Window child;
11696 int win_x = 0, win_y = 0;
11697 int flags = f->output_data.x->size_hint_flags;
11698 int this_window;
11699
11700 /* We have nothing to do if the current position
11701 is already for the top-left corner. */
11702 if (! ((flags & XNegative) || (flags & YNegative)))
11703 return;
11704
11705 #ifdef USE_X_TOOLKIT
11706 this_window = XtWindow (f->output_data.x->widget);
11707 #else
11708 this_window = FRAME_X_WINDOW (f);
11709 #endif
11710
11711 /* Find the position of the outside upper-left corner of
11712 the inner window, with respect to the outer window.
11713 But do this only if we will need the results. */
11714 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11715 {
11716 int count;
11717
11718 BLOCK_INPUT;
11719 count = x_catch_errors (FRAME_X_DISPLAY (f));
11720 while (1)
11721 {
11722 x_clear_errors (FRAME_X_DISPLAY (f));
11723 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11724
11725 /* From-window, to-window. */
11726 this_window,
11727 f->output_data.x->parent_desc,
11728
11729 /* From-position, to-position. */
11730 0, 0, &win_x, &win_y,
11731
11732 /* Child of win. */
11733 &child);
11734 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11735 {
11736 Window newroot, newparent = 0xdeadbeef;
11737 Window *newchildren;
11738 unsigned int nchildren;
11739
11740 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11741 &newparent, &newchildren, &nchildren))
11742 break;
11743
11744 XFree ((char *) newchildren);
11745
11746 f->output_data.x->parent_desc = newparent;
11747 }
11748 else
11749 break;
11750 }
11751
11752 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11753 UNBLOCK_INPUT;
11754 }
11755
11756 /* Treat negative positions as relative to the leftmost bottommost
11757 position that fits on the screen. */
11758 if (flags & XNegative)
11759 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11760 - 2 * f->output_data.x->border_width - win_x
11761 - PIXEL_WIDTH (f)
11762 + f->output_data.x->left_pos);
11763
11764 if (flags & YNegative)
11765 {
11766 int menubar_height = 0;
11767
11768 #ifdef USE_X_TOOLKIT
11769 if (f->output_data.x->menubar_widget)
11770 menubar_height
11771 = (f->output_data.x->menubar_widget->core.height
11772 + f->output_data.x->menubar_widget->core.border_width);
11773 #endif
11774
11775 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11776 - 2 * f->output_data.x->border_width
11777 - win_y
11778 - PIXEL_HEIGHT (f)
11779 - menubar_height
11780 + f->output_data.x->top_pos);
11781 }
11782
11783 /* The left_pos and top_pos
11784 are now relative to the top and left screen edges,
11785 so the flags should correspond. */
11786 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11787 }
11788
11789 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11790 to really change the position, and 0 when calling from
11791 x_make_frame_visible (in that case, XOFF and YOFF are the current
11792 position values). It is -1 when calling from x_set_frame_parameters,
11793 which means, do adjust for borders but don't change the gravity. */
11794
11795 void
11796 x_set_offset (f, xoff, yoff, change_gravity)
11797 struct frame *f;
11798 register int xoff, yoff;
11799 int change_gravity;
11800 {
11801 int modified_top, modified_left;
11802
11803 if (change_gravity > 0)
11804 {
11805 f->output_data.x->top_pos = yoff;
11806 f->output_data.x->left_pos = xoff;
11807 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11808 if (xoff < 0)
11809 f->output_data.x->size_hint_flags |= XNegative;
11810 if (yoff < 0)
11811 f->output_data.x->size_hint_flags |= YNegative;
11812 f->output_data.x->win_gravity = NorthWestGravity;
11813 }
11814 x_calc_absolute_position (f);
11815
11816 BLOCK_INPUT;
11817 x_wm_set_size_hint (f, (long) 0, 0);
11818
11819 modified_left = f->output_data.x->left_pos;
11820 modified_top = f->output_data.x->top_pos;
11821 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11822 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11823 /* It is a mystery why we need to add the border_width here
11824 when the frame is already visible, but experiment says we do. */
11825 if (change_gravity != 0)
11826 {
11827 modified_left += f->output_data.x->border_width;
11828 modified_top += f->output_data.x->border_width;
11829 }
11830 #endif
11831
11832 #ifdef USE_X_TOOLKIT
11833 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11834 modified_left, modified_top);
11835 #else /* not USE_X_TOOLKIT */
11836 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11837 modified_left, modified_top);
11838 #endif /* not USE_X_TOOLKIT */
11839 UNBLOCK_INPUT;
11840 }
11841
11842 /* Call this to change the size of frame F's x-window.
11843 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11844 for this size change and subsequent size changes.
11845 Otherwise we leave the window gravity unchanged. */
11846
11847 void
11848 x_set_window_size (f, change_gravity, cols, rows)
11849 struct frame *f;
11850 int change_gravity;
11851 int cols, rows;
11852 {
11853 #ifndef USE_X_TOOLKIT
11854 int pixelwidth, pixelheight;
11855 #endif
11856
11857 BLOCK_INPUT;
11858
11859 #ifdef USE_X_TOOLKIT
11860 {
11861 /* The x and y position of the widget is clobbered by the
11862 call to XtSetValues within EmacsFrameSetCharSize.
11863 This is a real kludge, but I don't understand Xt so I can't
11864 figure out a correct fix. Can anyone else tell me? -- rms. */
11865 int xpos = f->output_data.x->widget->core.x;
11866 int ypos = f->output_data.x->widget->core.y;
11867 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11868 f->output_data.x->widget->core.x = xpos;
11869 f->output_data.x->widget->core.y = ypos;
11870 }
11871
11872 #else /* not USE_X_TOOLKIT */
11873
11874 check_frame_size (f, &rows, &cols);
11875 f->output_data.x->vertical_scroll_bar_extra
11876 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11877 ? 0
11878 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11879 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11880 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11881 f->output_data.x->flags_areas_extra
11882 = FRAME_FLAGS_AREA_WIDTH (f);
11883 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11884 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11885
11886 f->output_data.x->win_gravity = NorthWestGravity;
11887 x_wm_set_size_hint (f, (long) 0, 0);
11888
11889 XSync (FRAME_X_DISPLAY (f), False);
11890 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11891 pixelwidth, pixelheight);
11892
11893 /* Now, strictly speaking, we can't be sure that this is accurate,
11894 but the window manager will get around to dealing with the size
11895 change request eventually, and we'll hear how it went when the
11896 ConfigureNotify event gets here.
11897
11898 We could just not bother storing any of this information here,
11899 and let the ConfigureNotify event set everything up, but that
11900 might be kind of confusing to the Lisp code, since size changes
11901 wouldn't be reported in the frame parameters until some random
11902 point in the future when the ConfigureNotify event arrives.
11903
11904 We pass 1 for DELAY since we can't run Lisp code inside of
11905 a BLOCK_INPUT. */
11906 change_frame_size (f, rows, cols, 0, 1, 0);
11907 PIXEL_WIDTH (f) = pixelwidth;
11908 PIXEL_HEIGHT (f) = pixelheight;
11909
11910 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11911 receive in the ConfigureNotify event; if we get what we asked
11912 for, then the event won't cause the screen to become garbaged, so
11913 we have to make sure to do it here. */
11914 SET_FRAME_GARBAGED (f);
11915
11916 XFlush (FRAME_X_DISPLAY (f));
11917
11918 #endif /* not USE_X_TOOLKIT */
11919
11920 /* If cursor was outside the new size, mark it as off. */
11921 mark_window_cursors_off (XWINDOW (f->root_window));
11922
11923 /* Clear out any recollection of where the mouse highlighting was,
11924 since it might be in a place that's outside the new frame size.
11925 Actually checking whether it is outside is a pain in the neck,
11926 so don't try--just let the highlighting be done afresh with new size. */
11927 cancel_mouse_face (f);
11928
11929 UNBLOCK_INPUT;
11930 }
11931 \f
11932 /* Mouse warping. */
11933
11934 void
11935 x_set_mouse_position (f, x, y)
11936 struct frame *f;
11937 int x, y;
11938 {
11939 int pix_x, pix_y;
11940
11941 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11942 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11943
11944 if (pix_x < 0) pix_x = 0;
11945 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11946
11947 if (pix_y < 0) pix_y = 0;
11948 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11949
11950 BLOCK_INPUT;
11951
11952 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11953 0, 0, 0, 0, pix_x, pix_y);
11954 UNBLOCK_INPUT;
11955 }
11956
11957 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11958
11959 void
11960 x_set_mouse_pixel_position (f, pix_x, pix_y)
11961 struct frame *f;
11962 int pix_x, pix_y;
11963 {
11964 BLOCK_INPUT;
11965
11966 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11967 0, 0, 0, 0, pix_x, pix_y);
11968 UNBLOCK_INPUT;
11969 }
11970 \f
11971 /* focus shifting, raising and lowering. */
11972
11973 void
11974 x_focus_on_frame (f)
11975 struct frame *f;
11976 {
11977 #if 0 /* This proves to be unpleasant. */
11978 x_raise_frame (f);
11979 #endif
11980 #if 0
11981 /* I don't think that the ICCCM allows programs to do things like this
11982 without the interaction of the window manager. Whatever you end up
11983 doing with this code, do it to x_unfocus_frame too. */
11984 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11985 RevertToPointerRoot, CurrentTime);
11986 #endif /* ! 0 */
11987 }
11988
11989 void
11990 x_unfocus_frame (f)
11991 struct frame *f;
11992 {
11993 #if 0
11994 /* Look at the remarks in x_focus_on_frame. */
11995 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11996 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11997 RevertToPointerRoot, CurrentTime);
11998 #endif /* ! 0 */
11999 }
12000
12001 /* Raise frame F. */
12002
12003 void
12004 x_raise_frame (f)
12005 struct frame *f;
12006 {
12007 if (f->async_visible)
12008 {
12009 BLOCK_INPUT;
12010 #ifdef USE_X_TOOLKIT
12011 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12012 #else /* not USE_X_TOOLKIT */
12013 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12014 #endif /* not USE_X_TOOLKIT */
12015 XFlush (FRAME_X_DISPLAY (f));
12016 UNBLOCK_INPUT;
12017 }
12018 }
12019
12020 /* Lower frame F. */
12021
12022 void
12023 x_lower_frame (f)
12024 struct frame *f;
12025 {
12026 if (f->async_visible)
12027 {
12028 BLOCK_INPUT;
12029 #ifdef USE_X_TOOLKIT
12030 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
12031 #else /* not USE_X_TOOLKIT */
12032 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12033 #endif /* not USE_X_TOOLKIT */
12034 XFlush (FRAME_X_DISPLAY (f));
12035 UNBLOCK_INPUT;
12036 }
12037 }
12038
12039 static void
12040 XTframe_raise_lower (f, raise_flag)
12041 FRAME_PTR f;
12042 int raise_flag;
12043 {
12044 if (raise_flag)
12045 x_raise_frame (f);
12046 else
12047 x_lower_frame (f);
12048 }
12049 \f
12050 /* Change of visibility. */
12051
12052 /* This tries to wait until the frame is really visible.
12053 However, if the window manager asks the user where to position
12054 the frame, this will return before the user finishes doing that.
12055 The frame will not actually be visible at that time,
12056 but it will become visible later when the window manager
12057 finishes with it. */
12058
12059 void
12060 x_make_frame_visible (f)
12061 struct frame *f;
12062 {
12063 Lisp_Object type;
12064 int original_top, original_left;
12065 int retry_count = 2;
12066
12067 retry:
12068
12069 BLOCK_INPUT;
12070
12071 type = x_icon_type (f);
12072 if (!NILP (type))
12073 x_bitmap_icon (f, type);
12074
12075 if (! FRAME_VISIBLE_P (f))
12076 {
12077 /* We test FRAME_GARBAGED_P here to make sure we don't
12078 call x_set_offset a second time
12079 if we get to x_make_frame_visible a second time
12080 before the window gets really visible. */
12081 if (! FRAME_ICONIFIED_P (f)
12082 && ! f->output_data.x->asked_for_visible)
12083 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12084
12085 f->output_data.x->asked_for_visible = 1;
12086
12087 if (! EQ (Vx_no_window_manager, Qt))
12088 x_wm_set_window_state (f, NormalState);
12089 #ifdef USE_X_TOOLKIT
12090 /* This was XtPopup, but that did nothing for an iconified frame. */
12091 XtMapWidget (f->output_data.x->widget);
12092 #else /* not USE_X_TOOLKIT */
12093 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12094 #endif /* not USE_X_TOOLKIT */
12095 #if 0 /* This seems to bring back scroll bars in the wrong places
12096 if the window configuration has changed. They seem
12097 to come back ok without this. */
12098 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
12099 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12100 #endif
12101 }
12102
12103 XFlush (FRAME_X_DISPLAY (f));
12104
12105 /* Synchronize to ensure Emacs knows the frame is visible
12106 before we do anything else. We do this loop with input not blocked
12107 so that incoming events are handled. */
12108 {
12109 Lisp_Object frame;
12110 int count;
12111 /* This must be before UNBLOCK_INPUT
12112 since events that arrive in response to the actions above
12113 will set it when they are handled. */
12114 int previously_visible = f->output_data.x->has_been_visible;
12115
12116 original_left = f->output_data.x->left_pos;
12117 original_top = f->output_data.x->top_pos;
12118
12119 /* This must come after we set COUNT. */
12120 UNBLOCK_INPUT;
12121
12122 /* We unblock here so that arriving X events are processed. */
12123
12124 /* Now move the window back to where it was "supposed to be".
12125 But don't do it if the gravity is negative.
12126 When the gravity is negative, this uses a position
12127 that is 3 pixels too low. Perhaps that's really the border width.
12128
12129 Don't do this if the window has never been visible before,
12130 because the window manager may choose the position
12131 and we don't want to override it. */
12132
12133 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
12134 && f->output_data.x->win_gravity == NorthWestGravity
12135 && previously_visible)
12136 {
12137 Drawable rootw;
12138 int x, y;
12139 unsigned int width, height, border, depth;
12140
12141 BLOCK_INPUT;
12142
12143 /* On some window managers (such as FVWM) moving an existing
12144 window, even to the same place, causes the window manager
12145 to introduce an offset. This can cause the window to move
12146 to an unexpected location. Check the geometry (a little
12147 slow here) and then verify that the window is in the right
12148 place. If the window is not in the right place, move it
12149 there, and take the potential window manager hit. */
12150 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12151 &rootw, &x, &y, &width, &height, &border, &depth);
12152
12153 if (original_left != x || original_top != y)
12154 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12155 original_left, original_top);
12156
12157 UNBLOCK_INPUT;
12158 }
12159
12160 XSETFRAME (frame, f);
12161
12162 /* Wait until the frame is visible. Process X events until a
12163 MapNotify event has been seen, or until we think we won't get a
12164 MapNotify at all.. */
12165 for (count = input_signal_count + 10;
12166 input_signal_count < count && !FRAME_VISIBLE_P (f);)
12167 {
12168 /* Force processing of queued events. */
12169 x_sync (f);
12170
12171 /* Machines that do polling rather than SIGIO have been
12172 observed to go into a busy-wait here. So we'll fake an
12173 alarm signal to let the handler know that there's something
12174 to be read. We used to raise a real alarm, but it seems
12175 that the handler isn't always enabled here. This is
12176 probably a bug. */
12177 if (input_polling_used ())
12178 {
12179 /* It could be confusing if a real alarm arrives while
12180 processing the fake one. Turn it off and let the
12181 handler reset it. */
12182 extern void poll_for_input_1 P_ ((void));
12183 int old_poll_suppress_count = poll_suppress_count;
12184 poll_suppress_count = 1;
12185 poll_for_input_1 ();
12186 poll_suppress_count = old_poll_suppress_count;
12187 }
12188
12189 /* See if a MapNotify event has been processed. */
12190 FRAME_SAMPLE_VISIBILITY (f);
12191 }
12192
12193 /* 2000-09-28: In
12194
12195 (let ((f (selected-frame)))
12196 (iconify-frame f)
12197 (raise-frame f))
12198
12199 the frame is not raised with various window managers on
12200 FreeBSD, Linux and Solaris. It turns out that, for some
12201 unknown reason, the call to XtMapWidget is completely ignored.
12202 Mapping the widget a second time works. */
12203
12204 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12205 goto retry;
12206 }
12207 }
12208
12209 /* Change from mapped state to withdrawn state. */
12210
12211 /* Make the frame visible (mapped and not iconified). */
12212
12213 void
12214 x_make_frame_invisible (f)
12215 struct frame *f;
12216 {
12217 Window window;
12218
12219 #ifdef USE_X_TOOLKIT
12220 /* Use the frame's outermost window, not the one we normally draw on. */
12221 window = XtWindow (f->output_data.x->widget);
12222 #else /* not USE_X_TOOLKIT */
12223 window = FRAME_X_WINDOW (f);
12224 #endif /* not USE_X_TOOLKIT */
12225
12226 /* Don't keep the highlight on an invisible frame. */
12227 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12228 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12229
12230 #if 0/* This might add unreliability; I don't trust it -- rms. */
12231 if (! f->async_visible && ! f->async_iconified)
12232 return;
12233 #endif
12234
12235 BLOCK_INPUT;
12236
12237 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12238 that the current position of the window is user-specified, rather than
12239 program-specified, so that when the window is mapped again, it will be
12240 placed at the same location, without forcing the user to position it
12241 by hand again (they have already done that once for this window.) */
12242 x_wm_set_size_hint (f, (long) 0, 1);
12243
12244 #ifdef HAVE_X11R4
12245
12246 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12247 DefaultScreen (FRAME_X_DISPLAY (f))))
12248 {
12249 UNBLOCK_INPUT_RESIGNAL;
12250 error ("Can't notify window manager of window withdrawal");
12251 }
12252 #else /* ! defined (HAVE_X11R4) */
12253
12254 /* Tell the window manager what we're going to do. */
12255 if (! EQ (Vx_no_window_manager, Qt))
12256 {
12257 XEvent unmap;
12258
12259 unmap.xunmap.type = UnmapNotify;
12260 unmap.xunmap.window = window;
12261 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
12262 unmap.xunmap.from_configure = False;
12263 if (! XSendEvent (FRAME_X_DISPLAY (f),
12264 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12265 False,
12266 SubstructureRedirectMaskSubstructureNotifyMask,
12267 &unmap))
12268 {
12269 UNBLOCK_INPUT_RESIGNAL;
12270 error ("Can't notify window manager of withdrawal");
12271 }
12272 }
12273
12274 /* Unmap the window ourselves. Cheeky! */
12275 XUnmapWindow (FRAME_X_DISPLAY (f), window);
12276 #endif /* ! defined (HAVE_X11R4) */
12277
12278 /* We can't distinguish this from iconification
12279 just by the event that we get from the server.
12280 So we can't win using the usual strategy of letting
12281 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12282 and synchronize with the server to make sure we agree. */
12283 f->visible = 0;
12284 FRAME_ICONIFIED_P (f) = 0;
12285 f->async_visible = 0;
12286 f->async_iconified = 0;
12287
12288 x_sync (f);
12289
12290 UNBLOCK_INPUT;
12291 }
12292
12293 /* Change window state from mapped to iconified. */
12294
12295 void
12296 x_iconify_frame (f)
12297 struct frame *f;
12298 {
12299 int result;
12300 Lisp_Object type;
12301
12302 /* Don't keep the highlight on an invisible frame. */
12303 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12304 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
12305
12306 if (f->async_iconified)
12307 return;
12308
12309 BLOCK_INPUT;
12310
12311 FRAME_SAMPLE_VISIBILITY (f);
12312
12313 type = x_icon_type (f);
12314 if (!NILP (type))
12315 x_bitmap_icon (f, type);
12316
12317 #ifdef USE_X_TOOLKIT
12318
12319 if (! FRAME_VISIBLE_P (f))
12320 {
12321 if (! EQ (Vx_no_window_manager, Qt))
12322 x_wm_set_window_state (f, IconicState);
12323 /* This was XtPopup, but that did nothing for an iconified frame. */
12324 XtMapWidget (f->output_data.x->widget);
12325 /* The server won't give us any event to indicate
12326 that an invisible frame was changed to an icon,
12327 so we have to record it here. */
12328 f->iconified = 1;
12329 f->visible = 1;
12330 f->async_iconified = 1;
12331 f->async_visible = 0;
12332 UNBLOCK_INPUT;
12333 return;
12334 }
12335
12336 result = XIconifyWindow (FRAME_X_DISPLAY (f),
12337 XtWindow (f->output_data.x->widget),
12338 DefaultScreen (FRAME_X_DISPLAY (f)));
12339 UNBLOCK_INPUT;
12340
12341 if (!result)
12342 error ("Can't notify window manager of iconification");
12343
12344 f->async_iconified = 1;
12345 f->async_visible = 0;
12346
12347
12348 BLOCK_INPUT;
12349 XFlush (FRAME_X_DISPLAY (f));
12350 UNBLOCK_INPUT;
12351 #else /* not USE_X_TOOLKIT */
12352
12353 /* Make sure the X server knows where the window should be positioned,
12354 in case the user deiconifies with the window manager. */
12355 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
12356 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12357
12358 /* Since we don't know which revision of X we're running, we'll use both
12359 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12360
12361 /* X11R4: send a ClientMessage to the window manager using the
12362 WM_CHANGE_STATE type. */
12363 {
12364 XEvent message;
12365
12366 message.xclient.window = FRAME_X_WINDOW (f);
12367 message.xclient.type = ClientMessage;
12368 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
12369 message.xclient.format = 32;
12370 message.xclient.data.l[0] = IconicState;
12371
12372 if (! XSendEvent (FRAME_X_DISPLAY (f),
12373 DefaultRootWindow (FRAME_X_DISPLAY (f)),
12374 False,
12375 SubstructureRedirectMask | SubstructureNotifyMask,
12376 &message))
12377 {
12378 UNBLOCK_INPUT_RESIGNAL;
12379 error ("Can't notify window manager of iconification");
12380 }
12381 }
12382
12383 /* X11R3: set the initial_state field of the window manager hints to
12384 IconicState. */
12385 x_wm_set_window_state (f, IconicState);
12386
12387 if (!FRAME_VISIBLE_P (f))
12388 {
12389 /* If the frame was withdrawn, before, we must map it. */
12390 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12391 }
12392
12393 f->async_iconified = 1;
12394 f->async_visible = 0;
12395
12396 XFlush (FRAME_X_DISPLAY (f));
12397 UNBLOCK_INPUT;
12398 #endif /* not USE_X_TOOLKIT */
12399 }
12400 \f
12401 /* Destroy the X window of frame F. */
12402
12403 void
12404 x_destroy_window (f)
12405 struct frame *f;
12406 {
12407 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12408
12409 BLOCK_INPUT;
12410
12411 /* If a display connection is dead, don't try sending more
12412 commands to the X server. */
12413 if (dpyinfo->display != 0)
12414 {
12415 if (f->output_data.x->icon_desc != 0)
12416 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12417 #ifdef HAVE_X_I18N
12418 if (FRAME_XIC (f))
12419 free_frame_xic (f);
12420 #endif
12421 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
12422 #ifdef USE_X_TOOLKIT
12423 if (f->output_data.x->widget)
12424 XtDestroyWidget (f->output_data.x->widget);
12425 free_frame_menubar (f);
12426 #endif /* USE_X_TOOLKIT */
12427
12428 unload_color (f, f->output_data.x->foreground_pixel);
12429 unload_color (f, f->output_data.x->background_pixel);
12430 unload_color (f, f->output_data.x->cursor_pixel);
12431 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12432 unload_color (f, f->output_data.x->border_pixel);
12433 unload_color (f, f->output_data.x->mouse_pixel);
12434 if (f->output_data.x->scroll_bar_background_pixel != -1)
12435 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12436 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12437 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12438 if (f->output_data.x->white_relief.allocated_p)
12439 unload_color (f, f->output_data.x->white_relief.pixel);
12440 if (f->output_data.x->black_relief.allocated_p)
12441 unload_color (f, f->output_data.x->black_relief.pixel);
12442
12443 free_frame_faces (f);
12444 XFlush (FRAME_X_DISPLAY (f));
12445 }
12446
12447 if (f->output_data.x->saved_menu_event)
12448 xfree (f->output_data.x->saved_menu_event);
12449
12450 xfree (f->output_data.x);
12451 f->output_data.x = 0;
12452 if (f == dpyinfo->x_focus_frame)
12453 dpyinfo->x_focus_frame = 0;
12454 if (f == dpyinfo->x_focus_event_frame)
12455 dpyinfo->x_focus_event_frame = 0;
12456 if (f == dpyinfo->x_highlight_frame)
12457 dpyinfo->x_highlight_frame = 0;
12458
12459 dpyinfo->reference_count--;
12460
12461 if (f == dpyinfo->mouse_face_mouse_frame)
12462 {
12463 dpyinfo->mouse_face_beg_row
12464 = dpyinfo->mouse_face_beg_col = -1;
12465 dpyinfo->mouse_face_end_row
12466 = dpyinfo->mouse_face_end_col = -1;
12467 dpyinfo->mouse_face_window = Qnil;
12468 dpyinfo->mouse_face_deferred_gc = 0;
12469 dpyinfo->mouse_face_mouse_frame = 0;
12470 }
12471
12472 UNBLOCK_INPUT;
12473 }
12474 \f
12475 /* Setting window manager hints. */
12476
12477 /* Set the normal size hints for the window manager, for frame F.
12478 FLAGS is the flags word to use--or 0 meaning preserve the flags
12479 that the window now has.
12480 If USER_POSITION is nonzero, we set the USPosition
12481 flag (this is useful when FLAGS is 0). */
12482
12483 void
12484 x_wm_set_size_hint (f, flags, user_position)
12485 struct frame *f;
12486 long flags;
12487 int user_position;
12488 {
12489 XSizeHints size_hints;
12490
12491 #ifdef USE_X_TOOLKIT
12492 Arg al[2];
12493 int ac = 0;
12494 Dimension widget_width, widget_height;
12495 Window window = XtWindow (f->output_data.x->widget);
12496 #else /* not USE_X_TOOLKIT */
12497 Window window = FRAME_X_WINDOW (f);
12498 #endif /* not USE_X_TOOLKIT */
12499
12500 /* Setting PMaxSize caused various problems. */
12501 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12502
12503 size_hints.x = f->output_data.x->left_pos;
12504 size_hints.y = f->output_data.x->top_pos;
12505
12506 #ifdef USE_X_TOOLKIT
12507 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12508 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12509 XtGetValues (f->output_data.x->widget, al, ac);
12510 size_hints.height = widget_height;
12511 size_hints.width = widget_width;
12512 #else /* not USE_X_TOOLKIT */
12513 size_hints.height = PIXEL_HEIGHT (f);
12514 size_hints.width = PIXEL_WIDTH (f);
12515 #endif /* not USE_X_TOOLKIT */
12516
12517 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12518 size_hints.height_inc = f->output_data.x->line_height;
12519 size_hints.max_width
12520 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12521 size_hints.max_height
12522 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12523
12524 /* Calculate the base and minimum sizes.
12525
12526 (When we use the X toolkit, we don't do it here.
12527 Instead we copy the values that the widgets are using, below.) */
12528 #ifndef USE_X_TOOLKIT
12529 {
12530 int base_width, base_height;
12531 int min_rows = 0, min_cols = 0;
12532
12533 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12534 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12535
12536 check_frame_size (f, &min_rows, &min_cols);
12537
12538 /* The window manager uses the base width hints to calculate the
12539 current number of rows and columns in the frame while
12540 resizing; min_width and min_height aren't useful for this
12541 purpose, since they might not give the dimensions for a
12542 zero-row, zero-column frame.
12543
12544 We use the base_width and base_height members if we have
12545 them; otherwise, we set the min_width and min_height members
12546 to the size for a zero x zero frame. */
12547
12548 #ifdef HAVE_X11R4
12549 size_hints.flags |= PBaseSize;
12550 size_hints.base_width = base_width;
12551 size_hints.base_height = base_height;
12552 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12553 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12554 #else
12555 size_hints.min_width = base_width;
12556 size_hints.min_height = base_height;
12557 #endif
12558 }
12559
12560 /* If we don't need the old flags, we don't need the old hint at all. */
12561 if (flags)
12562 {
12563 size_hints.flags |= flags;
12564 goto no_read;
12565 }
12566 #endif /* not USE_X_TOOLKIT */
12567
12568 {
12569 XSizeHints hints; /* Sometimes I hate X Windows... */
12570 long supplied_return;
12571 int value;
12572
12573 #ifdef HAVE_X11R4
12574 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12575 &supplied_return);
12576 #else
12577 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12578 #endif
12579
12580 #ifdef USE_X_TOOLKIT
12581 size_hints.base_height = hints.base_height;
12582 size_hints.base_width = hints.base_width;
12583 size_hints.min_height = hints.min_height;
12584 size_hints.min_width = hints.min_width;
12585 #endif
12586
12587 if (flags)
12588 size_hints.flags |= flags;
12589 else
12590 {
12591 if (value == 0)
12592 hints.flags = 0;
12593 if (hints.flags & PSize)
12594 size_hints.flags |= PSize;
12595 if (hints.flags & PPosition)
12596 size_hints.flags |= PPosition;
12597 if (hints.flags & USPosition)
12598 size_hints.flags |= USPosition;
12599 if (hints.flags & USSize)
12600 size_hints.flags |= USSize;
12601 }
12602 }
12603
12604 #ifndef USE_X_TOOLKIT
12605 no_read:
12606 #endif
12607
12608 #ifdef PWinGravity
12609 size_hints.win_gravity = f->output_data.x->win_gravity;
12610 size_hints.flags |= PWinGravity;
12611
12612 if (user_position)
12613 {
12614 size_hints.flags &= ~ PPosition;
12615 size_hints.flags |= USPosition;
12616 }
12617 #endif /* PWinGravity */
12618
12619 #ifdef HAVE_X11R4
12620 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12621 #else
12622 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12623 #endif
12624 }
12625
12626 /* Used for IconicState or NormalState */
12627
12628 void
12629 x_wm_set_window_state (f, state)
12630 struct frame *f;
12631 int state;
12632 {
12633 #ifdef USE_X_TOOLKIT
12634 Arg al[1];
12635
12636 XtSetArg (al[0], XtNinitialState, state);
12637 XtSetValues (f->output_data.x->widget, al, 1);
12638 #else /* not USE_X_TOOLKIT */
12639 Window window = FRAME_X_WINDOW (f);
12640
12641 f->output_data.x->wm_hints.flags |= StateHint;
12642 f->output_data.x->wm_hints.initial_state = state;
12643
12644 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12645 #endif /* not USE_X_TOOLKIT */
12646 }
12647
12648 void
12649 x_wm_set_icon_pixmap (f, pixmap_id)
12650 struct frame *f;
12651 int pixmap_id;
12652 {
12653 Pixmap icon_pixmap;
12654
12655 #ifndef USE_X_TOOLKIT
12656 Window window = FRAME_X_WINDOW (f);
12657 #endif
12658
12659 if (pixmap_id > 0)
12660 {
12661 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12662 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12663 }
12664 else
12665 {
12666 /* It seems there is no way to turn off use of an icon pixmap.
12667 The following line does it, only if no icon has yet been created,
12668 for some window managers. But with mwm it crashes.
12669 Some people say it should clear the IconPixmapHint bit in this case,
12670 but that doesn't work, and the X consortium said it isn't the
12671 right thing at all. Since there is no way to win,
12672 best to explicitly give up. */
12673 #if 0
12674 f->output_data.x->wm_hints.icon_pixmap = None;
12675 #else
12676 return;
12677 #endif
12678 }
12679
12680 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12681
12682 {
12683 Arg al[1];
12684 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12685 XtSetValues (f->output_data.x->widget, al, 1);
12686 }
12687
12688 #else /* not USE_X_TOOLKIT */
12689
12690 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12691 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12692
12693 #endif /* not USE_X_TOOLKIT */
12694 }
12695
12696 void
12697 x_wm_set_icon_position (f, icon_x, icon_y)
12698 struct frame *f;
12699 int icon_x, icon_y;
12700 {
12701 #ifdef USE_X_TOOLKIT
12702 Window window = XtWindow (f->output_data.x->widget);
12703 #else
12704 Window window = FRAME_X_WINDOW (f);
12705 #endif
12706
12707 f->output_data.x->wm_hints.flags |= IconPositionHint;
12708 f->output_data.x->wm_hints.icon_x = icon_x;
12709 f->output_data.x->wm_hints.icon_y = icon_y;
12710
12711 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12712 }
12713
12714 \f
12715 /***********************************************************************
12716 Fonts
12717 ***********************************************************************/
12718
12719 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12720
12721 struct font_info *
12722 x_get_font_info (f, font_idx)
12723 FRAME_PTR f;
12724 int font_idx;
12725 {
12726 return (FRAME_X_FONT_TABLE (f) + font_idx);
12727 }
12728
12729
12730 /* Return a list of names of available fonts matching PATTERN on frame
12731 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12732 to be listed. Frame F NULL means we have not yet created any
12733 frame on X, and consult the first display in x_display_list.
12734 MAXNAMES sets a limit on how many fonts to match. */
12735
12736 Lisp_Object
12737 x_list_fonts (f, pattern, size, maxnames)
12738 FRAME_PTR f;
12739 Lisp_Object pattern;
12740 int size;
12741 int maxnames;
12742 {
12743 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12744 Lisp_Object tem, second_best;
12745 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12746 int try_XLoadQueryFont = 0;
12747 int count;
12748
12749 patterns = Fassoc (pattern, Valternate_fontname_alist);
12750 if (NILP (patterns))
12751 patterns = Fcons (pattern, Qnil);
12752
12753 if (maxnames == 1 && !size)
12754 /* We can return any single font matching PATTERN. */
12755 try_XLoadQueryFont = 1;
12756
12757 for (; CONSP (patterns); patterns = XCDR (patterns))
12758 {
12759 int num_fonts;
12760 char **names = NULL;
12761
12762 pattern = XCAR (patterns);
12763 /* See if we cached the result for this particular query.
12764 The cache is an alist of the form:
12765 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12766 */
12767 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12768 key = Fcons (pattern, make_number (maxnames)),
12769 !NILP (list = Fassoc (key, tem))))
12770 {
12771 list = Fcdr_safe (list);
12772 /* We have a cashed list. Don't have to get the list again. */
12773 goto label_cached;
12774 }
12775
12776 /* At first, put PATTERN in the cache. */
12777
12778 BLOCK_INPUT;
12779 count = x_catch_errors (dpy);
12780
12781 if (try_XLoadQueryFont)
12782 {
12783 XFontStruct *font;
12784 unsigned long value;
12785
12786 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12787 if (x_had_errors_p (dpy))
12788 {
12789 /* This error is perhaps due to insufficient memory on X
12790 server. Let's just ignore it. */
12791 font = NULL;
12792 x_clear_errors (dpy);
12793 }
12794
12795 if (font
12796 && XGetFontProperty (font, XA_FONT, &value))
12797 {
12798 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12799 int len = strlen (name);
12800 char *tmp;
12801
12802 /* If DXPC (a Differential X Protocol Compressor)
12803 Ver.3.7 is running, XGetAtomName will return null
12804 string. We must avoid such a name. */
12805 if (len == 0)
12806 try_XLoadQueryFont = 0;
12807 else
12808 {
12809 num_fonts = 1;
12810 names = (char **) alloca (sizeof (char *));
12811 /* Some systems only allow alloca assigned to a
12812 simple var. */
12813 tmp = (char *) alloca (len + 1); names[0] = tmp;
12814 bcopy (name, names[0], len + 1);
12815 XFree (name);
12816 }
12817 }
12818 else
12819 try_XLoadQueryFont = 0;
12820
12821 if (font)
12822 XFreeFont (dpy, font);
12823 }
12824
12825 if (!try_XLoadQueryFont)
12826 {
12827 /* We try at least 10 fonts because XListFonts will return
12828 auto-scaled fonts at the head. */
12829 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12830 &num_fonts);
12831 if (x_had_errors_p (dpy))
12832 {
12833 /* This error is perhaps due to insufficient memory on X
12834 server. Let's just ignore it. */
12835 names = NULL;
12836 x_clear_errors (dpy);
12837 }
12838 }
12839
12840 x_uncatch_errors (dpy, count);
12841 UNBLOCK_INPUT;
12842
12843 if (names)
12844 {
12845 int i;
12846
12847 /* Make a list of all the fonts we got back.
12848 Store that in the font cache for the display. */
12849 for (i = 0; i < num_fonts; i++)
12850 {
12851 int width = 0;
12852 char *p = names[i];
12853 int average_width = -1, dashes = 0;
12854
12855 /* Count the number of dashes in NAMES[I]. If there are
12856 14 dashes, and the field value following 12th dash
12857 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12858 is usually too ugly to be used for editing. Let's
12859 ignore it. */
12860 while (*p)
12861 if (*p++ == '-')
12862 {
12863 dashes++;
12864 if (dashes == 7) /* PIXEL_SIZE field */
12865 width = atoi (p);
12866 else if (dashes == 12) /* AVERAGE_WIDTH field */
12867 average_width = atoi (p);
12868 }
12869 if (dashes < 14 || average_width != 0)
12870 {
12871 tem = build_string (names[i]);
12872 if (NILP (Fassoc (tem, list)))
12873 {
12874 if (STRINGP (Vx_pixel_size_width_font_regexp)
12875 && ((fast_c_string_match_ignore_case
12876 (Vx_pixel_size_width_font_regexp, names[i]))
12877 >= 0))
12878 /* We can set the value of PIXEL_SIZE to the
12879 width of this font. */
12880 list = Fcons (Fcons (tem, make_number (width)), list);
12881 else
12882 /* For the moment, width is not known. */
12883 list = Fcons (Fcons (tem, Qnil), list);
12884 }
12885 }
12886 }
12887 if (!try_XLoadQueryFont)
12888 XFreeFontNames (names);
12889 }
12890
12891 /* Now store the result in the cache. */
12892 if (f != NULL)
12893 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12894 = Fcons (Fcons (key, list),
12895 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12896
12897 label_cached:
12898 if (NILP (list)) continue; /* Try the remaining alternatives. */
12899
12900 newlist = second_best = Qnil;
12901 /* Make a list of the fonts that have the right width. */
12902 for (; CONSP (list); list = XCDR (list))
12903 {
12904 int found_size;
12905
12906 tem = XCAR (list);
12907
12908 if (!CONSP (tem) || NILP (XCAR (tem)))
12909 continue;
12910 if (!size)
12911 {
12912 newlist = Fcons (XCAR (tem), newlist);
12913 continue;
12914 }
12915
12916 if (!INTEGERP (XCDR (tem)))
12917 {
12918 /* Since we have not yet known the size of this font, we
12919 must try slow function call XLoadQueryFont. */
12920 XFontStruct *thisinfo;
12921
12922 BLOCK_INPUT;
12923 count = x_catch_errors (dpy);
12924 thisinfo = XLoadQueryFont (dpy,
12925 XSTRING (XCAR (tem))->data);
12926 if (x_had_errors_p (dpy))
12927 {
12928 /* This error is perhaps due to insufficient memory on X
12929 server. Let's just ignore it. */
12930 thisinfo = NULL;
12931 x_clear_errors (dpy);
12932 }
12933 x_uncatch_errors (dpy, count);
12934 UNBLOCK_INPUT;
12935
12936 if (thisinfo)
12937 {
12938 XCDR (tem)
12939 = (thisinfo->min_bounds.width == 0
12940 ? make_number (0)
12941 : make_number (thisinfo->max_bounds.width));
12942 XFreeFont (dpy, thisinfo);
12943 }
12944 else
12945 /* For unknown reason, the previous call of XListFont had
12946 returned a font which can't be opened. Record the size
12947 as 0 not to try to open it again. */
12948 XCDR (tem) = make_number (0);
12949 }
12950
12951 found_size = XINT (XCDR (tem));
12952 if (found_size == size)
12953 newlist = Fcons (XCAR (tem), newlist);
12954 else if (found_size > 0)
12955 {
12956 if (NILP (second_best))
12957 second_best = tem;
12958 else if (found_size < size)
12959 {
12960 if (XINT (XCDR (second_best)) > size
12961 || XINT (XCDR (second_best)) < found_size)
12962 second_best = tem;
12963 }
12964 else
12965 {
12966 if (XINT (XCDR (second_best)) > size
12967 && XINT (XCDR (second_best)) > found_size)
12968 second_best = tem;
12969 }
12970 }
12971 }
12972 if (!NILP (newlist))
12973 break;
12974 else if (!NILP (second_best))
12975 {
12976 newlist = Fcons (XCAR (second_best), Qnil);
12977 break;
12978 }
12979 }
12980
12981 return newlist;
12982 }
12983
12984
12985 #if GLYPH_DEBUG
12986
12987 /* Check that FONT is valid on frame F. It is if it can be found in F's
12988 font table. */
12989
12990 static void
12991 x_check_font (f, font)
12992 struct frame *f;
12993 XFontStruct *font;
12994 {
12995 int i;
12996 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12997
12998 xassert (font != NULL);
12999
13000 for (i = 0; i < dpyinfo->n_fonts; i++)
13001 if (dpyinfo->font_table[i].name
13002 && font == dpyinfo->font_table[i].font)
13003 break;
13004
13005 xassert (i < dpyinfo->n_fonts);
13006 }
13007
13008 #endif /* GLYPH_DEBUG != 0 */
13009
13010 /* Set *W to the minimum width, *H to the minimum font height of FONT.
13011 Note: There are (broken) X fonts out there with invalid XFontStruct
13012 min_bounds contents. For example, handa@etl.go.jp reports that
13013 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13014 have font->min_bounds.width == 0. */
13015
13016 static INLINE void
13017 x_font_min_bounds (font, w, h)
13018 XFontStruct *font;
13019 int *w, *h;
13020 {
13021 *h = FONT_HEIGHT (font);
13022 *w = font->min_bounds.width;
13023
13024 /* Try to handle the case where FONT->min_bounds has invalid
13025 contents. Since the only font known to have invalid min_bounds
13026 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13027 if (*w <= 0)
13028 *w = font->max_bounds.width;
13029 }
13030
13031
13032 /* Compute the smallest character width and smallest font height over
13033 all fonts available on frame F. Set the members smallest_char_width
13034 and smallest_font_height in F's x_display_info structure to
13035 the values computed. Value is non-zero if smallest_font_height or
13036 smallest_char_width become smaller than they were before. */
13037
13038 static int
13039 x_compute_min_glyph_bounds (f)
13040 struct frame *f;
13041 {
13042 int i;
13043 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13044 XFontStruct *font;
13045 int old_width = dpyinfo->smallest_char_width;
13046 int old_height = dpyinfo->smallest_font_height;
13047
13048 dpyinfo->smallest_font_height = 100000;
13049 dpyinfo->smallest_char_width = 100000;
13050
13051 for (i = 0; i < dpyinfo->n_fonts; ++i)
13052 if (dpyinfo->font_table[i].name)
13053 {
13054 struct font_info *fontp = dpyinfo->font_table + i;
13055 int w, h;
13056
13057 font = (XFontStruct *) fontp->font;
13058 xassert (font != (XFontStruct *) ~0);
13059 x_font_min_bounds (font, &w, &h);
13060
13061 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13062 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13063 }
13064
13065 xassert (dpyinfo->smallest_char_width > 0
13066 && dpyinfo->smallest_font_height > 0);
13067
13068 return (dpyinfo->n_fonts == 1
13069 || dpyinfo->smallest_char_width < old_width
13070 || dpyinfo->smallest_font_height < old_height);
13071 }
13072
13073
13074 /* Load font named FONTNAME of the size SIZE for frame F, and return a
13075 pointer to the structure font_info while allocating it dynamically.
13076 If SIZE is 0, load any size of font.
13077 If loading is failed, return NULL. */
13078
13079 struct font_info *
13080 x_load_font (f, fontname, size)
13081 struct frame *f;
13082 register char *fontname;
13083 int size;
13084 {
13085 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13086 Lisp_Object font_names;
13087 int count;
13088
13089 /* Get a list of all the fonts that match this name. Once we
13090 have a list of matching fonts, we compare them against the fonts
13091 we already have by comparing names. */
13092 font_names = x_list_fonts (f, build_string (fontname), size, 1);
13093
13094 if (!NILP (font_names))
13095 {
13096 Lisp_Object tail;
13097 int i;
13098
13099 for (i = 0; i < dpyinfo->n_fonts; i++)
13100 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
13101 if (dpyinfo->font_table[i].name
13102 && (!strcmp (dpyinfo->font_table[i].name,
13103 XSTRING (XCAR (tail))->data)
13104 || !strcmp (dpyinfo->font_table[i].full_name,
13105 XSTRING (XCAR (tail))->data)))
13106 return (dpyinfo->font_table + i);
13107 }
13108
13109 /* Load the font and add it to the table. */
13110 {
13111 char *full_name;
13112 XFontStruct *font;
13113 struct font_info *fontp;
13114 unsigned long value;
13115 int i;
13116
13117 /* If we have found fonts by x_list_font, load one of them. If
13118 not, we still try to load a font by the name given as FONTNAME
13119 because XListFonts (called in x_list_font) of some X server has
13120 a bug of not finding a font even if the font surely exists and
13121 is loadable by XLoadQueryFont. */
13122 if (size > 0 && !NILP (font_names))
13123 fontname = (char *) XSTRING (XCAR (font_names))->data;
13124
13125 BLOCK_INPUT;
13126 count = x_catch_errors (FRAME_X_DISPLAY (f));
13127 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
13128 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13129 {
13130 /* This error is perhaps due to insufficient memory on X
13131 server. Let's just ignore it. */
13132 font = NULL;
13133 x_clear_errors (FRAME_X_DISPLAY (f));
13134 }
13135 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
13136 UNBLOCK_INPUT;
13137 if (!font)
13138 return NULL;
13139
13140 /* Find a free slot in the font table. */
13141 for (i = 0; i < dpyinfo->n_fonts; ++i)
13142 if (dpyinfo->font_table[i].name == NULL)
13143 break;
13144
13145 /* If no free slot found, maybe enlarge the font table. */
13146 if (i == dpyinfo->n_fonts
13147 && dpyinfo->n_fonts == dpyinfo->font_table_size)
13148 {
13149 int sz;
13150 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13151 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
13152 dpyinfo->font_table
13153 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
13154 }
13155
13156 fontp = dpyinfo->font_table + i;
13157 if (i == dpyinfo->n_fonts)
13158 ++dpyinfo->n_fonts;
13159
13160 /* Now fill in the slots of *FONTP. */
13161 BLOCK_INPUT;
13162 fontp->font = font;
13163 fontp->font_idx = i;
13164 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13165 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13166
13167 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13168 full_name = 0;
13169 if (XGetFontProperty (font, XA_FONT, &value))
13170 {
13171 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13172 char *p = name;
13173 int dashes = 0;
13174
13175 /* Count the number of dashes in the "full name".
13176 If it is too few, this isn't really the font's full name,
13177 so don't use it.
13178 In X11R4, the fonts did not come with their canonical names
13179 stored in them. */
13180 while (*p)
13181 {
13182 if (*p == '-')
13183 dashes++;
13184 p++;
13185 }
13186
13187 if (dashes >= 13)
13188 {
13189 full_name = (char *) xmalloc (p - name + 1);
13190 bcopy (name, full_name, p - name + 1);
13191 }
13192
13193 XFree (name);
13194 }
13195
13196 if (full_name != 0)
13197 fontp->full_name = full_name;
13198 else
13199 fontp->full_name = fontp->name;
13200
13201 fontp->size = font->max_bounds.width;
13202 fontp->height = FONT_HEIGHT (font);
13203 {
13204 /* For some font, ascent and descent in max_bounds field is
13205 larger than the above value. */
13206 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
13207 if (max_height > fontp->height)
13208 fontp->height = max_height;
13209 }
13210
13211 if (NILP (font_names))
13212 {
13213 /* We come here because of a bug of XListFonts mentioned at
13214 the head of this block. Let's store this information in
13215 the cache for x_list_fonts. */
13216 Lisp_Object lispy_name = build_string (fontname);
13217 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13218
13219 XCDR (dpyinfo->name_list_element)
13220 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
13221 Fcons (Fcons (lispy_full_name,
13222 make_number (fontp->size)),
13223 Qnil)),
13224 XCDR (dpyinfo->name_list_element));
13225 if (full_name)
13226 XCDR (dpyinfo->name_list_element)
13227 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
13228 Fcons (Fcons (lispy_full_name,
13229 make_number (fontp->size)),
13230 Qnil)),
13231 XCDR (dpyinfo->name_list_element));
13232 }
13233
13234 /* The slot `encoding' specifies how to map a character
13235 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
13236 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13237 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
13238 2:0xA020..0xFF7F). For the moment, we don't know which charset
13239 uses this font. So, we set information in fontp->encoding[1]
13240 which is never used by any charset. If mapping can't be
13241 decided, set FONT_ENCODING_NOT_DECIDED. */
13242 fontp->encoding[1]
13243 = (font->max_byte1 == 0
13244 /* 1-byte font */
13245 ? (font->min_char_or_byte2 < 0x80
13246 ? (font->max_char_or_byte2 < 0x80
13247 ? 0 /* 0x20..0x7F */
13248 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
13249 : 1) /* 0xA0..0xFF */
13250 /* 2-byte font */
13251 : (font->min_byte1 < 0x80
13252 ? (font->max_byte1 < 0x80
13253 ? (font->min_char_or_byte2 < 0x80
13254 ? (font->max_char_or_byte2 < 0x80
13255 ? 0 /* 0x2020..0x7F7F */
13256 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
13257 : 3) /* 0x20A0..0x7FFF */
13258 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
13259 : (font->min_char_or_byte2 < 0x80
13260 ? (font->max_char_or_byte2 < 0x80
13261 ? 2 /* 0xA020..0xFF7F */
13262 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
13263 : 1))); /* 0xA0A0..0xFFFF */
13264
13265 fontp->baseline_offset
13266 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13267 ? (long) value : 0);
13268 fontp->relative_compose
13269 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13270 ? (long) value : 0);
13271 fontp->default_ascent
13272 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13273 ? (long) value : 0);
13274
13275 /* Set global flag fonts_changed_p to non-zero if the font loaded
13276 has a character with a smaller width than any other character
13277 before, or if the font loaded has a smalle>r height than any
13278 other font loaded before. If this happens, it will make a
13279 glyph matrix reallocation necessary. */
13280 fonts_changed_p = x_compute_min_glyph_bounds (f);
13281 UNBLOCK_INPUT;
13282 return fontp;
13283 }
13284 }
13285
13286
13287 /* Return a pointer to struct font_info of a font named FONTNAME for
13288 frame F. If no such font is loaded, return NULL. */
13289
13290 struct font_info *
13291 x_query_font (f, fontname)
13292 struct frame *f;
13293 register char *fontname;
13294 {
13295 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13296 int i;
13297
13298 for (i = 0; i < dpyinfo->n_fonts; i++)
13299 if (dpyinfo->font_table[i].name
13300 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13301 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
13302 return (dpyinfo->font_table + i);
13303 return NULL;
13304 }
13305
13306
13307 /* Find a CCL program for a font specified by FONTP, and set the member
13308 `encoder' of the structure. */
13309
13310 void
13311 x_find_ccl_program (fontp)
13312 struct font_info *fontp;
13313 {
13314 Lisp_Object list, elt;
13315
13316 elt = Qnil;
13317 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
13318 {
13319 elt = XCAR (list);
13320 if (CONSP (elt)
13321 && STRINGP (XCAR (elt))
13322 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13323 >= 0)
13324 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13325 >= 0)))
13326 break;
13327 }
13328
13329 if (! NILP (list))
13330 {
13331 struct ccl_program *ccl
13332 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
13333
13334 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
13335 xfree (ccl);
13336 else
13337 fontp->font_encoder = ccl;
13338 }
13339 }
13340
13341
13342 \f
13343 /***********************************************************************
13344 Initialization
13345 ***********************************************************************/
13346
13347 #ifdef USE_X_TOOLKIT
13348 static XrmOptionDescRec emacs_options[] = {
13349 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13350 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13351
13352 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13353 XrmoptionSepArg, NULL},
13354 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13355
13356 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13357 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13358 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13359 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13360 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13361 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13362 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13363 };
13364 #endif /* USE_X_TOOLKIT */
13365
13366 static int x_initialized;
13367
13368 #ifdef MULTI_KBOARD
13369 /* Test whether two display-name strings agree up to the dot that separates
13370 the screen number from the server number. */
13371 static int
13372 same_x_server (name1, name2)
13373 char *name1, *name2;
13374 {
13375 int seen_colon = 0;
13376 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13377 int system_name_length = strlen (system_name);
13378 int length_until_period = 0;
13379
13380 while (system_name[length_until_period] != 0
13381 && system_name[length_until_period] != '.')
13382 length_until_period++;
13383
13384 /* Treat `unix' like an empty host name. */
13385 if (! strncmp (name1, "unix:", 5))
13386 name1 += 4;
13387 if (! strncmp (name2, "unix:", 5))
13388 name2 += 4;
13389 /* Treat this host's name like an empty host name. */
13390 if (! strncmp (name1, system_name, system_name_length)
13391 && name1[system_name_length] == ':')
13392 name1 += system_name_length;
13393 if (! strncmp (name2, system_name, system_name_length)
13394 && name2[system_name_length] == ':')
13395 name2 += system_name_length;
13396 /* Treat this host's domainless name like an empty host name. */
13397 if (! strncmp (name1, system_name, length_until_period)
13398 && name1[length_until_period] == ':')
13399 name1 += length_until_period;
13400 if (! strncmp (name2, system_name, length_until_period)
13401 && name2[length_until_period] == ':')
13402 name2 += length_until_period;
13403
13404 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13405 {
13406 if (*name1 == ':')
13407 seen_colon++;
13408 if (seen_colon && *name1 == '.')
13409 return 1;
13410 }
13411 return (seen_colon
13412 && (*name1 == '.' || *name1 == '\0')
13413 && (*name2 == '.' || *name2 == '\0'));
13414 }
13415 #endif
13416
13417 struct x_display_info *
13418 x_term_init (display_name, xrm_option, resource_name)
13419 Lisp_Object display_name;
13420 char *xrm_option;
13421 char *resource_name;
13422 {
13423 int connection;
13424 Display *dpy;
13425 struct x_display_info *dpyinfo;
13426 XrmDatabase xrdb;
13427
13428 BLOCK_INPUT;
13429
13430 if (!x_initialized)
13431 {
13432 x_initialize ();
13433 x_initialized = 1;
13434 }
13435
13436 #ifdef USE_X_TOOLKIT
13437 /* weiner@footloose.sps.mot.com reports that this causes
13438 errors with X11R5:
13439 X protocol error: BadAtom (invalid Atom parameter)
13440 on protocol request 18skiloaf.
13441 So let's not use it until R6. */
13442 #ifdef HAVE_X11XTR6
13443 XtSetLanguageProc (NULL, NULL, NULL);
13444 #endif
13445
13446 {
13447 int argc = 0;
13448 char *argv[3];
13449
13450 argv[0] = "";
13451 argc = 1;
13452 if (xrm_option)
13453 {
13454 argv[argc++] = "-xrm";
13455 argv[argc++] = xrm_option;
13456 }
13457 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13458 resource_name, EMACS_CLASS,
13459 emacs_options, XtNumber (emacs_options),
13460 &argc, argv);
13461
13462 #ifdef HAVE_X11XTR6
13463 /* I think this is to compensate for XtSetLanguageProc. */
13464 fixup_locale ();
13465 #endif
13466 }
13467
13468 #else /* not USE_X_TOOLKIT */
13469 #ifdef HAVE_X11R5
13470 XSetLocaleModifiers ("");
13471 #endif
13472 dpy = XOpenDisplay (XSTRING (display_name)->data);
13473 #endif /* not USE_X_TOOLKIT */
13474
13475 /* Detect failure. */
13476 if (dpy == 0)
13477 {
13478 UNBLOCK_INPUT;
13479 return 0;
13480 }
13481
13482 /* We have definitely succeeded. Record the new connection. */
13483
13484 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13485 bzero (dpyinfo, sizeof *dpyinfo);
13486
13487 #ifdef MULTI_KBOARD
13488 {
13489 struct x_display_info *share;
13490 Lisp_Object tail;
13491
13492 for (share = x_display_list, tail = x_display_name_list; share;
13493 share = share->next, tail = XCDR (tail))
13494 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13495 XSTRING (display_name)->data))
13496 break;
13497 if (share)
13498 dpyinfo->kboard = share->kboard;
13499 else
13500 {
13501 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13502 init_kboard (dpyinfo->kboard);
13503 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13504 {
13505 char *vendor = ServerVendor (dpy);
13506 UNBLOCK_INPUT;
13507 dpyinfo->kboard->Vsystem_key_alist
13508 = call1 (Qvendor_specific_keysyms,
13509 build_string (vendor ? vendor : ""));
13510 BLOCK_INPUT;
13511 }
13512
13513 dpyinfo->kboard->next_kboard = all_kboards;
13514 all_kboards = dpyinfo->kboard;
13515 /* Don't let the initial kboard remain current longer than necessary.
13516 That would cause problems if a file loaded on startup tries to
13517 prompt in the mini-buffer. */
13518 if (current_kboard == initial_kboard)
13519 current_kboard = dpyinfo->kboard;
13520 }
13521 dpyinfo->kboard->reference_count++;
13522 }
13523 #endif
13524
13525 /* Put this display on the chain. */
13526 dpyinfo->next = x_display_list;
13527 x_display_list = dpyinfo;
13528
13529 /* Put it on x_display_name_list as well, to keep them parallel. */
13530 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13531 x_display_name_list);
13532 dpyinfo->name_list_element = XCAR (x_display_name_list);
13533
13534 dpyinfo->display = dpy;
13535
13536 #if 0
13537 XSetAfterFunction (x_current_display, x_trace_wire);
13538 #endif /* ! 0 */
13539
13540 dpyinfo->x_id_name
13541 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13542 + STRING_BYTES (XSTRING (Vsystem_name))
13543 + 2);
13544 sprintf (dpyinfo->x_id_name, "%s@%s",
13545 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13546
13547 /* Figure out which modifier bits mean what. */
13548 x_find_modifier_meanings (dpyinfo);
13549
13550 /* Get the scroll bar cursor. */
13551 dpyinfo->vertical_scroll_bar_cursor
13552 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13553
13554 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13555 resource_name, EMACS_CLASS);
13556 #ifdef HAVE_XRMSETDATABASE
13557 XrmSetDatabase (dpyinfo->display, xrdb);
13558 #else
13559 dpyinfo->display->db = xrdb;
13560 #endif
13561 /* Put the rdb where we can find it in a way that works on
13562 all versions. */
13563 dpyinfo->xrdb = xrdb;
13564
13565 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13566 DefaultScreen (dpyinfo->display));
13567 select_visual (dpyinfo);
13568 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13569 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13570 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13571 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13572 dpyinfo->grabbed = 0;
13573 dpyinfo->reference_count = 0;
13574 dpyinfo->icon_bitmap_id = -1;
13575 dpyinfo->font_table = NULL;
13576 dpyinfo->n_fonts = 0;
13577 dpyinfo->font_table_size = 0;
13578 dpyinfo->bitmaps = 0;
13579 dpyinfo->bitmaps_size = 0;
13580 dpyinfo->bitmaps_last = 0;
13581 dpyinfo->scratch_cursor_gc = 0;
13582 dpyinfo->mouse_face_mouse_frame = 0;
13583 dpyinfo->mouse_face_deferred_gc = 0;
13584 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13585 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13586 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13587 dpyinfo->mouse_face_window = Qnil;
13588 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13589 dpyinfo->mouse_face_defer = 0;
13590 dpyinfo->x_focus_frame = 0;
13591 dpyinfo->x_focus_event_frame = 0;
13592 dpyinfo->x_highlight_frame = 0;
13593 dpyinfo->image_cache = make_image_cache ();
13594
13595 /* See if a private colormap is requested. */
13596 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13597 {
13598 if (dpyinfo->visual->class == PseudoColor)
13599 {
13600 Lisp_Object value;
13601 value = display_x_get_resource (dpyinfo,
13602 build_string ("privateColormap"),
13603 build_string ("PrivateColormap"),
13604 Qnil, Qnil);
13605 if (STRINGP (value)
13606 && (!strcmp (XSTRING (value)->data, "true")
13607 || !strcmp (XSTRING (value)->data, "on")))
13608 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13609 }
13610 }
13611 else
13612 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13613 dpyinfo->visual, AllocNone);
13614
13615 {
13616 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13617 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13618 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13619 dpyinfo->resy = pixels * 25.4 / mm;
13620 pixels = DisplayWidth (dpyinfo->display, screen_number);
13621 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13622 dpyinfo->resx = pixels * 25.4 / mm;
13623 }
13624
13625 dpyinfo->Xatom_wm_protocols
13626 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13627 dpyinfo->Xatom_wm_take_focus
13628 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13629 dpyinfo->Xatom_wm_save_yourself
13630 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13631 dpyinfo->Xatom_wm_delete_window
13632 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13633 dpyinfo->Xatom_wm_change_state
13634 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13635 dpyinfo->Xatom_wm_configure_denied
13636 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13637 dpyinfo->Xatom_wm_window_moved
13638 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13639 dpyinfo->Xatom_editres
13640 = XInternAtom (dpyinfo->display, "Editres", False);
13641 dpyinfo->Xatom_CLIPBOARD
13642 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13643 dpyinfo->Xatom_TIMESTAMP
13644 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13645 dpyinfo->Xatom_TEXT
13646 = XInternAtom (dpyinfo->display, "TEXT", False);
13647 dpyinfo->Xatom_COMPOUND_TEXT
13648 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13649 dpyinfo->Xatom_DELETE
13650 = XInternAtom (dpyinfo->display, "DELETE", False);
13651 dpyinfo->Xatom_MULTIPLE
13652 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13653 dpyinfo->Xatom_INCR
13654 = XInternAtom (dpyinfo->display, "INCR", False);
13655 dpyinfo->Xatom_EMACS_TMP
13656 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13657 dpyinfo->Xatom_TARGETS
13658 = XInternAtom (dpyinfo->display, "TARGETS", False);
13659 dpyinfo->Xatom_NULL
13660 = XInternAtom (dpyinfo->display, "NULL", False);
13661 dpyinfo->Xatom_ATOM_PAIR
13662 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13663 /* For properties of font. */
13664 dpyinfo->Xatom_PIXEL_SIZE
13665 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13666 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13667 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13668 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13669 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13670 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13671 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13672
13673 /* Ghostscript support. */
13674 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13675 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13676
13677 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13678 False);
13679
13680 dpyinfo->cut_buffers_initialized = 0;
13681
13682 connection = ConnectionNumber (dpyinfo->display);
13683 dpyinfo->connection = connection;
13684
13685 {
13686 char null_bits[1];
13687
13688 null_bits[0] = 0x00;
13689
13690 dpyinfo->null_pixel
13691 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13692 null_bits, 1, 1, (long) 0, (long) 0,
13693 1);
13694 }
13695
13696 {
13697 extern int gray_bitmap_width, gray_bitmap_height;
13698 extern unsigned char *gray_bitmap_bits;
13699 dpyinfo->gray
13700 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13701 gray_bitmap_bits,
13702 gray_bitmap_width, gray_bitmap_height,
13703 (unsigned long) 1, (unsigned long) 0, 1);
13704 }
13705
13706 #ifdef HAVE_X_I18N
13707 xim_initialize (dpyinfo, resource_name);
13708 #endif
13709
13710 #ifdef subprocesses
13711 /* This is only needed for distinguishing keyboard and process input. */
13712 if (connection != 0)
13713 add_keyboard_wait_descriptor (connection);
13714 #endif
13715
13716 #ifndef F_SETOWN_BUG
13717 #ifdef F_SETOWN
13718 #ifdef F_SETOWN_SOCK_NEG
13719 /* stdin is a socket here */
13720 fcntl (connection, F_SETOWN, -getpid ());
13721 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13722 fcntl (connection, F_SETOWN, getpid ());
13723 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13724 #endif /* ! defined (F_SETOWN) */
13725 #endif /* F_SETOWN_BUG */
13726
13727 #ifdef SIGIO
13728 if (interrupt_input)
13729 init_sigio (connection);
13730 #endif /* ! defined (SIGIO) */
13731
13732 #ifdef USE_LUCID
13733 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13734 /* Make sure that we have a valid font for dialog boxes
13735 so that Xt does not crash. */
13736 {
13737 Display *dpy = dpyinfo->display;
13738 XrmValue d, fr, to;
13739 Font font;
13740 int count;
13741
13742 d.addr = (XPointer)&dpy;
13743 d.size = sizeof (Display *);
13744 fr.addr = XtDefaultFont;
13745 fr.size = sizeof (XtDefaultFont);
13746 to.size = sizeof (Font *);
13747 to.addr = (XPointer)&font;
13748 count = x_catch_errors (dpy);
13749 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13750 abort ();
13751 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13752 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13753 x_uncatch_errors (dpy, count);
13754 }
13755 #endif
13756 #endif
13757
13758 /* See if we should run in synchronous mode. This is useful
13759 for debugging X code. */
13760 {
13761 Lisp_Object value;
13762 value = display_x_get_resource (dpyinfo,
13763 build_string ("synchronous"),
13764 build_string ("Synchronous"),
13765 Qnil, Qnil);
13766 if (STRINGP (value)
13767 && (!strcmp (XSTRING (value)->data, "true")
13768 || !strcmp (XSTRING (value)->data, "on")))
13769 XSynchronize (dpyinfo->display, True);
13770 }
13771
13772 UNBLOCK_INPUT;
13773
13774 return dpyinfo;
13775 }
13776 \f
13777 /* Get rid of display DPYINFO, assuming all frames are already gone,
13778 and without sending any more commands to the X server. */
13779
13780 void
13781 x_delete_display (dpyinfo)
13782 struct x_display_info *dpyinfo;
13783 {
13784 delete_keyboard_wait_descriptor (dpyinfo->connection);
13785
13786 /* Discard this display from x_display_name_list and x_display_list.
13787 We can't use Fdelq because that can quit. */
13788 if (! NILP (x_display_name_list)
13789 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13790 x_display_name_list = XCDR (x_display_name_list);
13791 else
13792 {
13793 Lisp_Object tail;
13794
13795 tail = x_display_name_list;
13796 while (CONSP (tail) && CONSP (XCDR (tail)))
13797 {
13798 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13799 {
13800 XCDR (tail) = XCDR (XCDR (tail));
13801 break;
13802 }
13803 tail = XCDR (tail);
13804 }
13805 }
13806
13807 if (next_noop_dpyinfo == dpyinfo)
13808 next_noop_dpyinfo = dpyinfo->next;
13809
13810 if (x_display_list == dpyinfo)
13811 x_display_list = dpyinfo->next;
13812 else
13813 {
13814 struct x_display_info *tail;
13815
13816 for (tail = x_display_list; tail; tail = tail->next)
13817 if (tail->next == dpyinfo)
13818 tail->next = tail->next->next;
13819 }
13820
13821 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13822 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13823 XrmDestroyDatabase (dpyinfo->xrdb);
13824 #endif
13825 #endif
13826 #ifdef MULTI_KBOARD
13827 if (--dpyinfo->kboard->reference_count == 0)
13828 delete_kboard (dpyinfo->kboard);
13829 #endif
13830 #ifdef HAVE_X_I18N
13831 if (dpyinfo->xim)
13832 xim_close_dpy (dpyinfo);
13833 #endif
13834
13835 xfree (dpyinfo->font_table);
13836 xfree (dpyinfo->x_id_name);
13837 xfree (dpyinfo->color_cells);
13838 xfree (dpyinfo);
13839 }
13840
13841 \f
13842 /* Set up use of X before we make the first connection. */
13843
13844 static struct redisplay_interface x_redisplay_interface =
13845 {
13846 x_produce_glyphs,
13847 x_write_glyphs,
13848 x_insert_glyphs,
13849 x_clear_end_of_line,
13850 x_scroll_run,
13851 x_after_update_window_line,
13852 x_update_window_begin,
13853 x_update_window_end,
13854 XTcursor_to,
13855 x_flush,
13856 x_clear_mouse_face,
13857 x_get_glyph_overhangs,
13858 x_fix_overlapping_area
13859 };
13860
13861 void
13862 x_initialize ()
13863 {
13864 rif = &x_redisplay_interface;
13865
13866 clear_frame_hook = x_clear_frame;
13867 ins_del_lines_hook = x_ins_del_lines;
13868 change_line_highlight_hook = x_change_line_highlight;
13869 delete_glyphs_hook = x_delete_glyphs;
13870 ring_bell_hook = XTring_bell;
13871 reset_terminal_modes_hook = XTreset_terminal_modes;
13872 set_terminal_modes_hook = XTset_terminal_modes;
13873 update_begin_hook = x_update_begin;
13874 update_end_hook = x_update_end;
13875 set_terminal_window_hook = XTset_terminal_window;
13876 read_socket_hook = XTread_socket;
13877 frame_up_to_date_hook = XTframe_up_to_date;
13878 reassert_line_highlight_hook = XTreassert_line_highlight;
13879 mouse_position_hook = XTmouse_position;
13880 frame_rehighlight_hook = XTframe_rehighlight;
13881 frame_raise_lower_hook = XTframe_raise_lower;
13882 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13883 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13884 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13885 judge_scroll_bars_hook = XTjudge_scroll_bars;
13886 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13887
13888 scroll_region_ok = 1; /* we'll scroll partial frames */
13889 char_ins_del_ok = 0; /* just as fast to write the line */
13890 line_ins_del_ok = 1; /* we'll just blt 'em */
13891 fast_clear_end_of_line = 1; /* X does this well */
13892 memory_below_frame = 0; /* we don't remember what scrolls
13893 off the bottom */
13894 baud_rate = 19200;
13895
13896 x_noop_count = 0;
13897 last_tool_bar_item = -1;
13898 any_help_event_p = 0;
13899
13900 /* Try to use interrupt input; if we can't, then start polling. */
13901 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13902
13903 #ifdef USE_X_TOOLKIT
13904 XtToolkitInitialize ();
13905 Xt_app_con = XtCreateApplicationContext ();
13906 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13907
13908 /* Install an asynchronous timer that processes Xt timeout events
13909 every 0.1s. This is necessary because some widget sets use
13910 timeouts internally, for example the LessTif menu bar, or the
13911 Xaw3d scroll bar. When Xt timouts aren't processed, these
13912 widgets don't behave normally. */
13913 {
13914 EMACS_TIME interval;
13915 EMACS_SET_SECS_USECS (interval, 0, 100000);
13916 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13917 }
13918 #endif
13919
13920 #if USE_TOOLKIT_SCROLL_BARS
13921 xaw3d_arrow_scroll = False;
13922 xaw3d_pick_top = True;
13923 #endif
13924
13925 /* Note that there is no real way portable across R3/R4 to get the
13926 original error handler. */
13927 XSetErrorHandler (x_error_handler);
13928 XSetIOErrorHandler (x_io_error_quitter);
13929
13930 /* Disable Window Change signals; they are handled by X events. */
13931 #ifdef SIGWINCH
13932 signal (SIGWINCH, SIG_DFL);
13933 #endif /* ! defined (SIGWINCH) */
13934
13935 signal (SIGPIPE, x_connection_signal);
13936 }
13937
13938
13939 void
13940 syms_of_xterm ()
13941 {
13942 staticpro (&x_error_message_string);
13943 x_error_message_string = Qnil;
13944
13945 staticpro (&x_display_name_list);
13946 x_display_name_list = Qnil;
13947
13948 staticpro (&last_mouse_scroll_bar);
13949 last_mouse_scroll_bar = Qnil;
13950
13951 staticpro (&Qvendor_specific_keysyms);
13952 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13953
13954 staticpro (&last_mouse_press_frame);
13955 last_mouse_press_frame = Qnil;
13956
13957 help_echo = Qnil;
13958 staticpro (&help_echo);
13959 help_echo_object = Qnil;
13960 staticpro (&help_echo_object);
13961 help_echo_window = Qnil;
13962 staticpro (&help_echo_window);
13963 previous_help_echo = Qnil;
13964 staticpro (&previous_help_echo);
13965 help_echo_pos = -1;
13966
13967 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13968 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13969 For example, if a block cursor is over a tab, it will be drawn as\n\
13970 wide as that tab on the display.");
13971 x_stretch_cursor_p = 0;
13972
13973 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13974 "If not nil, Emacs uses toolkit scroll bars.");
13975 #if USE_TOOLKIT_SCROLL_BARS
13976 x_toolkit_scroll_bars_p = 1;
13977 #else
13978 x_toolkit_scroll_bars_p = 0;
13979 #endif
13980
13981 staticpro (&last_mouse_motion_frame);
13982 last_mouse_motion_frame = Qnil;
13983 }
13984
13985 #endif /* not HAVE_X_WINDOWS */