(XTread_socket) <ClientMessage, Xatom_Scrollbar>:
[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
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 #ifndef USG
48 /* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */
50 #ifndef makedev
51 #include <sys/types.h>
52 #endif /* makedev */
53 #endif /* USG */
54
55 #ifdef BSD_SYSTEM
56 #include <sys/ioctl.h>
57 #endif /* ! defined (BSD_SYSTEM) */
58
59 #include "systty.h"
60 #include "systime.h"
61
62 #ifndef INCLUDED_FCNTL
63 #include <fcntl.h>
64 #endif
65 #include <ctype.h>
66 #include <errno.h>
67 #include <setjmp.h>
68 #include <sys/stat.h>
69 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
70 /* #include <sys/param.h> */
71
72 #include "charset.h"
73 #include "ccl.h"
74 #include "frame.h"
75 #include "fontset.h"
76 #include "dispextern.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #if 0
81 #include "sink.h"
82 #include "sinkmask.h"
83 #endif /* ! 0 */
84 #include "gnu.h"
85 #include "disptab.h"
86 #include "buffer.h"
87 #include "window.h"
88 #include "keyboard.h"
89 #include "intervals.h"
90 #include "process.h"
91
92 #ifdef USE_X_TOOLKIT
93 #include <X11/Shell.h>
94 #endif
95
96 #include <sys/types.h>
97 #ifdef HAVE_SYS_TIME_H
98 #include <sys/time.h>
99 #endif
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
103
104 #ifdef USE_X_TOOLKIT
105
106 extern void free_frame_menubar ();
107 extern FRAME_PTR x_menubar_window_to_frame ();
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 #elif defined HAVE_XAW3D
122 #include <X11/Xaw3d/Simple.h>
123 #include <X11/Xaw3d/ThreeD.h>
124 #include <X11/Xaw3d/Scrollbar.h>
125 #define ARROW_SCROLLBAR
126 #include <X11/Xaw3d/ScrollbarP.h>
127 #endif /* HAVE_XAW3D */
128 #endif /* USE_TOOLKIT_SCROLL_BARS */
129
130 #endif /* USE_X_TOOLKIT */
131
132 #ifndef USE_X_TOOLKIT
133 #define x_any_window_to_frame x_window_to_frame
134 #define x_top_window_to_frame x_window_to_frame
135 #endif
136
137 #ifdef USE_X_TOOLKIT
138 #include "widget.h"
139 #ifndef XtNinitialState
140 #define XtNinitialState "initialState"
141 #endif
142 #endif
143
144 #ifdef SOLARIS2
145 /* memmove will be defined as a macro in Xfuncs.h unless
146 <string.h> is included beforehand. The declaration for memmove in
147 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
148 #include <string.h>
149 #endif
150
151 #ifndef min
152 #define min(a,b) ((a) < (b) ? (a) : (b))
153 #endif
154 #ifndef max
155 #define max(a,b) ((a) > (b) ? (a) : (b))
156 #endif
157
158 #define abs(x) ((x) < 0 ? -(x) : (x))
159
160 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
161
162 \f
163 /* Bitmaps for truncated lines. */
164
165 enum bitmap_type
166 {
167 NO_BITMAP,
168 LEFT_TRUNCATION_BITMAP,
169 RIGHT_TRUNCATION_BITMAP,
170 OVERLAY_ARROW_BITMAP,
171 CONTINUED_LINE_BITMAP,
172 CONTINUATION_LINE_BITMAP,
173 ZV_LINE_BITMAP
174 };
175
176 /* Bitmap drawn to indicate lines not displaying text if
177 `indicate-empty-lines' is non-nil. */
178
179 #define zv_width 8
180 #define zv_height 8
181 static unsigned char zv_bits[] = {
182 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
183
184 /* An arrow like this: `<-'. */
185
186 #define left_width 8
187 #define left_height 8
188 static unsigned char left_bits[] = {
189 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
190
191 /* Right truncation arrow bitmap `->'. */
192
193 #define right_width 8
194 #define right_height 8
195 static unsigned char right_bits[] = {
196 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
197
198 /* Marker for continued lines. */
199
200 #define continued_width 8
201 #define continued_height 8
202 static unsigned char continued_bits[] = {
203 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
204
205 /* Marker for continuation lines. */
206
207 #define continuation_width 8
208 #define continuation_height 8
209 static unsigned char continuation_bits[] = {
210 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
211
212 /* Overlay arrow bitmap. */
213
214 #if 0
215 /* A bomb. */
216 #define ov_width 8
217 #define ov_height 8
218 static unsigned char ov_bits[] = {
219 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
220 #else
221 /* A triangular arrow. */
222 #define ov_width 8
223 #define ov_height 8
224 static unsigned char ov_bits[] = {
225 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
226
227 #endif
228
229 extern Lisp_Object Qhelp_echo;
230
231 \f
232 /* Non-zero means Emacs uses toolkit scroll bars. */
233
234 int x_toolkit_scroll_bars_p;
235
236 /* If a string, XTread_socket generates an event to display that string.
237 (The display is done in read_char.) */
238
239 static Lisp_Object help_echo;
240
241 /* Temporary variable for XTread_socket. */
242
243 static Lisp_Object previous_help_echo;
244
245 /* Non-zero means that a HELP_EVENT has been generated since Emacs
246 start. */
247
248 static int any_help_event_p;
249
250 /* Non-zero means draw block and hollow cursor as wide as the glyph
251 under it. For example, if a block cursor is over a tab, it will be
252 drawn as wide as that tab on the display. */
253
254 int x_stretch_cursor_p;
255
256 /* This is a chain of structures for all the X displays currently in
257 use. */
258
259 struct x_display_info *x_display_list;
260
261 /* This is a list of cons cells, each of the form (NAME
262 . FONT-LIST-CACHE), one for each element of x_display_list and in
263 the same order. NAME is the name of the frame. FONT-LIST-CACHE
264 records previous values returned by x-list-fonts. */
265
266 Lisp_Object x_display_name_list;
267
268 /* Frame being updated by update_frame. This is declared in term.c.
269 This is set by update_begin and looked at by all the XT functions.
270 It is zero while not inside an update. In that case, the XT
271 functions assume that `selected_frame' is the frame to apply to. */
272
273 extern struct frame *updating_frame;
274
275 extern int waiting_for_input;
276
277 /* This is a frame waiting to be auto-raised, within XTread_socket. */
278
279 struct frame *pending_autoraise_frame;
280
281 #ifdef USE_X_TOOLKIT
282 /* The application context for Xt use. */
283 XtAppContext Xt_app_con;
284 static String Xt_default_resources[] = {0};
285 #endif /* USE_X_TOOLKIT */
286
287 /* Nominal cursor position -- where to draw output.
288 HPOS and VPOS are window relative glyph matrix coordinates.
289 X and Y are window relative pixel coordinates. */
290
291 struct cursor_pos output_cursor;
292
293
294 /* Mouse movement.
295
296 Formerly, we used PointerMotionHintMask (in standard_event_mask)
297 so that we would have to call XQueryPointer after each MotionNotify
298 event to ask for another such event. However, this made mouse tracking
299 slow, and there was a bug that made it eventually stop.
300
301 Simply asking for MotionNotify all the time seems to work better.
302
303 In order to avoid asking for motion events and then throwing most
304 of them away or busy-polling the server for mouse positions, we ask
305 the server for pointer motion hints. This means that we get only
306 one event per group of mouse movements. "Groups" are delimited by
307 other kinds of events (focus changes and button clicks, for
308 example), or by XQueryPointer calls; when one of these happens, we
309 get another MotionNotify event the next time the mouse moves. This
310 is at least as efficient as getting motion events when mouse
311 tracking is on, and I suspect only negligibly worse when tracking
312 is off. */
313
314 /* Where the mouse was last time we reported a mouse event. */
315
316 FRAME_PTR last_mouse_frame;
317 static XRectangle last_mouse_glyph;
318 static Lisp_Object last_mouse_press_frame;
319
320 /* The scroll bar in which the last X motion event occurred.
321
322 If the last X motion event occurred in a scroll bar, we set this so
323 XTmouse_position can know whether to report a scroll bar motion or
324 an ordinary motion.
325
326 If the last X motion event didn't occur in a scroll bar, we set
327 this to Qnil, to tell XTmouse_position to return an ordinary motion
328 event. */
329
330 static Lisp_Object last_mouse_scroll_bar;
331
332 /* This is a hack. We would really prefer that XTmouse_position would
333 return the time associated with the position it returns, but there
334 doesn't seem to be any way to wrest the time-stamp from the server
335 along with the position query. So, we just keep track of the time
336 of the last movement we received, and return that in hopes that
337 it's somewhat accurate. */
338
339 static Time last_mouse_movement_time;
340
341 /* Incremented by XTread_socket whenever it really tries to read
342 events. */
343
344 #ifdef __STDC__
345 static int volatile input_signal_count;
346 #else
347 static int input_signal_count;
348 #endif
349
350 /* Used locally within XTread_socket. */
351
352 static int x_noop_count;
353
354 /* Initial values of argv and argc. */
355
356 extern char **initial_argv;
357 extern int initial_argc;
358
359 extern Lisp_Object Vcommand_line_args, Vsystem_name;
360
361 /* Tells if a window manager is present or not. */
362
363 extern Lisp_Object Vx_no_window_manager;
364
365 extern Lisp_Object Qface, Qmouse_face;
366
367 extern int errno;
368
369 /* A mask of extra modifier bits to put into every keyboard char. */
370
371 extern int extra_keyboard_modifiers;
372
373 static Lisp_Object Qvendor_specific_keysyms;
374
375 extern XrmDatabase x_load_resources ();
376 extern Lisp_Object x_icon_type ();
377
378
379 /* Enumeration for overriding/changing the face to use for drawing
380 glyphs in x_draw_glyphs. */
381
382 enum draw_glyphs_face
383 {
384 DRAW_NORMAL_TEXT,
385 DRAW_INVERSE_VIDEO,
386 DRAW_CURSOR,
387 DRAW_MOUSE_FACE,
388 DRAW_IMAGE_RAISED,
389 DRAW_IMAGE_SUNKEN
390 };
391
392 static void x_update_window_end P_ ((struct window *, int));
393 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
394 void x_delete_display P_ ((struct x_display_info *));
395 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
396 unsigned));
397 static int fast_find_position P_ ((struct window *, int, int *, int *,
398 int *, int *));
399 static void set_output_cursor P_ ((struct cursor_pos *));
400 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
401 int *, int *, int *));
402 static void note_mode_line_highlight P_ ((struct window *, int, int));
403 static void x_check_font P_ ((struct frame *, XFontStruct *));
404 static void note_mouse_highlight P_ ((struct frame *, int, int));
405 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
406 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
407 static void show_mouse_face P_ ((struct x_display_info *,
408 enum draw_glyphs_face));
409 static int x_io_error_quitter P_ ((Display *));
410 int x_catch_errors P_ ((Display *));
411 void x_uncatch_errors P_ ((Display *, int));
412 void x_lower_frame P_ ((struct frame *));
413 void x_scroll_bar_clear P_ ((struct frame *));
414 int x_had_errors_p P_ ((Display *));
415 void x_wm_set_size_hint P_ ((struct frame *, long, int));
416 void x_raise_frame P_ ((struct frame *));
417 void x_set_window_size P_ ((struct frame *, int, int, int));
418 void x_wm_set_window_state P_ ((struct frame *, int));
419 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
420 void x_initialize P_ ((void));
421 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
422 static int x_compute_min_glyph_bounds P_ ((struct frame *));
423 static void x_draw_phys_cursor_glyph P_ ((struct window *,
424 struct glyph_row *,
425 enum draw_glyphs_face));
426 static void x_update_end P_ ((struct frame *));
427 static void XTframe_up_to_date P_ ((struct frame *));
428 static void XTreassert_line_highlight P_ ((int, int));
429 static void x_change_line_highlight P_ ((int, int, int, int));
430 static void XTset_terminal_modes P_ ((void));
431 static void XTreset_terminal_modes P_ ((void));
432 static void XTcursor_to P_ ((int, int, int, int));
433 static void x_write_glyphs P_ ((struct glyph *, int));
434 static void x_clear_end_of_line P_ ((int));
435 static void x_clear_frame P_ ((void));
436 static void x_clear_cursor P_ ((struct window *));
437 static void frame_highlight P_ ((struct frame *));
438 static void frame_unhighlight P_ ((struct frame *));
439 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
440 static void XTframe_rehighlight P_ ((struct frame *));
441 static void x_frame_rehighlight P_ ((struct x_display_info *));
442 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
443 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
444 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
445 XRectangle *));
446 static void expose_frame P_ ((struct frame *, int, int, int, int));
447 static void expose_window_tree P_ ((struct window *, XRectangle *));
448 static void expose_window P_ ((struct window *, XRectangle *));
449 static void expose_area P_ ((struct window *, struct glyph_row *,
450 XRectangle *, enum glyph_row_area));
451 static void expose_line P_ ((struct window *, struct glyph_row *,
452 XRectangle *));
453 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
454 static void x_update_window_cursor P_ ((struct window *, int));
455 static void x_erase_phys_cursor P_ ((struct window *));
456 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
457 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
458 enum bitmap_type));
459
460 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
461 GC, int));
462 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
463 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
464 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
465 static void x_flush P_ ((struct frame *f));
466
467
468 /* Flush display of frame F, or of all frames if F is null. */
469
470 static void
471 x_flush (f)
472 struct frame *f;
473 {
474 BLOCK_INPUT;
475 if (f == NULL)
476 {
477 Lisp_Object rest, frame;
478 FOR_EACH_FRAME (rest, frame)
479 x_flush (XFRAME (frame));
480 }
481 else if (FRAME_X_P (f))
482 XFlush (FRAME_X_DISPLAY (f));
483 UNBLOCK_INPUT;
484 }
485
486
487 /* Remove calls to XFlush by defining XFlush to an empty replacement.
488 Calls to XFlush should be unnecessary because the X output buffer
489 is flushed automatically as needed by calls to XPending,
490 XNextEvent, or XWindowEvent according to the XFlush man page.
491 XTread_socket calls XPending. Removing XFlush improves
492 performance. */
493
494 #define XFlush(DISPLAY) (void) 0
495
496 \f
497 /***********************************************************************
498 Debugging
499 ***********************************************************************/
500
501 #if 0
502
503 /* This is a function useful for recording debugging information about
504 the sequence of occurrences in this file. */
505
506 struct record
507 {
508 char *locus;
509 int type;
510 };
511
512 struct record event_record[100];
513
514 int event_record_index;
515
516 record_event (locus, type)
517 char *locus;
518 int type;
519 {
520 if (event_record_index == sizeof (event_record) / sizeof (struct record))
521 event_record_index = 0;
522
523 event_record[event_record_index].locus = locus;
524 event_record[event_record_index].type = type;
525 event_record_index++;
526 }
527
528 #endif /* 0 */
529
530
531 \f
532 /* Return the struct x_display_info corresponding to DPY. */
533
534 struct x_display_info *
535 x_display_info_for_display (dpy)
536 Display *dpy;
537 {
538 struct x_display_info *dpyinfo;
539
540 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
541 if (dpyinfo->display == dpy)
542 return dpyinfo;
543
544 return 0;
545 }
546
547
548 \f
549 /***********************************************************************
550 Starting and ending an update
551 ***********************************************************************/
552
553 /* Start an update of frame F. This function is installed as a hook
554 for update_begin, i.e. it is called when update_begin is called.
555 This function is called prior to calls to x_update_window_begin for
556 each window being updated. Currently, there is nothing to do here
557 because all interesting stuff is done on a window basis. */
558
559 static void
560 x_update_begin (f)
561 struct frame *f;
562 {
563 /* Nothing to do. */
564 }
565
566
567 /* Start update of window W. Set the global variable updated_window
568 to the window being updated and set output_cursor to the cursor
569 position of W. */
570
571 static void
572 x_update_window_begin (w)
573 struct window *w;
574 {
575 struct frame *f = XFRAME (WINDOW_FRAME (w));
576 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
577
578 updated_window = w;
579 set_output_cursor (&w->cursor);
580
581 BLOCK_INPUT;
582
583 if (f == display_info->mouse_face_mouse_frame)
584 {
585 /* Don't do highlighting for mouse motion during the update. */
586 display_info->mouse_face_defer = 1;
587
588 /* If F needs to be redrawn, simply forget about any prior mouse
589 highlighting. */
590 if (FRAME_GARBAGED_P (f))
591 display_info->mouse_face_window = Qnil;
592
593 /* Can we tell that this update does not affect the window
594 where the mouse highlight is? If so, no need to turn off.
595 Likewise, don't do anything if the frame is garbaged;
596 in that case, the frame's current matrix that we would use
597 is all wrong, and we will redisplay that line anyway. */
598 if (!NILP (display_info->mouse_face_window)
599 && w == XWINDOW (display_info->mouse_face_window))
600 {
601 int i;
602
603 for (i = 0; i < w->desired_matrix->nrows; ++i)
604 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
605 break;
606
607 if (i < w->desired_matrix->nrows)
608 clear_mouse_face (display_info);
609 }
610 }
611
612 UNBLOCK_INPUT;
613 }
614
615
616 /* Draw a vertical window border to the right of window W if W doesn't
617 have vertical scroll bars. */
618
619 static void
620 x_draw_vertical_border (w)
621 struct window *w;
622 {
623 struct frame *f = XFRAME (WINDOW_FRAME (w));
624
625 /* Redraw borders between horizontally adjacent windows. Don't
626 do it for frames with vertical scroll bars because either the
627 right scroll bar of a window, or the left scroll bar of its
628 neighbor will suffice as a border. */
629 if (!WINDOW_RIGHTMOST_P (w)
630 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
631 {
632 int x0, x1, y0, y1;
633
634 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
635 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
636 y1 -= 1;
637
638 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
639 f->output_data.x->normal_gc, x1, y0, x1, y1);
640 }
641 }
642
643
644 /* End update of window W (which is equal to updated_window). Draw
645 vertical borders between horizontally adjacent windows, and display
646 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
647 pseudo-window in case we don't have X toolkit support. Such
648 windows don't have a cursor, so don't display it here. */
649
650 static void
651 x_update_window_end (w, cursor_on_p)
652 struct window *w;
653 int cursor_on_p;
654 {
655 if (!w->pseudo_window_p)
656 {
657 BLOCK_INPUT;
658 if (cursor_on_p)
659 x_display_and_set_cursor (w, 1, output_cursor.hpos,
660 output_cursor.vpos,
661 output_cursor.x, output_cursor.y);
662 x_draw_vertical_border (w);
663 UNBLOCK_INPUT;
664 }
665
666 updated_window = NULL;
667 }
668
669
670 /* End update of frame F. This function is installed as a hook in
671 update_end. */
672
673 static void
674 x_update_end (f)
675 struct frame *f;
676 {
677 /* Mouse highlight may be displayed again. */
678 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
679
680 BLOCK_INPUT;
681 XFlush (FRAME_X_DISPLAY (f));
682 UNBLOCK_INPUT;
683 }
684
685
686 /* This function is called from various places in xdisp.c whenever a
687 complete update has been performed. The global variable
688 updated_window is not available here. */
689
690 static void
691 XTframe_up_to_date (f)
692 struct frame *f;
693 {
694 if (FRAME_X_P (f))
695 {
696 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
697 if (dpyinfo->mouse_face_deferred_gc
698 || f == dpyinfo->mouse_face_mouse_frame)
699 {
700 BLOCK_INPUT;
701 if (dpyinfo->mouse_face_mouse_frame)
702 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
703 dpyinfo->mouse_face_mouse_x,
704 dpyinfo->mouse_face_mouse_y);
705 dpyinfo->mouse_face_deferred_gc = 0;
706 UNBLOCK_INPUT;
707 }
708 }
709 }
710
711
712 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
713 arrow bitmaps, or clear the areas where they would be displayed
714 before DESIRED_ROW is made current. The window being updated is
715 found in updated_window. This function It is called from
716 update_window_line only if it is known that there are differences
717 between bitmaps to be drawn between current row and DESIRED_ROW. */
718
719 static void
720 x_after_update_window_line (desired_row)
721 struct glyph_row *desired_row;
722 {
723 struct window *w = updated_window;
724
725 xassert (w);
726
727 if (!desired_row->mode_line_p && !w->pseudo_window_p)
728 {
729 BLOCK_INPUT;
730 x_draw_row_bitmaps (w, desired_row);
731
732 /* When a window has disappeared, make sure that no rest of
733 full-width rows stays visible in the internal border. */
734 if (windows_or_buffers_changed)
735 {
736 struct frame *f = XFRAME (w->frame);
737 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
738 int height = desired_row->visible_height;
739 int x = (window_box_right (w, -1)
740 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
741 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
742
743 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
744 x, y, width, height, False);
745 }
746
747 UNBLOCK_INPUT;
748 }
749 }
750
751
752 /* Draw the bitmap WHICH in one of the areas to the left or right of
753 window W. ROW is the glyph row for which to display the bitmap; it
754 determines the vertical position at which the bitmap has to be
755 drawn. */
756
757 static void
758 x_draw_bitmap (w, row, which)
759 struct window *w;
760 struct glyph_row *row;
761 enum bitmap_type which;
762 {
763 struct frame *f = XFRAME (WINDOW_FRAME (w));
764 Display *display = FRAME_X_DISPLAY (f);
765 Window window = FRAME_X_WINDOW (f);
766 int x, y, wd, h, dy;
767 unsigned char *bits;
768 Pixmap pixmap;
769 GC gc = f->output_data.x->normal_gc;
770 struct face *face;
771 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
772
773 /* Must clip because of partially visible lines. */
774 x_clip_to_row (w, row, gc, 1);
775
776 switch (which)
777 {
778 case LEFT_TRUNCATION_BITMAP:
779 wd = left_width;
780 h = left_height;
781 bits = left_bits;
782 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
783 - wd
784 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
785 break;
786
787 case OVERLAY_ARROW_BITMAP:
788 wd = left_width;
789 h = left_height;
790 bits = ov_bits;
791 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
792 - wd
793 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
794 break;
795
796 case RIGHT_TRUNCATION_BITMAP:
797 wd = right_width;
798 h = right_height;
799 bits = right_bits;
800 x = window_box_right (w, -1);
801 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
802 break;
803
804 case CONTINUED_LINE_BITMAP:
805 wd = right_width;
806 h = right_height;
807 bits = continued_bits;
808 x = window_box_right (w, -1);
809 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
810 break;
811
812 case CONTINUATION_LINE_BITMAP:
813 wd = continuation_width;
814 h = continuation_height;
815 bits = continuation_bits;
816 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
817 - wd
818 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
819 break;
820
821 case ZV_LINE_BITMAP:
822 wd = zv_width;
823 h = zv_height;
824 bits = zv_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 default:
831 abort ();
832 }
833
834 /* Convert to frame coordinates. Set dy to the offset in the row to
835 start drawing the bitmap. */
836 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
837 dy = (row->height - h) / 2;
838
839 /* Draw the bitmap. I believe these small pixmaps can be cached
840 by the server. */
841 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
842 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
843 face->foreground,
844 face->background, depth);
845 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
846 XFreePixmap (display, pixmap);
847 XSetClipMask (display, gc, None);
848 }
849
850
851 /* Draw flags bitmaps for glyph row ROW on window W. Call this
852 function with input blocked. */
853
854 static void
855 x_draw_row_bitmaps (w, row)
856 struct window *w;
857 struct glyph_row *row;
858 {
859 struct frame *f = XFRAME (w->frame);
860 enum bitmap_type bitmap;
861 struct face *face;
862 int header_line_height = -1;
863
864 xassert (interrupt_input_blocked);
865
866 /* If row is completely invisible, because of vscrolling, we
867 don't have to draw anything. */
868 if (row->visible_height <= 0)
869 return;
870
871 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
872 PREPARE_FACE_FOR_DISPLAY (f, face);
873
874 /* Decide which bitmap to draw at the left side. */
875 if (row->overlay_arrow_p)
876 bitmap = OVERLAY_ARROW_BITMAP;
877 else if (row->truncated_on_left_p)
878 bitmap = LEFT_TRUNCATION_BITMAP;
879 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
880 bitmap = CONTINUATION_LINE_BITMAP;
881 else if (row->indicate_empty_line_p)
882 bitmap = ZV_LINE_BITMAP;
883 else
884 bitmap = NO_BITMAP;
885
886 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
887 the flags area. */
888 if (bitmap == NO_BITMAP
889 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
890 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
891 {
892 /* If W has a vertical border to its left, don't draw over it. */
893 int border = ((XFASTINT (w->left) > 0
894 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
895 ? 1 : 0);
896 int left = window_box_left (w, -1);
897
898 if (header_line_height < 0)
899 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
900
901 /* In case the same realized face is used for bitmap areas and
902 for something displayed in the text (e.g. face `region' on
903 mono-displays, the fill style may have been changed to
904 FillSolid in x_draw_glyph_string_background. */
905 if (face->stipple)
906 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
907 else
908 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
909
910 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
911 face->gc,
912 (left
913 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
914 + border),
915 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
916 row->y)),
917 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
918 row->visible_height);
919 if (!face->stipple)
920 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
921 }
922
923 /* Draw the left bitmap. */
924 if (bitmap != NO_BITMAP)
925 x_draw_bitmap (w, row, bitmap);
926
927 /* Decide which bitmap to draw at the right side. */
928 if (row->truncated_on_right_p)
929 bitmap = RIGHT_TRUNCATION_BITMAP;
930 else if (row->continued_p)
931 bitmap = CONTINUED_LINE_BITMAP;
932 else
933 bitmap = NO_BITMAP;
934
935 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
936 the flags area. */
937 if (bitmap == NO_BITMAP
938 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
939 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
940 {
941 int right = window_box_right (w, -1);
942
943 if (header_line_height < 0)
944 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
945
946 /* In case the same realized face is used for bitmap areas and
947 for something displayed in the text (e.g. face `region' on
948 mono-displays, the fill style may have been changed to
949 FillSolid in x_draw_glyph_string_background. */
950 if (face->stipple)
951 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
952 else
953 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
954 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
955 face->gc,
956 right,
957 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
958 row->y)),
959 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
960 row->visible_height);
961 if (!face->stipple)
962 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
963 }
964
965 /* Draw the right bitmap. */
966 if (bitmap != NO_BITMAP)
967 x_draw_bitmap (w, row, bitmap);
968 }
969
970 \f
971 /***********************************************************************
972 Line Highlighting
973 ***********************************************************************/
974
975 /* External interface to control of standout mode. Not used for X
976 frames. Aborts when called. */
977
978 static void
979 XTreassert_line_highlight (new, vpos)
980 int new, vpos;
981 {
982 abort ();
983 }
984
985
986 /* Call this when about to modify line at position VPOS and change
987 whether it is highlighted. Not used for X frames. Aborts when
988 called. */
989
990 static void
991 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
992 int new_highlight, vpos, y, first_unused_hpos;
993 {
994 abort ();
995 }
996
997
998 /* This is called when starting Emacs and when restarting after
999 suspend. When starting Emacs, no X window is mapped. And nothing
1000 must be done to Emacs's own window if it is suspended (though that
1001 rarely happens). */
1002
1003 static void
1004 XTset_terminal_modes ()
1005 {
1006 }
1007
1008 /* This is called when exiting or suspending Emacs. Exiting will make
1009 the X-windows go away, and suspending requires no action. */
1010
1011 static void
1012 XTreset_terminal_modes ()
1013 {
1014 }
1015
1016
1017 \f
1018 /***********************************************************************
1019 Output Cursor
1020 ***********************************************************************/
1021
1022 /* Set the global variable output_cursor to CURSOR. All cursor
1023 positions are relative to updated_window. */
1024
1025 static void
1026 set_output_cursor (cursor)
1027 struct cursor_pos *cursor;
1028 {
1029 output_cursor.hpos = cursor->hpos;
1030 output_cursor.vpos = cursor->vpos;
1031 output_cursor.x = cursor->x;
1032 output_cursor.y = cursor->y;
1033 }
1034
1035
1036 /* Set a nominal cursor position.
1037
1038 HPOS and VPOS are column/row positions in a window glyph matrix. X
1039 and Y are window text area relative pixel positions.
1040
1041 If this is done during an update, updated_window will contain the
1042 window that is being updated and the position is the future output
1043 cursor position for that window. If updated_window is null, use
1044 selected_window and display the cursor at the given position. */
1045
1046 static void
1047 XTcursor_to (vpos, hpos, y, x)
1048 int vpos, hpos, y, x;
1049 {
1050 struct window *w;
1051
1052 /* If updated_window is not set, work on selected_window. */
1053 if (updated_window)
1054 w = updated_window;
1055 else
1056 w = XWINDOW (selected_window);
1057
1058 /* Set the output cursor. */
1059 output_cursor.hpos = hpos;
1060 output_cursor.vpos = vpos;
1061 output_cursor.x = x;
1062 output_cursor.y = y;
1063
1064 /* If not called as part of an update, really display the cursor.
1065 This will also set the cursor position of W. */
1066 if (updated_window == NULL)
1067 {
1068 BLOCK_INPUT;
1069 x_display_cursor (w, 1, hpos, vpos, x, y);
1070 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1071 UNBLOCK_INPUT;
1072 }
1073 }
1074
1075
1076 \f
1077 /***********************************************************************
1078 Display Iterator
1079 ***********************************************************************/
1080
1081 /* Function prototypes of this page. */
1082
1083 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1084 struct glyph *,
1085 XChar2b *));
1086 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1087 int, XChar2b *, int));
1088 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1089 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1090 static void x_append_glyph P_ ((struct it *));
1091 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1092 int, int, double));
1093 static void x_produce_glyphs P_ ((struct it *));
1094 static void x_produce_image_glyph P_ ((struct it *it));
1095
1096
1097 /* Return a pointer to per-char metric information in FONT of a
1098 character pointed by B which is a pointer to an XChar2b. */
1099
1100 #define PER_CHAR_METRIC(font, b) \
1101 ((font)->per_char \
1102 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1103 + (((font)->min_byte1 || (font)->max_byte1) \
1104 ? (((b)->byte1 - (font)->min_byte1) \
1105 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1106 : 0)) \
1107 : &((font)->max_bounds))
1108
1109
1110 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1111 If CHAR2B is not contained in FONT, the font's default character
1112 metric is returned. */
1113
1114 static INLINE XCharStruct *
1115 x_per_char_metric (font, char2b)
1116 XFontStruct *font;
1117 XChar2b *char2b;
1118 {
1119 /* The result metric information. */
1120 XCharStruct *pcm = NULL;
1121
1122 xassert (font && char2b);
1123
1124 if (font->per_char != NULL)
1125 {
1126 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1127 {
1128 /* min_char_or_byte2 specifies the linear character index
1129 corresponding to the first element of the per_char array,
1130 max_char_or_byte2 is the index of the last character. A
1131 character with non-zero CHAR2B->byte1 is not in the font.
1132 A character with byte2 less than min_char_or_byte2 or
1133 greater max_char_or_byte2 is not in the font. */
1134 if (char2b->byte1 == 0
1135 && char2b->byte2 >= font->min_char_or_byte2
1136 && char2b->byte2 <= font->max_char_or_byte2)
1137 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1138 }
1139 else
1140 {
1141 /* If either min_byte1 or max_byte1 are nonzero, both
1142 min_char_or_byte2 and max_char_or_byte2 are less than
1143 256, and the 2-byte character index values corresponding
1144 to the per_char array element N (counting from 0) are:
1145
1146 byte1 = N/D + min_byte1
1147 byte2 = N\D + min_char_or_byte2
1148
1149 where:
1150
1151 D = max_char_or_byte2 - min_char_or_byte2 + 1
1152 / = integer division
1153 \ = integer modulus */
1154 if (char2b->byte1 >= font->min_byte1
1155 && char2b->byte1 <= font->max_byte1
1156 && char2b->byte2 >= font->min_char_or_byte2
1157 && char2b->byte2 <= font->max_char_or_byte2)
1158 {
1159 pcm = (font->per_char
1160 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1161 * (char2b->byte1 - font->min_byte1))
1162 + (char2b->byte2 - font->min_char_or_byte2));
1163 }
1164 }
1165 }
1166 else
1167 {
1168 /* If the per_char pointer is null, all glyphs between the first
1169 and last character indexes inclusive have the same
1170 information, as given by both min_bounds and max_bounds. */
1171 if (char2b->byte2 >= font->min_char_or_byte2
1172 && char2b->byte2 <= font->max_char_or_byte2)
1173 pcm = &font->max_bounds;
1174 }
1175
1176
1177 if (pcm == NULL || pcm->width == 0)
1178 {
1179 /* Character not contained in the font. FONT->default_char
1180 gives the character that will be printed. FONT->default_char
1181 is a 16-bit character code with byte1 in the most significant
1182 byte and byte2 in the least significant byte. */
1183 XChar2b default_char;
1184 default_char.byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff;
1185 default_char.byte2 = font->default_char & 0xff;
1186
1187 /* Avoid an endless recursion if FONT->default_char itself
1188 hasn't per char metrics. handa@etl.go.jp reports that some
1189 fonts have this problem. */
1190 if (default_char.byte1 != char2b->byte1
1191 || default_char.byte2 != char2b->byte2)
1192 pcm = x_per_char_metric (font, &default_char);
1193 else
1194 pcm = &font->max_bounds;
1195 }
1196
1197 return pcm;
1198 }
1199
1200
1201 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1202 the two-byte form of C. Encoding is returned in *CHAR2B. */
1203
1204 static INLINE void
1205 x_encode_char (c, char2b, font_info)
1206 int c;
1207 XChar2b *char2b;
1208 struct font_info *font_info;
1209 {
1210 int charset = CHAR_CHARSET (c);
1211 XFontStruct *font = font_info->font;
1212
1213 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1214 This may be either a program in a special encoder language or a
1215 fixed encoding. */
1216 if (font_info->font_encoder)
1217 {
1218 /* It's a program. */
1219 struct ccl_program *ccl = font_info->font_encoder;
1220
1221 if (CHARSET_DIMENSION (charset) == 1)
1222 {
1223 ccl->reg[0] = charset;
1224 ccl->reg[1] = char2b->byte2;
1225 }
1226 else
1227 {
1228 ccl->reg[0] = charset;
1229 ccl->reg[1] = char2b->byte1;
1230 ccl->reg[2] = char2b->byte2;
1231 }
1232
1233 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1234
1235 /* We assume that MSBs are appropriately set/reset by CCL
1236 program. */
1237 if (font->max_byte1 == 0) /* 1-byte font */
1238 char2b->byte2 = ccl->reg[1];
1239 else
1240 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1241 }
1242 else if (font_info->encoding[charset])
1243 {
1244 /* Fixed encoding scheme. See fontset.h for the meaning of the
1245 encoding numbers. */
1246 int enc = font_info->encoding[charset];
1247
1248 if ((enc == 1 || enc == 2)
1249 && CHARSET_DIMENSION (charset) == 2)
1250 char2b->byte1 |= 0x80;
1251
1252 if (enc == 1 || enc == 3)
1253 char2b->byte2 |= 0x80;
1254 }
1255 }
1256
1257
1258 /* Get face and two-byte form of character C in face FACE_ID on frame
1259 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1260 means we want to display multibyte text. Value is a pointer to a
1261 realized face that is ready for display. */
1262
1263 static INLINE struct face *
1264 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1265 struct frame *f;
1266 int c, face_id;
1267 XChar2b *char2b;
1268 int multibyte_p;
1269 {
1270 struct face *face = FACE_FROM_ID (f, face_id);
1271
1272 if (!multibyte_p)
1273 {
1274 /* Unibyte case. We don't have to encode, but we have to make
1275 sure to use a face suitable for unibyte. */
1276 char2b->byte1 = 0;
1277 char2b->byte2 = c;
1278
1279 if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
1280 {
1281 face_id = FACE_FOR_CHARSET (f, face_id, -1);
1282 face = FACE_FROM_ID (f, face_id);
1283 }
1284 }
1285 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1286 {
1287 /* Case of ASCII in a face known to fit ASCII. */
1288 char2b->byte1 = 0;
1289 char2b->byte2 = c;
1290 }
1291 else
1292 {
1293 int c1, c2, charset;
1294
1295 /* Split characters into bytes. If c2 is -1 afterwards, C is
1296 really a one-byte character so that byte1 is zero. */
1297 SPLIT_CHAR (c, charset, c1, c2);
1298 if (c2 > 0)
1299 char2b->byte1 = c1, char2b->byte2 = c2;
1300 else
1301 char2b->byte1 = 0, char2b->byte2 = c1;
1302
1303 /* Get the face for displaying C. If `face' is not suitable for
1304 charset, get the one that fits. (This can happen for the
1305 translations of composite characters where the glyph
1306 specifies a face for ASCII, but translations have a different
1307 charset.) */
1308 if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
1309 {
1310 face_id = FACE_FOR_CHARSET (f, face_id, charset);
1311 face = FACE_FROM_ID (f, face_id);
1312 }
1313
1314 /* Maybe encode the character in *CHAR2B. */
1315 if (charset != CHARSET_ASCII)
1316 {
1317 struct font_info *font_info
1318 = FONT_INFO_FROM_ID (f, face->font_info_id);
1319 if (font_info)
1320 {
1321 x_encode_char (c, char2b, font_info);
1322 if (charset == charset_latin_iso8859_1)
1323 {
1324 xassert (((XFontStruct *) font_info->font)->max_char_or_byte2
1325 >= 0x80);
1326 char2b->byte2 |= 0x80;
1327 }
1328 }
1329 }
1330 }
1331
1332 /* Make sure X resources of the face are allocated. */
1333 xassert (face != NULL);
1334 PREPARE_FACE_FOR_DISPLAY (f, face);
1335
1336 return face;
1337 }
1338
1339
1340 /* Get face and two-byte form of character glyph GLYPH on frame F.
1341 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1342 a pointer to a realized face that is ready for display. */
1343
1344 static INLINE struct face *
1345 x_get_glyph_face_and_encoding (f, glyph, char2b)
1346 struct frame *f;
1347 struct glyph *glyph;
1348 XChar2b *char2b;
1349 {
1350 struct face *face;
1351
1352 xassert (glyph->type == CHAR_GLYPH);
1353 face = FACE_FROM_ID (f, glyph->u.ch.face_id);
1354
1355 if (!glyph->multibyte_p)
1356 {
1357 /* Unibyte case. We don't have to encode, but we have to make
1358 sure to use a face suitable for unibyte. */
1359 char2b->byte1 = 0;
1360 char2b->byte2 = glyph->u.ch.code;
1361 }
1362 else if (glyph->u.ch.code < 128
1363 && glyph->u.ch.face_id < BASIC_FACE_ID_SENTINEL)
1364 {
1365 /* Case of ASCII in a face known to fit ASCII. */
1366 char2b->byte1 = 0;
1367 char2b->byte2 = glyph->u.ch.code;
1368 }
1369 else
1370 {
1371 int c1, c2, charset;
1372
1373 /* Split characters into bytes. If c2 is -1 afterwards, C is
1374 really a one-byte character so that byte1 is zero. */
1375 SPLIT_CHAR (glyph->u.ch.code, charset, c1, c2);
1376 if (c2 > 0)
1377 char2b->byte1 = c1, char2b->byte2 = c2;
1378 else
1379 char2b->byte1 = 0, char2b->byte2 = c1;
1380
1381 /* Maybe encode the character in *CHAR2B. */
1382 if (charset != CHARSET_ASCII)
1383 {
1384 struct font_info *font_info
1385 = FONT_INFO_FROM_ID (f, face->font_info_id);
1386 if (font_info)
1387 {
1388 x_encode_char (glyph->u.ch.code, char2b, font_info);
1389 if (charset == charset_latin_iso8859_1)
1390 char2b->byte2 |= 0x80;
1391 }
1392 }
1393 }
1394
1395 /* Make sure X resources of the face are allocated. */
1396 xassert (face != NULL);
1397 PREPARE_FACE_FOR_DISPLAY (f, face);
1398 return face;
1399 }
1400
1401
1402 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1403 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1404
1405 static INLINE void
1406 x_append_glyph (it)
1407 struct it *it;
1408 {
1409 struct glyph *glyph;
1410 enum glyph_row_area area = it->area;
1411
1412 xassert (it->glyph_row);
1413 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1414
1415 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1416 if (glyph < it->glyph_row->glyphs[area + 1])
1417 {
1418 /* Play it safe. If sub-structures of the glyph are not all the
1419 same size, it otherwise be that some bits stay set. This
1420 would prevent a comparison with GLYPH_EQUAL_P. */
1421 glyph->u.val = 0;
1422
1423 glyph->type = CHAR_GLYPH;
1424 glyph->pixel_width = it->pixel_width;
1425 glyph->u.ch.code = it->char_to_display;
1426 glyph->u.ch.face_id = it->face_id;
1427 glyph->charpos = CHARPOS (it->position);
1428 glyph->object = it->object;
1429 glyph->left_box_line_p = it->start_of_box_run_p;
1430 glyph->right_box_line_p = it->end_of_box_run_p;
1431 glyph->voffset = it->voffset;
1432 glyph->multibyte_p = it->multibyte_p;
1433 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1434 || it->phys_descent > it->descent);
1435 ++it->glyph_row->used[area];
1436 }
1437 }
1438
1439
1440 /* Change IT->ascent and IT->height according to the setting of
1441 IT->voffset. */
1442
1443 static INLINE void
1444 take_vertical_position_into_account (it)
1445 struct it *it;
1446 {
1447 if (it->voffset)
1448 {
1449 if (it->voffset < 0)
1450 /* Increase the ascent so that we can display the text higher
1451 in the line. */
1452 it->ascent += abs (it->voffset);
1453 else
1454 /* Increase the descent so that we can display the text lower
1455 in the line. */
1456 it->descent += it->voffset;
1457 }
1458 }
1459
1460
1461 /* Produce glyphs/get display metrics for the image IT is loaded with.
1462 See the description of struct display_iterator in dispextern.h for
1463 an overview of struct display_iterator. */
1464
1465 static void
1466 x_produce_image_glyph (it)
1467 struct it *it;
1468 {
1469 struct image *img;
1470 struct face *face;
1471
1472 xassert (it->what == IT_IMAGE);
1473
1474 face = FACE_FROM_ID (it->f, it->face_id);
1475 img = IMAGE_FROM_ID (it->f, it->image_id);
1476 xassert (img);
1477
1478 /* Make sure X resources of the face and image are loaded. */
1479 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1480 prepare_image_for_display (it->f, img);
1481
1482 it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
1483 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1484 it->pixel_width = img->width + 2 * img->margin;
1485
1486 it->nglyphs = 1;
1487
1488 if (face->box != FACE_NO_BOX)
1489 {
1490 it->ascent += face->box_line_width;
1491 it->descent += face->box_line_width;
1492
1493 if (it->start_of_box_run_p)
1494 it->pixel_width += face->box_line_width;
1495 if (it->end_of_box_run_p)
1496 it->pixel_width += face->box_line_width;
1497 }
1498
1499 take_vertical_position_into_account (it);
1500
1501 if (it->glyph_row)
1502 {
1503 struct glyph *glyph;
1504 enum glyph_row_area area = it->area;
1505
1506 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1507 if (glyph < it->glyph_row->glyphs[area + 1])
1508 {
1509 glyph->type = IMAGE_GLYPH;
1510 glyph->u.img.id = img->id;
1511 glyph->u.img.face_id = it->face_id;
1512 glyph->pixel_width = it->pixel_width;
1513 glyph->charpos = CHARPOS (it->position);
1514 glyph->object = it->object;
1515 glyph->left_box_line_p = it->start_of_box_run_p;
1516 glyph->right_box_line_p = it->end_of_box_run_p;
1517 glyph->voffset = it->voffset;
1518 glyph->multibyte_p = it->multibyte_p;
1519 ++it->glyph_row->used[area];
1520 }
1521 }
1522 }
1523
1524
1525 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1526 of the glyph, WIDTH and HEIGHT are the width and height of the
1527 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1528 ascent of the glyph (0 <= ASCENT <= 1). */
1529
1530 static void
1531 x_append_stretch_glyph (it, object, width, height, ascent)
1532 struct it *it;
1533 Lisp_Object object;
1534 int width, height;
1535 double ascent;
1536 {
1537 struct glyph *glyph;
1538 enum glyph_row_area area = it->area;
1539
1540 xassert (ascent >= 0 && ascent <= 1);
1541
1542 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1543 if (glyph < it->glyph_row->glyphs[area + 1])
1544 {
1545 glyph->type = STRETCH_GLYPH;
1546 glyph->u.stretch.ascent = height * ascent;
1547 glyph->u.stretch.height = height;
1548 glyph->u.stretch.face_id = it->face_id;
1549 glyph->pixel_width = width;
1550 glyph->charpos = CHARPOS (it->position);
1551 glyph->object = object;
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->voffset = it->voffset;
1555 glyph->multibyte_p = it->multibyte_p;
1556 ++it->glyph_row->used[area];
1557 }
1558 }
1559
1560
1561 /* Produce a stretch glyph for iterator IT. IT->object is the value
1562 of the glyph property displayed. The value must be a list
1563 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1564 being recognized:
1565
1566 1. `:width WIDTH' specifies that the space should be WIDTH *
1567 canonical char width wide. WIDTH may be an integer or floating
1568 point number.
1569
1570 2. `:relative-width FACTOR' specifies that the width of the stretch
1571 should be computed from the width of the first character having the
1572 `glyph' property, and should be FACTOR times that width.
1573
1574 3. `:align-to HPOS' specifies that the space should be wide enough
1575 to reach HPOS, a value in canonical character units.
1576
1577 Exactly one of the above pairs must be present.
1578
1579 4. `:height HEIGHT' specifies that the height of the stretch produced
1580 should be HEIGHT, measured in canonical character units.
1581
1582 5. `:relative-height FACTOR' specifies that the height of the the
1583 stretch should be FACTOR times the height of the characters having
1584 the glyph property.
1585
1586 Either none or exactly one of 4 or 5 must be present.
1587
1588 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1589 of the stretch should be used for the ascent of the stretch.
1590 ASCENT must be in the range 0 <= ASCENT <= 100. */
1591
1592 #define NUMVAL(X) \
1593 ((INTEGERP (X) || FLOATP (X)) \
1594 ? XFLOATINT (X) \
1595 : - 1)
1596
1597
1598 static void
1599 x_produce_stretch_glyph (it)
1600 struct it *it;
1601 {
1602 /* (space :width WIDTH :height HEIGHT. */
1603 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1604 extern Lisp_Object QCrelative_width, QCrelative_height;
1605 extern Lisp_Object QCalign_to;
1606 Lisp_Object prop, plist;
1607 double width = 0, height = 0, ascent = 0;
1608 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1609 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1610
1611 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1612
1613 /* List should start with `space'. */
1614 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1615 plist = XCDR (it->object);
1616
1617 /* Compute the width of the stretch. */
1618 if (prop = Fplist_get (plist, QCwidth),
1619 NUMVAL (prop) > 0)
1620 /* Absolute width `:width WIDTH' specified and valid. */
1621 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1622 else if (prop = Fplist_get (plist, QCrelative_width),
1623 NUMVAL (prop) > 0)
1624 {
1625 /* Relative width `:relative-width FACTOR' specified and valid.
1626 Compute the width of the characters having the `glyph'
1627 property. */
1628 struct it it2;
1629 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1630
1631 it2 = *it;
1632 if (it->multibyte_p)
1633 {
1634 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1635 - IT_BYTEPOS (*it));
1636 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1637 }
1638 else
1639 it2.c = *p, it2.len = 1;
1640
1641 it2.glyph_row = NULL;
1642 it2.what = IT_CHARACTER;
1643 x_produce_glyphs (&it2);
1644 width = NUMVAL (prop) * it2.pixel_width;
1645 }
1646 else if (prop = Fplist_get (plist, QCalign_to),
1647 NUMVAL (prop) > 0)
1648 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1649 else
1650 /* Nothing specified -> width defaults to canonical char width. */
1651 width = CANON_X_UNIT (it->f);
1652
1653 /* Compute height. */
1654 if (prop = Fplist_get (plist, QCheight),
1655 NUMVAL (prop) > 0)
1656 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1657 else if (prop = Fplist_get (plist, QCrelative_height),
1658 NUMVAL (prop) > 0)
1659 height = FONT_HEIGHT (font) * NUMVAL (prop);
1660 else
1661 height = FONT_HEIGHT (font);
1662
1663 /* Compute percentage of height used for ascent. If
1664 `:ascent ASCENT' is present and valid, use that. Otherwise,
1665 derive the ascent from the font in use. */
1666 if (prop = Fplist_get (plist, QCascent),
1667 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1668 ascent = NUMVAL (prop) / 100.0;
1669 else
1670 ascent = (double) font->ascent / FONT_HEIGHT (font);
1671
1672 if (width <= 0)
1673 width = 1;
1674 if (height <= 0)
1675 height = 1;
1676
1677 if (it->glyph_row)
1678 {
1679 Lisp_Object object = it->stack[it->sp - 1].string;
1680 if (!STRINGP (object))
1681 object = it->w->buffer;
1682 x_append_stretch_glyph (it, object, width, height, ascent);
1683 }
1684
1685 it->pixel_width = width;
1686 it->ascent = it->phys_ascent = height * ascent;
1687 it->descent = it->phys_descent = height - it->ascent;
1688 it->nglyphs = 1;
1689
1690 if (face->box != FACE_NO_BOX)
1691 {
1692 it->ascent += face->box_line_width;
1693 it->descent += face->box_line_width;
1694
1695 if (it->start_of_box_run_p)
1696 it->pixel_width += face->box_line_width;
1697 if (it->end_of_box_run_p)
1698 it->pixel_width += face->box_line_width;
1699 }
1700
1701 take_vertical_position_into_account (it);
1702 }
1703
1704
1705 /* Produce glyphs/get display metrics for the display element IT is
1706 loaded with. See the description of struct display_iterator in
1707 dispextern.h for an overview of struct display_iterator. */
1708
1709 static void
1710 x_produce_glyphs (it)
1711 struct it *it;
1712 {
1713 if (it->what == IT_CHARACTER)
1714 {
1715 XChar2b char2b;
1716 XFontStruct *font;
1717 struct face *face;
1718 XCharStruct *pcm;
1719 int font_not_found_p;
1720
1721 /* Maybe translate single-byte characters to multibyte. */
1722 it->char_to_display = it->c;
1723 if (unibyte_display_via_language_environment
1724 && SINGLE_BYTE_CHAR_P (it->c)
1725 && (it->c >= 0240
1726 || (it->c >= 0200
1727 && !NILP (Vnonascii_translation_table))))
1728 {
1729 it->char_to_display = unibyte_char_to_multibyte (it->c);
1730 it->charset = CHAR_CHARSET (it->char_to_display);
1731 }
1732
1733 /* Get face and font to use. Encode IT->char_to_display. */
1734 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
1735 it->face_id, &char2b,
1736 it->multibyte_p);
1737 font = face->font;
1738
1739 /* When no suitable font found, use the default font. */
1740 font_not_found_p = font == NULL;
1741 if (font_not_found_p)
1742 font = FRAME_FONT (it->f);
1743
1744 if (it->char_to_display >= ' '
1745 && (!it->multibyte_p || it->char_to_display < 128))
1746 {
1747 /* Either unibyte or ASCII. */
1748 int stretched_p;
1749
1750 it->nglyphs = 1;
1751
1752 pcm = x_per_char_metric (font, &char2b);
1753 it->ascent = font->ascent;
1754 it->descent = font->descent;
1755 it->phys_ascent = pcm->ascent;
1756 it->phys_descent = pcm->descent;
1757 it->pixel_width = pcm->width;
1758
1759 /* If this is a space inside a region of text with
1760 `space-width' property, change its width. */
1761 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1762 if (stretched_p)
1763 it->pixel_width *= XFLOATINT (it->space_width);
1764
1765 /* If face has a box, add the box thickness to the character
1766 height. If character has a box line to the left and/or
1767 right, add the box line width to the character's width. */
1768 if (face->box != FACE_NO_BOX)
1769 {
1770 int thick = face->box_line_width;
1771
1772 it->ascent += thick;
1773 it->descent += thick;
1774
1775 if (it->start_of_box_run_p)
1776 it->pixel_width += thick;
1777 if (it->end_of_box_run_p)
1778 it->pixel_width += thick;
1779 }
1780
1781 /* If face has an overline, add the height of the overline
1782 (1 pixel) and a 1 pixel margin to the character height. */
1783 if (face->overline_p)
1784 it->ascent += 2;
1785
1786 take_vertical_position_into_account (it);
1787
1788 /* If we have to actually produce glyphs, do it. */
1789 if (it->glyph_row)
1790 {
1791 if (stretched_p)
1792 {
1793 /* Translate a space with a `space-width' property
1794 into a stretch glyph. */
1795 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1796 x_append_stretch_glyph (it, it->object, it->pixel_width,
1797 it->ascent + it->descent, ascent);
1798 }
1799 else
1800 x_append_glyph (it);
1801
1802 /* If characters with lbearing or rbearing are displayed
1803 in this line, record that fact in a flag of the
1804 glyph row. This is used to optimize X output code. */
1805 if (pcm->lbearing < 0
1806 || pcm->rbearing > pcm->width)
1807 it->glyph_row->contains_overlapping_glyphs_p = 1;
1808 }
1809 }
1810 else if (it->char_to_display == '\n')
1811 {
1812 /* A newline has no width but we need the height of the line. */
1813 it->pixel_width = 0;
1814 it->nglyphs = 0;
1815 it->ascent = it->phys_ascent = font->ascent;
1816 it->descent = it->phys_descent = font->descent;
1817
1818 if (face->box != FACE_NO_BOX)
1819 {
1820 int thick = face->box_line_width;
1821 it->ascent += thick;
1822 it->descent += thick;
1823 }
1824 }
1825 else if (it->char_to_display == '\t')
1826 {
1827 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1828 int x = (it->current_x
1829 - it->prompt_width
1830 + it->continuation_lines_width);
1831 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1832
1833 it->pixel_width = next_tab_x - x;
1834 it->nglyphs = 1;
1835 it->ascent = it->phys_ascent = font->ascent;
1836 it->descent = it->phys_descent = font->descent;
1837
1838 if (it->glyph_row)
1839 {
1840 double ascent = (double) it->ascent / (it->ascent + it->descent);
1841 x_append_stretch_glyph (it, it->object, it->pixel_width,
1842 it->ascent + it->descent, ascent);
1843 }
1844 }
1845 else
1846 {
1847 /* A multi-byte character. Assume that the display width of the
1848 character is the width of the character multiplied by the
1849 width of the font. There has to be better support for
1850 variable sizes in cmpchar_info to do anything better than
1851 that.
1852
1853 Note: composite characters are represented as one glyph in
1854 the glyph matrix. There are no padding glyphs. */
1855 if (it->charset == CHARSET_COMPOSITION)
1856 {
1857 struct cmpchar_info *cmpcharp;
1858 int idx;
1859
1860 idx = COMPOSITE_CHAR_ID (it->char_to_display);
1861 cmpcharp = cmpchar_table[idx];
1862 it->pixel_width = font->max_bounds.width * cmpcharp->width;
1863
1864 /* There are no padding glyphs, so there is only one glyph
1865 to produce for the composite char. Important is that
1866 pixel_width, ascent and descent are the values of what is
1867 drawn by draw_glyphs. */
1868 it->nglyphs = 1;
1869
1870 /* These settings may not be correct. We must have more
1871 information in cmpcharp to do the correct setting. */
1872 it->ascent = font->ascent;
1873 it->descent = font->descent;
1874 it->phys_ascent = font->max_bounds.ascent;
1875 it->phys_descent = font->max_bounds.descent;
1876 }
1877 else
1878 {
1879 /* If we found a font, this font should give us the right
1880 metrics. If we didn't find a font, use the frame's
1881 default font and calculate the width of the character
1882 from the charset width; this is what old redisplay code
1883 did. */
1884 pcm = x_per_char_metric (font, &char2b);
1885 it->pixel_width = pcm->width;
1886 if (font_not_found_p)
1887 it->pixel_width *= CHARSET_WIDTH (it->charset);
1888 it->nglyphs = 1;
1889 it->ascent = font->ascent;
1890 it->descent = font->descent;
1891 it->phys_ascent = pcm->ascent;
1892 it->phys_descent = pcm->descent;
1893 if (it->glyph_row
1894 && (pcm->lbearing < 0
1895 || pcm->rbearing > pcm->width))
1896 it->glyph_row->contains_overlapping_glyphs_p = 1;
1897 }
1898
1899 if (face->box != FACE_NO_BOX)
1900 {
1901 int thick = face->box_line_width;
1902 it->ascent += thick;
1903 it->descent += thick;
1904
1905 if (it->start_of_box_run_p)
1906 it->pixel_width += thick;
1907 if (it->end_of_box_run_p)
1908 it->pixel_width += thick;
1909 }
1910
1911 /* If face has an overline, add the height of the overline
1912 (1 pixel) and a 1 pixel margin to the character height. */
1913 if (face->overline_p)
1914 it->ascent += 2;
1915
1916 take_vertical_position_into_account (it);
1917
1918 if (it->glyph_row)
1919 x_append_glyph (it);
1920 }
1921 }
1922 else if (it->what == IT_IMAGE)
1923 x_produce_image_glyph (it);
1924 else if (it->what == IT_STRETCH)
1925 x_produce_stretch_glyph (it);
1926
1927 /* Accumulate dimensions. */
1928 xassert (it->ascent >= 0 && it->descent > 0);
1929 if (it->area == TEXT_AREA)
1930 it->current_x += it->pixel_width;
1931
1932 it->max_ascent = max (it->max_ascent, it->ascent);
1933 it->max_descent = max (it->max_descent, it->descent);
1934 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
1935 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
1936 }
1937
1938
1939 /* Estimate the pixel height of the mode or top line on frame F.
1940 FACE_ID specifies what line's height to estimate. */
1941
1942 int
1943 x_estimate_mode_line_height (f, face_id)
1944 struct frame *f;
1945 enum face_id face_id;
1946 {
1947 int height = 1;
1948
1949 /* This function is called so early when Emacs starts that the face
1950 cache and mode line face are not yet initialized. */
1951 if (FRAME_FACE_CACHE (f))
1952 {
1953 struct face *face = FACE_FROM_ID (f, face_id);
1954 if (face)
1955 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
1956 }
1957
1958 return height;
1959 }
1960
1961 \f
1962 /***********************************************************************
1963 Glyph display
1964 ***********************************************************************/
1965
1966 /* A sequence of glyphs to be drawn in the same face.
1967
1968 This data structure is not really completely X specific, so it
1969 could possibly, at least partially, be useful for other systems. It
1970 is currently not part of the external redisplay interface because
1971 it's not clear what other systems will need. */
1972
1973 struct glyph_string
1974 {
1975 /* X-origin of the string. */
1976 int x;
1977
1978 /* Y-origin and y-position of the base line of this string. */
1979 int y, ybase;
1980
1981 /* The width of the string, not including a face extension. */
1982 int width;
1983
1984 /* The width of the string, including a face extension. */
1985 int background_width;
1986
1987 /* The height of this string. This is the height of the line this
1988 string is drawn in, and can be different from the height of the
1989 font the string is drawn in. */
1990 int height;
1991
1992 /* Number of pixels this string overwrites in front of its x-origin.
1993 This number is zero if the string has an lbearing >= 0; it is
1994 -lbearing, if the string has an lbearing < 0. */
1995 int left_overhang;
1996
1997 /* Number of pixels this string overwrites past its right-most
1998 nominal x-position, i.e. x + width. Zero if the string's
1999 rbearing is <= its nominal width, rbearing - width otherwise. */
2000 int right_overhang;
2001
2002 /* The frame on which the glyph string is drawn. */
2003 struct frame *f;
2004
2005 /* The window on which the glyph string is drawn. */
2006 struct window *w;
2007
2008 /* X display and window for convenience. */
2009 Display *display;
2010 Window window;
2011
2012 /* The glyph row for which this string was built. It determines the
2013 y-origin and height of the string. */
2014 struct glyph_row *row;
2015
2016 /* The area within row. */
2017 enum glyph_row_area area;
2018
2019 /* Characters to be drawn, and number of characters. */
2020 XChar2b *char2b;
2021 int nchars;
2022
2023 /* Character set of this glyph string. */
2024 int charset;
2025
2026 /* A face-override for drawing cursors, mouse face and similar. */
2027 enum draw_glyphs_face hl;
2028
2029 /* Face in which this string is to be drawn. */
2030 struct face *face;
2031
2032 /* Font in which this string is to be drawn. */
2033 XFontStruct *font;
2034
2035 /* Font info for this string. */
2036 struct font_info *font_info;
2037
2038 /* Non-null means this string describes (part of) a composite
2039 character. All characters from char2b are drawn at the same
2040 x-origin in that case. */
2041 struct cmpchar_info *cmpcharp;
2042
2043 /* Index of this glyph string's first character in the glyph
2044 definition of cmpcharp. If this is zero, this glyph string
2045 describes the first character of a composite character. */
2046 int gidx;
2047
2048 /* 1 means this glyph strings face has to be drawn to the right end
2049 of the window's drawing area. */
2050 unsigned extends_to_end_of_line_p : 1;
2051
2052 /* 1 means the background of this string has been drawn. */
2053 unsigned background_filled_p : 1;
2054
2055 /* 1 means glyph string must be drawn with 16-bit functions. */
2056 unsigned two_byte_p : 1;
2057
2058 /* 1 means that the original font determined for drawing this glyph
2059 string could not be loaded. The member `font' has been set to
2060 the frame's default font in this case. */
2061 unsigned font_not_found_p : 1;
2062
2063 /* 1 means that the face in which this glyph string is drawn has a
2064 stipple pattern. */
2065 unsigned stippled_p : 1;
2066
2067 /* 1 means only the foreground of this glyph string must be drawn,
2068 and we should use the physical height of the line this glyph
2069 string appears in as clip rect. */
2070 unsigned for_overlaps_p : 1;
2071
2072 /* The GC to use for drawing this glyph string. */
2073 GC gc;
2074
2075 /* A pointer to the first glyph in the string. This glyph
2076 corresponds to char2b[0]. Needed to draw rectangles if
2077 font_not_found_p is 1. */
2078 struct glyph *first_glyph;
2079
2080 /* Image, if any. */
2081 struct image *img;
2082
2083 struct glyph_string *next, *prev;
2084 };
2085
2086
2087 #if 0
2088
2089 static void
2090 x_dump_glyph_string (s)
2091 struct glyph_string *s;
2092 {
2093 fprintf (stderr, "glyph string\n");
2094 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2095 s->x, s->y, s->width, s->height);
2096 fprintf (stderr, " ybase = %d\n", s->ybase);
2097 fprintf (stderr, " hl = %d\n", s->hl);
2098 fprintf (stderr, " left overhang = %d, right = %d\n",
2099 s->left_overhang, s->right_overhang);
2100 fprintf (stderr, " nchars = %d\n", s->nchars);
2101 fprintf (stderr, " extends to end of line = %d\n",
2102 s->extends_to_end_of_line_p);
2103 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2104 fprintf (stderr, " bg width = %d\n", s->background_width);
2105 }
2106
2107 #endif /* GLYPH_DEBUG */
2108
2109
2110
2111 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2112 struct glyph_string **,
2113 struct glyph_string *,
2114 struct glyph_string *));
2115 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2116 struct glyph_string **,
2117 struct glyph_string *,
2118 struct glyph_string *));
2119 static void x_append_glyph_string P_ ((struct glyph_string **,
2120 struct glyph_string **,
2121 struct glyph_string *));
2122 static int x_left_overwritten P_ ((struct glyph_string *));
2123 static int x_left_overwriting P_ ((struct glyph_string *));
2124 static int x_right_overwritten P_ ((struct glyph_string *));
2125 static int x_right_overwriting P_ ((struct glyph_string *));
2126 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2127 int));
2128 static void x_init_glyph_string P_ ((struct glyph_string *,
2129 XChar2b *, struct window *,
2130 struct glyph_row *,
2131 enum glyph_row_area, int,
2132 enum draw_glyphs_face));
2133 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2134 enum glyph_row_area, int, int,
2135 enum draw_glyphs_face, int *, int *, int));
2136 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2137 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2138 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2139 int));
2140 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2141 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2142 static void x_draw_glyph_string P_ ((struct glyph_string *));
2143 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2144 static void x_set_cursor_gc P_ ((struct glyph_string *));
2145 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2146 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2147 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2148 int *, int *));
2149 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2150 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2151 unsigned long *, double, int));
2152 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2153 double, int, unsigned long));
2154 static void x_setup_relief_colors P_ ((struct glyph_string *));
2155 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2156 static void x_draw_image_relief P_ ((struct glyph_string *));
2157 static void x_draw_image_foreground P_ ((struct glyph_string *));
2158 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2159 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2160 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2161 int, int, int));
2162 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2163 int, int, int, int, XRectangle *));
2164 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2165 int, int, int, XRectangle *));
2166 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2167 enum glyph_row_area));
2168
2169
2170 /* Append the list of glyph strings with head H and tail T to the list
2171 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2172
2173 static INLINE void
2174 x_append_glyph_string_lists (head, tail, h, t)
2175 struct glyph_string **head, **tail;
2176 struct glyph_string *h, *t;
2177 {
2178 if (h)
2179 {
2180 if (*head)
2181 (*tail)->next = h;
2182 else
2183 *head = h;
2184 h->prev = *tail;
2185 *tail = t;
2186 }
2187 }
2188
2189
2190 /* Prepend the list of glyph strings with head H and tail T to the
2191 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2192 result. */
2193
2194 static INLINE void
2195 x_prepend_glyph_string_lists (head, tail, h, t)
2196 struct glyph_string **head, **tail;
2197 struct glyph_string *h, *t;
2198 {
2199 if (h)
2200 {
2201 if (*head)
2202 (*head)->prev = t;
2203 else
2204 *tail = t;
2205 t->next = *head;
2206 *head = h;
2207 }
2208 }
2209
2210
2211 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2212 Set *HEAD and *TAIL to the resulting list. */
2213
2214 static INLINE void
2215 x_append_glyph_string (head, tail, s)
2216 struct glyph_string **head, **tail;
2217 struct glyph_string *s;
2218 {
2219 s->next = s->prev = NULL;
2220 x_append_glyph_string_lists (head, tail, s, s);
2221 }
2222
2223
2224 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2225 face. */
2226
2227 static void
2228 x_set_cursor_gc (s)
2229 struct glyph_string *s;
2230 {
2231 if (s->font == FRAME_FONT (s->f)
2232 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2233 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2234 && !s->cmpcharp)
2235 s->gc = s->f->output_data.x->cursor_gc;
2236 else
2237 {
2238 /* Cursor on non-default face: must merge. */
2239 XGCValues xgcv;
2240 unsigned long mask;
2241
2242 xgcv.background = s->f->output_data.x->cursor_pixel;
2243 xgcv.foreground = s->face->background;
2244
2245 /* If the glyph would be invisible, try a different foreground. */
2246 if (xgcv.foreground == xgcv.background)
2247 xgcv.foreground = s->face->foreground;
2248 if (xgcv.foreground == xgcv.background)
2249 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2250 if (xgcv.foreground == xgcv.background)
2251 xgcv.foreground = s->face->foreground;
2252
2253 /* Make sure the cursor is distinct from text in this face. */
2254 if (xgcv.background == s->face->background
2255 && xgcv.foreground == s->face->foreground)
2256 {
2257 xgcv.background = s->face->foreground;
2258 xgcv.foreground = s->face->background;
2259 }
2260
2261 IF_DEBUG (x_check_font (s->f, s->font));
2262 xgcv.font = s->font->fid;
2263 xgcv.graphics_exposures = False;
2264 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2265
2266 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2267 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2268 mask, &xgcv);
2269 else
2270 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2271 = XCreateGC (s->display, s->window, mask, &xgcv);
2272
2273 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2274 }
2275 }
2276
2277
2278 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2279
2280 static void
2281 x_set_mouse_face_gc (s)
2282 struct glyph_string *s;
2283 {
2284 int face_id;
2285
2286 /* What face has to be used for the mouse face? */
2287 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2288 face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
2289 s->face = FACE_FROM_ID (s->f, face_id);
2290 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2291
2292 /* If font in this face is same as S->font, use it. */
2293 if (s->font == s->face->font)
2294 s->gc = s->face->gc;
2295 else
2296 {
2297 /* Otherwise construct scratch_cursor_gc with values from FACE
2298 but font FONT. */
2299 XGCValues xgcv;
2300 unsigned long mask;
2301
2302 xgcv.background = s->face->background;
2303 xgcv.foreground = s->face->foreground;
2304 IF_DEBUG (x_check_font (s->f, s->font));
2305 xgcv.font = s->font->fid;
2306 xgcv.graphics_exposures = False;
2307 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2308
2309 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2310 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2311 mask, &xgcv);
2312 else
2313 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2314 = XCreateGC (s->display, s->window, mask, &xgcv);
2315
2316 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2317 }
2318
2319 xassert (s->gc != 0);
2320 }
2321
2322
2323 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2324 Faces to use in the mode line have already been computed when the
2325 matrix was built, so there isn't much to do, here. */
2326
2327 static INLINE void
2328 x_set_mode_line_face_gc (s)
2329 struct glyph_string *s;
2330 {
2331 s->gc = s->face->gc;
2332 xassert (s->gc != 0);
2333 }
2334
2335
2336 /* Set S->gc of glyph string S for drawing that glyph string. Set
2337 S->stippled_p to a non-zero value if the face of S has a stipple
2338 pattern. */
2339
2340 static INLINE void
2341 x_set_glyph_string_gc (s)
2342 struct glyph_string *s;
2343 {
2344 if (s->hl == DRAW_NORMAL_TEXT)
2345 {
2346 s->gc = s->face->gc;
2347 s->stippled_p = s->face->stipple != 0;
2348 }
2349 else if (s->hl == DRAW_INVERSE_VIDEO)
2350 {
2351 x_set_mode_line_face_gc (s);
2352 s->stippled_p = s->face->stipple != 0;
2353 }
2354 else if (s->hl == DRAW_CURSOR)
2355 {
2356 x_set_cursor_gc (s);
2357 s->stippled_p = 0;
2358 }
2359 else if (s->hl == DRAW_MOUSE_FACE)
2360 {
2361 x_set_mouse_face_gc (s);
2362 s->stippled_p = s->face->stipple != 0;
2363 }
2364 else if (s->hl == DRAW_IMAGE_RAISED
2365 || s->hl == DRAW_IMAGE_SUNKEN)
2366 {
2367 s->gc = s->face->gc;
2368 s->stippled_p = s->face->stipple != 0;
2369 }
2370 else
2371 {
2372 s->gc = s->face->gc;
2373 s->stippled_p = s->face->stipple != 0;
2374 }
2375
2376 /* GC must have been set. */
2377 xassert (s->gc != 0);
2378 }
2379
2380
2381 /* Return in *R the clipping rectangle for glyph string S. */
2382
2383 static void
2384 x_get_glyph_string_clip_rect (s, r)
2385 struct glyph_string *s;
2386 XRectangle *r;
2387 {
2388 if (s->row->full_width_p)
2389 {
2390 /* Draw full-width. X coordinates are relative to S->w->left. */
2391 int canon_x = CANON_X_UNIT (s->f);
2392
2393 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2394 r->width = XFASTINT (s->w->width) * canon_x;
2395
2396 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2397 {
2398 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2399 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2400 r->x -= width;
2401 }
2402
2403 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2404
2405 /* Unless displaying a mode or menu bar line, which are always
2406 fully visible, clip to the visible part of the row. */
2407 if (s->w->pseudo_window_p)
2408 r->height = s->row->visible_height;
2409 else
2410 r->height = s->height;
2411 }
2412 else
2413 {
2414 /* This is a text line that may be partially visible. */
2415 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2416 r->width = window_box_width (s->w, s->area);
2417 r->height = s->row->visible_height;
2418 }
2419
2420 /* Don't use S->y for clipping because it doesn't take partially
2421 visible lines into account. For example, it can be negative for
2422 partially visible lines at the top of a window. */
2423 if (!s->row->full_width_p
2424 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2425 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2426 else
2427 r->y = max (0, s->row->y);
2428
2429 /* If drawing a tool-bar window, draw it over the internal border
2430 at the top of the window. */
2431 if (s->w == XWINDOW (s->f->tool_bar_window))
2432 r->y -= s->f->output_data.x->internal_border_width;
2433
2434 /* If S draws overlapping rows, it's sufficient to use the top and
2435 bottom of the window for clipping because this glyph string
2436 intentionally draws over other lines. */
2437 if (s->for_overlaps_p)
2438 {
2439 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2440 r->height = window_text_bottom_y (s->w) - r->y;
2441 }
2442
2443 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2444 }
2445
2446
2447 /* Set clipping for output of glyph string S. S may be part of a mode
2448 line or menu if we don't have X toolkit support. */
2449
2450 static INLINE void
2451 x_set_glyph_string_clipping (s)
2452 struct glyph_string *s;
2453 {
2454 XRectangle r;
2455 x_get_glyph_string_clip_rect (s, &r);
2456 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2457 }
2458
2459
2460 /* Compute left and right overhang of glyph string S. If S is a glyph
2461 string for a composite character, assume overhangs don't exist. */
2462
2463 static INLINE void
2464 x_compute_glyph_string_overhangs (s)
2465 struct glyph_string *s;
2466 {
2467 if (s->cmpcharp == NULL
2468 && s->first_glyph->type == CHAR_GLYPH)
2469 {
2470 XCharStruct cs;
2471 int direction, font_ascent, font_descent;
2472 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2473 &font_ascent, &font_descent, &cs);
2474 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2475 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2476 }
2477 }
2478
2479
2480 /* Compute overhangs and x-positions for glyph string S and its
2481 predecessors, or successors. X is the starting x-position for S.
2482 BACKWARD_P non-zero means process predecessors. */
2483
2484 static void
2485 x_compute_overhangs_and_x (s, x, backward_p)
2486 struct glyph_string *s;
2487 int x;
2488 int backward_p;
2489 {
2490 if (backward_p)
2491 {
2492 while (s)
2493 {
2494 x_compute_glyph_string_overhangs (s);
2495 x -= s->width;
2496 s->x = x;
2497 s = s->prev;
2498 }
2499 }
2500 else
2501 {
2502 while (s)
2503 {
2504 x_compute_glyph_string_overhangs (s);
2505 s->x = x;
2506 x += s->width;
2507 s = s->next;
2508 }
2509 }
2510 }
2511
2512
2513 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2514 frame F. Overhangs of glyphs other than type CHAR_GLYPH or of
2515 character glyphs for composite characters are assumed to be zero. */
2516
2517 static void
2518 x_get_glyph_overhangs (glyph, f, left, right)
2519 struct glyph *glyph;
2520 struct frame *f;
2521 int *left, *right;
2522 {
2523 int c;
2524
2525 *left = *right = 0;
2526
2527 if (glyph->type == CHAR_GLYPH
2528 && (c = glyph->u.ch.code,
2529 CHAR_CHARSET (c) != CHARSET_COMPOSITION))
2530 {
2531 XFontStruct *font;
2532 struct face *face;
2533 struct font_info *font_info;
2534 XChar2b char2b;
2535
2536 face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
2537 font = face->font;
2538 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2539 if (font)
2540 {
2541 XCharStruct *pcm = x_per_char_metric (font, &char2b);
2542
2543 if (pcm->rbearing > pcm->width)
2544 *right = pcm->rbearing - pcm->width;
2545 if (pcm->lbearing < 0)
2546 *left = -pcm->lbearing;
2547 }
2548 }
2549 }
2550
2551
2552 /* Return the index of the first glyph preceding glyph string S that
2553 is overwritten by S because of S's left overhang. Value is -1
2554 if no glyphs are overwritten. */
2555
2556 static int
2557 x_left_overwritten (s)
2558 struct glyph_string *s;
2559 {
2560 int k;
2561
2562 if (s->left_overhang)
2563 {
2564 int x = 0, i;
2565 struct glyph *glyphs = s->row->glyphs[s->area];
2566 int first = s->first_glyph - glyphs;
2567
2568 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2569 x -= glyphs[i].pixel_width;
2570
2571 k = i + 1;
2572 }
2573 else
2574 k = -1;
2575
2576 return k;
2577 }
2578
2579
2580 /* Return the index of the first glyph preceding glyph string S that
2581 is overwriting S because of its right overhang. Value is -1 if no
2582 glyph in front of S overwrites S. */
2583
2584 static int
2585 x_left_overwriting (s)
2586 struct glyph_string *s;
2587 {
2588 int i, k, x;
2589 struct glyph *glyphs = s->row->glyphs[s->area];
2590 int first = s->first_glyph - glyphs;
2591
2592 k = -1;
2593 x = 0;
2594 for (i = first - 1; i >= 0; --i)
2595 {
2596 int left, right;
2597 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2598 if (x + right > 0)
2599 k = i;
2600 x -= glyphs[i].pixel_width;
2601 }
2602
2603 return k;
2604 }
2605
2606
2607 /* Return the index of the last glyph following glyph string S that is
2608 not overwritten by S because of S's right overhang. Value is -1 if
2609 no such glyph is found. */
2610
2611 static int
2612 x_right_overwritten (s)
2613 struct glyph_string *s;
2614 {
2615 int k = -1;
2616
2617 if (s->right_overhang)
2618 {
2619 int x = 0, i;
2620 struct glyph *glyphs = s->row->glyphs[s->area];
2621 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
2622 int end = s->row->used[s->area];
2623
2624 for (i = first; i < end && s->right_overhang > x; ++i)
2625 x += glyphs[i].pixel_width;
2626
2627 k = i;
2628 }
2629
2630 return k;
2631 }
2632
2633
2634 /* Return the index of the last glyph following glyph string S that
2635 overwrites S because of its left overhang. Value is negative
2636 if no such glyph is found. */
2637
2638 static int
2639 x_right_overwriting (s)
2640 struct glyph_string *s;
2641 {
2642 int i, k, x;
2643 int end = s->row->used[s->area];
2644 struct glyph *glyphs = s->row->glyphs[s->area];
2645 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
2646
2647 k = -1;
2648 x = 0;
2649 for (i = first; i < end; ++i)
2650 {
2651 int left, right;
2652 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2653 if (x - left < 0)
2654 k = i;
2655 x += glyphs[i].pixel_width;
2656 }
2657
2658 return k;
2659 }
2660
2661
2662 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2663
2664 static INLINE void
2665 x_clear_glyph_string_rect (s, x, y, w, h)
2666 struct glyph_string *s;
2667 int x, y, w, h;
2668 {
2669 XGCValues xgcv;
2670 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
2671 XSetForeground (s->display, s->gc, xgcv.background);
2672 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2673 XSetForeground (s->display, s->gc, xgcv.foreground);
2674 }
2675
2676
2677 /* Draw the background of glyph_string S. If S->background_filled_p
2678 is non-zero don't draw it. FORCE_P non-zero means draw the
2679 background even if it wouldn't be drawn normally. This is used
2680 when a string preceding S draws into the background of S. */
2681
2682 static void
2683 x_draw_glyph_string_background (s, force_p)
2684 struct glyph_string *s;
2685 int force_p;
2686 {
2687 /* Nothing to do if background has already been drawn or if it
2688 shouldn't be drawn in the first place. */
2689 if (!s->background_filled_p)
2690 {
2691 if (s->cmpcharp
2692 && s->gidx > 0
2693 && !s->font_not_found_p
2694 && !s->extends_to_end_of_line_p)
2695 {
2696 /* Don't draw background for glyphs of a composite
2697 characters, except for the first one. */
2698 s->background_filled_p = 1;
2699 }
2700 else if (s->stippled_p)
2701 {
2702 /* Fill background with a stipple pattern. */
2703 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2704 XFillRectangle (s->display, s->window, s->gc, s->x,
2705 s->y + s->face->box_line_width,
2706 s->background_width,
2707 s->height - 2 * s->face->box_line_width);
2708 XSetFillStyle (s->display, s->gc, FillSolid);
2709 s->background_filled_p = 1;
2710 }
2711 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2712 || s->font_not_found_p
2713 || s->extends_to_end_of_line_p
2714 || s->cmpcharp
2715 || force_p)
2716 {
2717 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2718 s->background_width,
2719 s->height - 2 * s->face->box_line_width);
2720 s->background_filled_p = 1;
2721 }
2722 }
2723 }
2724
2725
2726 /* Draw the foreground of glyph string S. */
2727
2728 static void
2729 x_draw_glyph_string_foreground (s)
2730 struct glyph_string *s;
2731 {
2732 int i, x;
2733
2734 /* If first glyph of S has a left box line, start drawing the text
2735 of S to the right of that box line. */
2736 if (s->face->box != FACE_NO_BOX
2737 && s->first_glyph->left_box_line_p)
2738 x = s->x + s->face->box_line_width;
2739 else
2740 x = s->x;
2741
2742 if (s->cmpcharp == NULL)
2743 {
2744 /* Not a composite character. Draw characters of S as
2745 rectangles if S's font could not be loaded. */
2746 if (s->font_not_found_p)
2747 {
2748 for (i = 0; i < s->nchars; ++i)
2749 {
2750 struct glyph *g = s->first_glyph + i;
2751 XDrawRectangle (s->display, s->window,
2752 s->gc, x, s->y, g->pixel_width - 1,
2753 s->height - 1);
2754 x += g->pixel_width;
2755 }
2756 }
2757 else
2758 {
2759 char *char1b = (char *) s->char2b;
2760
2761 /* If we can use 8-bit functions, condense S->char2b. */
2762 if (!s->two_byte_p)
2763 for (i = 0; i < s->nchars; ++i)
2764 char1b[i] = s->char2b[i].byte2;
2765
2766 /* Draw text with XDrawString if background has already been
2767 filled. Otherwise, use XDrawImageString. (Note that
2768 XDrawImageString is usually faster than XDrawString.)
2769 Always use XDrawImageString when drawing the cursor so
2770 that there is no chance that characters under a box
2771 cursor are invisible. */
2772 if (s->for_overlaps_p
2773 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2774 {
2775 /* Draw characters with 16-bit or 8-bit functions. */
2776 if (s->two_byte_p)
2777 XDrawString16 (s->display, s->window, s->gc, x, s->ybase,
2778 s->char2b, s->nchars);
2779 else
2780 XDrawString (s->display, s->window, s->gc, x, s->ybase,
2781 char1b, s->nchars);
2782 }
2783 else
2784 {
2785 if (s->two_byte_p)
2786 XDrawImageString16 (s->display, s->window, s->gc,
2787 x, s->ybase, s->char2b, s->nchars);
2788 else
2789 XDrawImageString (s->display, s->window, s->gc,
2790 x, s->ybase, char1b, s->nchars);
2791 }
2792 }
2793 }
2794 else
2795 {
2796 /* S is a glyph string for a composite character. S->gidx is the
2797 index of the first character drawn in the vector
2798 S->cmpcharp->glyph. S->gidx == 0 means we are drawing the
2799 very first component character of a composite char. */
2800
2801 /* Draw a single rectangle for the composite character if S's
2802 font could not be loaded. */
2803 if (s->font_not_found_p && s->gidx == 0)
2804 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
2805 s->width - 1, s->height - 1);
2806 else
2807 {
2808 XCharStruct *pcm;
2809 int relative_compose, default_ascent, i;
2810 int highest = 0, lowest = 0;
2811
2812 /* The value of font_info my be null if we couldn't find it
2813 in x_get_char_face_and_encoding. */
2814 if (s->cmpcharp->cmp_rule == NULL && s->font_info)
2815 {
2816 relative_compose = s->font_info->relative_compose;
2817 default_ascent = s->font_info->default_ascent;
2818 }
2819 else
2820 relative_compose = default_ascent = 0;
2821
2822 if ((s->cmpcharp->cmp_rule || relative_compose)
2823 && s->gidx == 0)
2824 {
2825 /* This is the first character. Initialize variables.
2826 Highest is the highest position of glyphs ever
2827 written, lowest the lowest position. */
2828 int x_offset = 0;
2829 int first_ch = s->first_glyph->u.ch.code;
2830
2831 if (default_ascent
2832 && CHAR_TABLE_P (Vuse_default_ascent)
2833 && !NILP (Faref (Vuse_default_ascent, first_ch)))
2834 {
2835 highest = default_ascent;
2836 lowest = 0;
2837 }
2838 else
2839 {
2840 pcm = PER_CHAR_METRIC (s->font, s->char2b);
2841 highest = pcm->ascent + 1;
2842 lowest = - pcm->descent;
2843 }
2844
2845 if (s->cmpcharp->cmp_rule)
2846 x_offset = (s->cmpcharp->col_offset[0]
2847 * FONT_WIDTH (s->f->output_data.x->font));
2848
2849 /* Draw the first character at the normal position. */
2850 XDrawString16 (s->display, s->window, s->gc,
2851 x + x_offset,
2852 s->ybase, s->char2b, 1);
2853 i = 1;
2854 ++s->gidx;
2855 }
2856 else
2857 i = 0;
2858
2859 for (; i < s->nchars; i++, ++s->gidx)
2860 {
2861 int x_offset = 0, y_offset = 0;
2862
2863 if (relative_compose)
2864 {
2865 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
2866 if (NILP (Vignore_relative_composition)
2867 || NILP (Faref (Vignore_relative_composition,
2868 make_number (s->cmpcharp->glyph[s->gidx]))))
2869 {
2870 if (- pcm->descent >= relative_compose)
2871 {
2872 /* Draw above the current glyphs. */
2873 y_offset = highest + pcm->descent;
2874 highest += pcm->ascent + pcm->descent;
2875 }
2876 else if (pcm->ascent <= 0)
2877 {
2878 /* Draw beneath the current glyphs. */
2879 y_offset = lowest - pcm->ascent;
2880 lowest -= pcm->ascent + pcm->descent;
2881 }
2882 }
2883 else
2884 {
2885 /* Draw the glyph at normal position. If
2886 it sticks out of HIGHEST or LOWEST,
2887 update them appropriately. */
2888 if (pcm->ascent > highest)
2889 highest = pcm->ascent;
2890 else if (- pcm->descent < lowest)
2891 lowest = - pcm->descent;
2892 }
2893 }
2894 else if (s->cmpcharp->cmp_rule)
2895 {
2896 int gref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) / 9;
2897 int nref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) % 9;
2898 int bottom, top;
2899
2900 /* Re-encode GREF and NREF so that they specify
2901 only Y-axis information:
2902 0:top, 1:base, 2:bottom, 3:center */
2903 gref = gref / 3 + (gref == 4) * 2;
2904 nref = nref / 3 + (nref == 4) * 2;
2905
2906 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
2907 bottom = ((gref == 0 ? highest : gref == 1 ? 0
2908 : gref == 2 ? lowest
2909 : (highest + lowest) / 2)
2910 - (nref == 0 ? pcm->ascent + pcm->descent
2911 : nref == 1 ? pcm->descent : nref == 2 ? 0
2912 : (pcm->ascent + pcm->descent) / 2));
2913 top = bottom + (pcm->ascent + pcm->descent);
2914 if (top > highest)
2915 highest = top;
2916 if (bottom < lowest)
2917 lowest = bottom;
2918 y_offset = bottom + pcm->descent;
2919 x_offset = (s->cmpcharp->col_offset[s->gidx]
2920 * FONT_WIDTH (FRAME_FONT (s->f)));
2921 }
2922
2923 XDrawString16 (s->display, s->window, s->gc,
2924 x + x_offset, s->ybase - y_offset,
2925 s->char2b + i, 1);
2926 }
2927 }
2928 }
2929 }
2930
2931
2932 #ifdef USE_X_TOOLKIT
2933
2934 /* Allocate the color COLOR->pixel on the screen and display of
2935 widget WIDGET in colormap CMAP. If an exact match cannot be
2936 allocated, try the nearest color available. Value is non-zero
2937 if successful. This is called from lwlib. */
2938
2939 int
2940 x_alloc_nearest_color_for_widget (widget, cmap, color)
2941 Widget widget;
2942 Colormap cmap;
2943 XColor *color;
2944 {
2945 struct frame *f;
2946 struct x_display_info *dpyinfo;
2947 Lisp_Object tail;
2948
2949 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2950
2951 /* Find the top-level shell of the widget. Note that this function
2952 can be called when the widget is not yet realized, so XtWindow
2953 (widget) == 0. That's the reason we can't simply use
2954 x_any_window_to_frame. */
2955 while (!XtIsTopLevelShell (widget))
2956 widget = XtParent (widget);
2957
2958 /* Look for a frame with that top-level widget. Allocate the color
2959 on that frame to get the right gamma correction value. */
2960 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2961 if (GC_FRAMEP (XCAR (tail))
2962 && (f = XFRAME (XCAR (tail)),
2963 (f->output_data.nothing != 1
2964 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2965 && f->output_data.x->widget == widget)
2966 return x_alloc_nearest_color (f, cmap, color);
2967
2968 abort ();
2969 }
2970
2971 #endif /* USE_X_TOOLKIT */
2972
2973
2974 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2975 CMAP. If an exact match can't be allocated, try the nearest color
2976 available. Value is non-zero if successful. Set *COLOR to the
2977 color allocated. */
2978
2979 int
2980 x_alloc_nearest_color (f, cmap, color)
2981 struct frame *f;
2982 Colormap cmap;
2983 XColor *color;
2984 {
2985 Display *display = FRAME_X_DISPLAY (f);
2986 Screen *screen = FRAME_X_SCREEN (f);
2987 int rc;
2988
2989 gamma_correct (f, color);
2990 rc = XAllocColor (display, cmap, color);
2991 if (rc == 0)
2992 {
2993 /* If we got to this point, the colormap is full, so we're going
2994 to try to get the next closest color. The algorithm used is
2995 a least-squares matching, which is what X uses for closest
2996 color matching with StaticColor visuals. */
2997 int nearest, i;
2998 unsigned long nearest_delta = ~0;
2999 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3000 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3001
3002 for (i = 0; i < ncells; ++i)
3003 cells[i].pixel = i;
3004 XQueryColors (display, cmap, cells, ncells);
3005
3006 for (nearest = i = 0; i < ncells; ++i)
3007 {
3008 long dred = (color->red >> 8) - (cells[i].red >> 8);
3009 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3010 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3011 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3012
3013 if (delta < nearest_delta)
3014 {
3015 nearest = i;
3016 nearest_delta = delta;
3017 }
3018 }
3019
3020 color->red = cells[nearest].red;
3021 color->green = cells[nearest].green;
3022 color->blue = cells[nearest].blue;
3023 rc = XAllocColor (display, cmap, color);
3024 }
3025
3026 return rc;
3027 }
3028
3029
3030 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3031 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3032 If this produces the same color as PIXEL, try a color where all RGB
3033 values have DELTA added. Return the allocated color in *PIXEL.
3034 DISPLAY is the X display, CMAP is the colormap to operate on.
3035 Value is non-zero if successful. */
3036
3037 static int
3038 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3039 struct frame *f;
3040 Display *display;
3041 Colormap cmap;
3042 unsigned long *pixel;
3043 double factor;
3044 int delta;
3045 {
3046 XColor color, new;
3047 int success_p;
3048
3049 /* Get RGB color values. */
3050 color.pixel = *pixel;
3051 XQueryColor (display, cmap, &color);
3052
3053 /* Change RGB values by specified FACTOR. Avoid overflow! */
3054 xassert (factor >= 0);
3055 new.red = min (0xffff, factor * color.red);
3056 new.green = min (0xffff, factor * color.green);
3057 new.blue = min (0xffff, factor * color.blue);
3058
3059 /* Try to allocate the color. */
3060 success_p = x_alloc_nearest_color (f, cmap, &new);
3061 if (success_p)
3062 {
3063 if (new.pixel == *pixel)
3064 {
3065 /* If we end up with the same color as before, try adding
3066 delta to the RGB values. */
3067 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
3068
3069 /* If display has an immutable color map, freeing colors is
3070 not necessary and some servers don't allow it. So don't
3071 do it. */
3072 if (class != StaticColor
3073 && class != StaticGray
3074 && class != TrueColor)
3075 XFreeColors (display, cmap, &new.pixel, 1, 0);
3076
3077 new.red = min (0xffff, delta + color.red);
3078 new.green = min (0xffff, delta + color.green);
3079 new.blue = min (0xffff, delta + color.blue);
3080 success_p = x_alloc_nearest_color (f, cmap, &new);
3081 }
3082 else
3083 success_p = 1;
3084 *pixel = new.pixel;
3085 }
3086
3087 return success_p;
3088 }
3089
3090
3091 /* Set up the foreground color for drawing relief lines of glyph
3092 string S. RELIEF is a pointer to a struct relief containing the GC
3093 with which lines will be drawn. Use a color that is FACTOR or
3094 DELTA lighter or darker than the relief's background which is found
3095 in S->f->output_data.x->relief_background. If such a color cannot
3096 be allocated, use DEFAULT_PIXEL, instead. */
3097
3098 static void
3099 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3100 struct frame *f;
3101 struct relief *relief;
3102 double factor;
3103 int delta;
3104 unsigned long default_pixel;
3105 {
3106 XGCValues xgcv;
3107 struct x_output *di = f->output_data.x;
3108 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3109 unsigned long pixel;
3110 unsigned long background = di->relief_background;
3111 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
3112 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3113 Display *dpy = FRAME_X_DISPLAY (f);
3114
3115 xgcv.graphics_exposures = False;
3116 xgcv.line_width = 1;
3117
3118 /* Free previously allocated color. The color cell will be reused
3119 when it has been freed as many times as it was allocated, so this
3120 doesn't affect faces using the same colors. */
3121 if (relief->gc
3122 && relief->allocated_p)
3123 {
3124 /* If display has an immutable color map, freeing colors is not
3125 necessary and some servers don't allow it. So don't do it. */
3126 int class = dpyinfo->visual->class;
3127 if (class != StaticColor
3128 && class != StaticGray
3129 && class != TrueColor)
3130 XFreeColors (dpy, cmap, &relief->pixel, 1, 0);
3131 relief->allocated_p = 0;
3132 }
3133
3134 /* Allocate new color. */
3135 xgcv.foreground = default_pixel;
3136 pixel = background;
3137 if (dpyinfo->n_planes != 1
3138 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3139 {
3140 relief->allocated_p = 1;
3141 xgcv.foreground = relief->pixel = pixel;
3142 }
3143
3144 if (relief->gc == 0)
3145 {
3146 xgcv.stipple = dpyinfo->gray;
3147 mask |= GCStipple;
3148 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3149 }
3150 else
3151 XChangeGC (dpy, relief->gc, mask, &xgcv);
3152 }
3153
3154
3155 /* Set up colors for the relief lines around glyph string S. */
3156
3157 static void
3158 x_setup_relief_colors (s)
3159 struct glyph_string *s;
3160 {
3161 struct x_output *di = s->f->output_data.x;
3162 unsigned long color;
3163
3164 if (s->face->use_box_color_for_shadows_p)
3165 color = s->face->box_color;
3166 else
3167 {
3168 XGCValues xgcv;
3169
3170 /* Get the background color of the face. */
3171 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3172 color = xgcv.background;
3173 }
3174
3175 if (di->white_relief.gc == 0
3176 || color != di->relief_background)
3177 {
3178 di->relief_background = color;
3179 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3180 WHITE_PIX_DEFAULT (s->f));
3181 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3182 BLACK_PIX_DEFAULT (s->f));
3183 }
3184 }
3185
3186
3187 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3188 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3189 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3190 relief. LEFT_P non-zero means draw a relief on the left side of
3191 the rectangle. RIGHT_P non-zero means draw a relief on the right
3192 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3193 when drawing. */
3194
3195 static void
3196 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3197 raised_p, left_p, right_p, clip_rect)
3198 struct frame *f;
3199 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3200 XRectangle *clip_rect;
3201 {
3202 int i;
3203 GC gc;
3204
3205 if (raised_p)
3206 gc = f->output_data.x->white_relief.gc;
3207 else
3208 gc = f->output_data.x->black_relief.gc;
3209 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3210
3211 /* Top. */
3212 for (i = 0; i < width; ++i)
3213 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3214 left_x + i * left_p, top_y + i,
3215 right_x + 1 - i * right_p, top_y + i);
3216
3217 /* Left. */
3218 if (left_p)
3219 for (i = 0; i < width; ++i)
3220 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3221 left_x + i, top_y + i, left_x + i, bottom_y - i);
3222
3223 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3224 if (raised_p)
3225 gc = f->output_data.x->black_relief.gc;
3226 else
3227 gc = f->output_data.x->white_relief.gc;
3228 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3229
3230 /* Bottom. */
3231 for (i = 0; i < width; ++i)
3232 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3233 left_x + i * left_p, bottom_y - i,
3234 right_x + 1 - i * right_p, bottom_y - i);
3235
3236 /* Right. */
3237 if (right_p)
3238 for (i = 0; i < width; ++i)
3239 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3240 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3241
3242 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3243 }
3244
3245
3246 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3247 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3248 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3249 left side of the rectangle. RIGHT_P non-zero means draw a line
3250 on the right side of the rectangle. CLIP_RECT is the clipping
3251 rectangle to use when drawing. */
3252
3253 static void
3254 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3255 left_p, right_p, clip_rect)
3256 struct glyph_string *s;
3257 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3258 XRectangle *clip_rect;
3259 {
3260 XGCValues xgcv;
3261
3262 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3263 XSetForeground (s->display, s->gc, s->face->box_color);
3264 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3265
3266 /* Top. */
3267 XFillRectangle (s->display, s->window, s->gc,
3268 left_x, top_y, right_x - left_x, width);
3269
3270 /* Left. */
3271 if (left_p)
3272 XFillRectangle (s->display, s->window, s->gc,
3273 left_x, top_y, width, bottom_y - top_y);
3274
3275 /* Bottom. */
3276 XFillRectangle (s->display, s->window, s->gc,
3277 left_x, bottom_y - width, right_x - left_x, width);
3278
3279 /* Right. */
3280 if (right_p)
3281 XFillRectangle (s->display, s->window, s->gc,
3282 right_x - width, top_y, width, bottom_y - top_y);
3283
3284 XSetForeground (s->display, s->gc, xgcv.foreground);
3285 XSetClipMask (s->display, s->gc, None);
3286 }
3287
3288
3289 /* Draw a box around glyph string S. */
3290
3291 static void
3292 x_draw_glyph_string_box (s)
3293 struct glyph_string *s;
3294 {
3295 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3296 int left_p, right_p;
3297 struct glyph *last_glyph;
3298 XRectangle clip_rect;
3299
3300 last_x = window_box_right (s->w, s->area);
3301 if (s->row->full_width_p
3302 && !s->w->pseudo_window_p)
3303 {
3304 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3305 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3306 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3307 }
3308
3309 /* The glyph that may have a right box line. */
3310 last_glyph = (s->cmpcharp || s->img
3311 ? s->first_glyph
3312 : s->first_glyph + s->nchars - 1);
3313
3314 width = s->face->box_line_width;
3315 raised_p = s->face->box == FACE_RAISED_BOX;
3316 left_x = s->x;
3317 right_x = ((s->row->full_width_p
3318 ? last_x - 1
3319 : min (last_x, s->x + s->background_width) - 1));
3320 top_y = s->y;
3321 bottom_y = top_y + s->height - 1;
3322
3323 left_p = (s->first_glyph->left_box_line_p
3324 || (s->hl == DRAW_MOUSE_FACE
3325 && (s->prev == NULL
3326 || s->prev->hl != s->hl)));
3327 right_p = (last_glyph->right_box_line_p
3328 || (s->hl == DRAW_MOUSE_FACE
3329 && (s->next == NULL
3330 || s->next->hl != s->hl)));
3331
3332 x_get_glyph_string_clip_rect (s, &clip_rect);
3333
3334 if (s->face->box == FACE_SIMPLE_BOX)
3335 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3336 left_p, right_p, &clip_rect);
3337 else
3338 {
3339 x_setup_relief_colors (s);
3340 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3341 width, raised_p, left_p, right_p, &clip_rect);
3342 }
3343 }
3344
3345
3346 /* Draw foreground of image glyph string S. */
3347
3348 static void
3349 x_draw_image_foreground (s)
3350 struct glyph_string *s;
3351 {
3352 int x;
3353 int y = s->ybase - IMAGE_ASCENT (s->img);
3354
3355 /* If first glyph of S has a left box line, start drawing it to the
3356 right of that line. */
3357 if (s->face->box != FACE_NO_BOX
3358 && s->first_glyph->left_box_line_p)
3359 x = s->x + s->face->box_line_width;
3360 else
3361 x = s->x;
3362
3363 /* If there is a margin around the image, adjust x- and y-position
3364 by that margin. */
3365 if (s->img->margin)
3366 {
3367 x += s->img->margin;
3368 y += s->img->margin;
3369 }
3370
3371 if (s->img->pixmap)
3372 {
3373 if (s->img->mask)
3374 {
3375 /* We can't set both a clip mask and use XSetClipRectangles
3376 because the latter also sets a clip mask. We also can't
3377 trust on the shape extension to be available
3378 (XShapeCombineRegion). So, compute the rectangle to draw
3379 manually. */
3380 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3381 | GCFunction);
3382 XGCValues xgcv;
3383 XRectangle clip_rect, image_rect, r;
3384
3385 xgcv.clip_mask = s->img->mask;
3386 xgcv.clip_x_origin = x;
3387 xgcv.clip_y_origin = y;
3388 xgcv.function = GXcopy;
3389 XChangeGC (s->display, s->gc, mask, &xgcv);
3390
3391 x_get_glyph_string_clip_rect (s, &clip_rect);
3392 image_rect.x = x;
3393 image_rect.y = y;
3394 image_rect.width = s->img->width;
3395 image_rect.height = s->img->height;
3396 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3397 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3398 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3399 }
3400 else
3401 {
3402 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3403 0, 0, s->img->width, s->img->height, x, y);
3404
3405 /* When the image has a mask, we can expect that at
3406 least part of a mouse highlight or a block cursor will
3407 be visible. If the image doesn't have a mask, make
3408 a block cursor visible by drawing a rectangle around
3409 the image. I believe it's looking better if we do
3410 nothing here for mouse-face. */
3411 if (s->hl == DRAW_CURSOR)
3412 XDrawRectangle (s->display, s->window, s->gc, x, y,
3413 s->img->width - 1, s->img->height - 1);
3414 }
3415 }
3416 else
3417 /* Draw a rectangle if image could not be loaded. */
3418 XDrawRectangle (s->display, s->window, s->gc, x, y,
3419 s->img->width - 1, s->img->height - 1);
3420 }
3421
3422
3423 /* Draw a relief around the image glyph string S. */
3424
3425 static void
3426 x_draw_image_relief (s)
3427 struct glyph_string *s;
3428 {
3429 int x0, y0, x1, y1, thick, raised_p;
3430 XRectangle r;
3431 int x;
3432 int y = s->ybase - IMAGE_ASCENT (s->img);
3433
3434 /* If first glyph of S has a left box line, start drawing it to the
3435 right of that line. */
3436 if (s->face->box != FACE_NO_BOX
3437 && s->first_glyph->left_box_line_p)
3438 x = s->x + s->face->box_line_width;
3439 else
3440 x = s->x;
3441
3442 /* If there is a margin around the image, adjust x- and y-position
3443 by that margin. */
3444 if (s->img->margin)
3445 {
3446 x += s->img->margin;
3447 y += s->img->margin;
3448 }
3449
3450 if (s->hl == DRAW_IMAGE_SUNKEN
3451 || s->hl == DRAW_IMAGE_RAISED)
3452 {
3453 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3454 raised_p = s->hl == DRAW_IMAGE_RAISED;
3455 }
3456 else
3457 {
3458 thick = abs (s->img->relief);
3459 raised_p = s->img->relief > 0;
3460 }
3461
3462 x0 = x - thick;
3463 y0 = y - thick;
3464 x1 = x + s->img->width + thick - 1;
3465 y1 = y + s->img->height + thick - 1;
3466
3467 x_setup_relief_colors (s);
3468 x_get_glyph_string_clip_rect (s, &r);
3469 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3470 }
3471
3472
3473 /* Draw the foreground of image glyph string S to PIXMAP. */
3474
3475 static void
3476 x_draw_image_foreground_1 (s, pixmap)
3477 struct glyph_string *s;
3478 Pixmap pixmap;
3479 {
3480 int x;
3481 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3482
3483 /* If first glyph of S has a left box line, start drawing it to the
3484 right of that line. */
3485 if (s->face->box != FACE_NO_BOX
3486 && s->first_glyph->left_box_line_p)
3487 x = s->face->box_line_width;
3488 else
3489 x = 0;
3490
3491 /* If there is a margin around the image, adjust x- and y-position
3492 by that margin. */
3493 if (s->img->margin)
3494 {
3495 x += s->img->margin;
3496 y += s->img->margin;
3497 }
3498
3499 if (s->img->pixmap)
3500 {
3501 if (s->img->mask)
3502 {
3503 /* We can't set both a clip mask and use XSetClipRectangles
3504 because the latter also sets a clip mask. We also can't
3505 trust on the shape extension to be available
3506 (XShapeCombineRegion). So, compute the rectangle to draw
3507 manually. */
3508 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3509 | GCFunction);
3510 XGCValues xgcv;
3511
3512 xgcv.clip_mask = s->img->mask;
3513 xgcv.clip_x_origin = x;
3514 xgcv.clip_y_origin = y;
3515 xgcv.function = GXcopy;
3516 XChangeGC (s->display, s->gc, mask, &xgcv);
3517
3518 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3519 0, 0, s->img->width, s->img->height, x, y);
3520 XSetClipMask (s->display, s->gc, None);
3521 }
3522 else
3523 {
3524 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3525 0, 0, s->img->width, s->img->height, x, y);
3526
3527 /* When the image has a mask, we can expect that at
3528 least part of a mouse highlight or a block cursor will
3529 be visible. If the image doesn't have a mask, make
3530 a block cursor visible by drawing a rectangle around
3531 the image. I believe it's looking better if we do
3532 nothing here for mouse-face. */
3533 if (s->hl == DRAW_CURSOR)
3534 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3535 s->img->width - 1, s->img->height - 1);
3536 }
3537 }
3538 else
3539 /* Draw a rectangle if image could not be loaded. */
3540 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3541 s->img->width - 1, s->img->height - 1);
3542 }
3543
3544
3545 /* Draw part of the background of glyph string S. X, Y, W, and H
3546 give the rectangle to draw. */
3547
3548 static void
3549 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3550 struct glyph_string *s;
3551 int x, y, w, h;
3552 {
3553 if (s->stippled_p)
3554 {
3555 /* Fill background with a stipple pattern. */
3556 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3557 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3558 XSetFillStyle (s->display, s->gc, FillSolid);
3559 }
3560 else
3561 x_clear_glyph_string_rect (s, x, y, w, h);
3562 }
3563
3564
3565 /* Draw image glyph string S.
3566
3567 s->y
3568 s->x +-------------------------
3569 | s->face->box
3570 |
3571 | +-------------------------
3572 | | s->img->margin
3573 | |
3574 | | +-------------------
3575 | | | the image
3576
3577 */
3578
3579 static void
3580 x_draw_image_glyph_string (s)
3581 struct glyph_string *s;
3582 {
3583 int x, y;
3584 int box_line_width = s->face->box_line_width;
3585 int margin = s->img->margin;
3586 int height;
3587 Pixmap pixmap = None;
3588
3589 height = s->height - 2 * box_line_width;
3590
3591 /* Fill background with face under the image. Do it only if row is
3592 taller than image or if image has a clip mask to reduce
3593 flickering. */
3594 s->stippled_p = s->face->stipple != 0;
3595 if (height > s->img->height
3596 || margin
3597 || s->img->mask
3598 || s->img->pixmap == 0
3599 || s->width != s->background_width)
3600 {
3601 if (box_line_width && s->first_glyph->left_box_line_p)
3602 x = s->x + box_line_width;
3603 else
3604 x = s->x;
3605
3606 y = s->y + box_line_width;
3607
3608 if (s->img->mask)
3609 {
3610 /* Create a pixmap as large as the glyph string Fill it with
3611 the background color. Copy the image to it, using its
3612 mask. Copy the temporary pixmap to the display. */
3613 Screen *screen = FRAME_X_SCREEN (s->f);
3614 int depth = DefaultDepthOfScreen (screen);
3615
3616 /* Create a pixmap as large as the glyph string. */
3617 pixmap = XCreatePixmap (s->display, s->window,
3618 s->background_width,
3619 s->height, depth);
3620
3621 /* Don't clip in the following because we're working on the
3622 pixmap. */
3623 XSetClipMask (s->display, s->gc, None);
3624
3625 /* Fill the pixmap with the background color/stipple. */
3626 if (s->stippled_p)
3627 {
3628 /* Fill background with a stipple pattern. */
3629 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3630 XFillRectangle (s->display, pixmap, s->gc,
3631 0, 0, s->background_width, s->height);
3632 XSetFillStyle (s->display, s->gc, FillSolid);
3633 }
3634 else
3635 {
3636 XGCValues xgcv;
3637 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3638 &xgcv);
3639 XSetForeground (s->display, s->gc, xgcv.background);
3640 XFillRectangle (s->display, pixmap, s->gc,
3641 0, 0, s->background_width, s->height);
3642 XSetForeground (s->display, s->gc, xgcv.foreground);
3643 }
3644 }
3645 else
3646 /* Implementation idea: Is it possible to construct a mask?
3647 We could look at the color at the margins of the image, and
3648 say that this color is probably the background color of the
3649 image. */
3650 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3651
3652 s->background_filled_p = 1;
3653 }
3654
3655 /* Draw the foreground. */
3656 if (pixmap != None)
3657 {
3658 x_draw_image_foreground_1 (s, pixmap);
3659 x_set_glyph_string_clipping (s);
3660 XCopyArea (s->display, pixmap, s->window, s->gc,
3661 0, 0, s->background_width, s->height, s->x, s->y);
3662 XFreePixmap (s->display, pixmap);
3663 }
3664 else
3665 x_draw_image_foreground (s);
3666
3667 /* If we must draw a relief around the image, do it. */
3668 if (s->img->relief
3669 || s->hl == DRAW_IMAGE_RAISED
3670 || s->hl == DRAW_IMAGE_SUNKEN)
3671 x_draw_image_relief (s);
3672 }
3673
3674
3675 /* Draw stretch glyph string S. */
3676
3677 static void
3678 x_draw_stretch_glyph_string (s)
3679 struct glyph_string *s;
3680 {
3681 xassert (s->first_glyph->type == STRETCH_GLYPH);
3682 s->stippled_p = s->face->stipple != 0;
3683
3684 if (s->hl == DRAW_CURSOR
3685 && !x_stretch_cursor_p)
3686 {
3687 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3688 as wide as the stretch glyph. */
3689 int width = min (CANON_X_UNIT (s->f), s->background_width);
3690
3691 /* Draw cursor. */
3692 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3693
3694 /* Clear rest using the GC of the original non-cursor face. */
3695 if (width < s->background_width)
3696 {
3697 GC gc = s->face->gc;
3698 int x = s->x + width, y = s->y;
3699 int w = s->background_width - width, h = s->height;
3700 XRectangle r;
3701
3702 x_get_glyph_string_clip_rect (s, &r);
3703 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
3704
3705 if (s->face->stipple)
3706 {
3707 /* Fill background with a stipple pattern. */
3708 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3709 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3710 XSetFillStyle (s->display, gc, FillSolid);
3711 }
3712 else
3713 {
3714 XGCValues xgcv;
3715 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3716 XSetForeground (s->display, gc, xgcv.background);
3717 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3718 XSetForeground (s->display, gc, xgcv.foreground);
3719 }
3720 }
3721 }
3722 else
3723 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3724 s->height);
3725
3726 s->background_filled_p = 1;
3727 }
3728
3729
3730 /* Draw glyph string S. */
3731
3732 static void
3733 x_draw_glyph_string (s)
3734 struct glyph_string *s;
3735 {
3736 /* If S draws into the background of its successor, draw the
3737 background of the successor first so that S can draw into it.
3738 This makes S->next use XDrawString instead of XDrawImageString. */
3739 if (s->next && s->right_overhang && !s->for_overlaps_p)
3740 {
3741 xassert (s->next->img == NULL);
3742 x_set_glyph_string_gc (s->next);
3743 x_set_glyph_string_clipping (s->next);
3744 x_draw_glyph_string_background (s->next, 1);
3745 }
3746
3747 /* Set up S->gc, set clipping and draw S. */
3748 x_set_glyph_string_gc (s);
3749 x_set_glyph_string_clipping (s);
3750
3751 switch (s->first_glyph->type)
3752 {
3753 case IMAGE_GLYPH:
3754 x_draw_image_glyph_string (s);
3755 break;
3756
3757 case STRETCH_GLYPH:
3758 x_draw_stretch_glyph_string (s);
3759 break;
3760
3761 case CHAR_GLYPH:
3762 if (s->for_overlaps_p)
3763 s->background_filled_p = 1;
3764 else
3765 x_draw_glyph_string_background (s, 0);
3766 x_draw_glyph_string_foreground (s);
3767 break;
3768
3769 default:
3770 abort ();
3771 }
3772
3773 if (!s->for_overlaps_p)
3774 {
3775 /* Draw underline. */
3776 if (s->face->underline_p)
3777 {
3778 unsigned long dy, h;
3779
3780 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3781 h = 1;
3782 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
3783 dy = s->height - h;
3784
3785 if (s->face->underline_defaulted_p)
3786 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3787 s->width, h);
3788 else
3789 {
3790 XGCValues xgcv;
3791 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3792 XSetForeground (s->display, s->gc, s->face->underline_color);
3793 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3794 s->width, h);
3795 XSetForeground (s->display, s->gc, xgcv.foreground);
3796 }
3797 }
3798
3799 /* Draw overline. */
3800 if (s->face->overline_p)
3801 {
3802 unsigned long dy = 0, h = 1;
3803
3804 if (s->face->overline_color_defaulted_p)
3805 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3806 s->width, h);
3807 else
3808 {
3809 XGCValues xgcv;
3810 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3811 XSetForeground (s->display, s->gc, s->face->overline_color);
3812 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3813 s->width, h);
3814 XSetForeground (s->display, s->gc, xgcv.foreground);
3815 }
3816 }
3817
3818 /* Draw strike-through. */
3819 if (s->face->strike_through_p)
3820 {
3821 unsigned long h = 1;
3822 unsigned long dy = (s->height - h) / 2;
3823
3824 if (s->face->strike_through_color_defaulted_p)
3825 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3826 s->width, h);
3827 else
3828 {
3829 XGCValues xgcv;
3830 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3831 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3832 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3833 s->width, h);
3834 XSetForeground (s->display, s->gc, xgcv.foreground);
3835 }
3836 }
3837
3838 /* Draw relief. */
3839 if (s->face->box != FACE_NO_BOX)
3840 x_draw_glyph_string_box (s);
3841 }
3842
3843 /* Reset clipping. */
3844 XSetClipMask (s->display, s->gc, None);
3845 }
3846
3847
3848 /* A work-list entry used during the construction of glyph_string
3849 structures for a composite character. */
3850
3851 struct work
3852 {
3853 /* Pointer to composite char info defining has the composite
3854 character is drawn. */
3855 struct cmpchar_info *cmpcharp;
3856
3857 /* Start index in compcharp->glyph[]. */
3858 int gidx;
3859
3860 /* Next in stack. */
3861 struct work *next;
3862 };
3863
3864
3865 static void x_fill_composite_glyph_string P_ ((struct glyph_string *,
3866 int, struct work **,
3867 struct work **, int));
3868
3869
3870 /* Load glyph string S with information from the top of *STACK for a
3871 composite character. FACE_ID is the id of the face in which S is
3872 drawn. *NEW is a pointer to a struct work not on the stack, that
3873 can be used if this function needs to push a new structure on the
3874 stack. If it uses it, *NEW is set to null. OVERLAPS_P non-zero
3875 means S should draw the foreground only, and use its lines physical
3876 height for clipping. */
3877
3878 static void
3879 x_fill_composite_glyph_string (s, face_id, stack, new, overlaps_p)
3880 struct glyph_string *s;
3881 int face_id;
3882 struct work **stack, **new;
3883 int overlaps_p;
3884 {
3885 int i, c;
3886 struct work *work;
3887
3888 xassert (s && *new && *stack);
3889
3890 s->for_overlaps_p = 1;
3891
3892 /* Pop the work stack. */
3893 work = *stack;
3894 *stack = work->next;
3895
3896 /* For all glyphs of cmpcharp->glyph, starting at the offset
3897 work->offset, until we reach the end of the definition or
3898 encounter another composite char, get the font and face to use,
3899 and add it to S. */
3900 for (i = work->gidx; i < work->cmpcharp->glyph_len; ++i)
3901 {
3902 c = FAST_GLYPH_CHAR (work->cmpcharp->glyph[i]);
3903 if (CHAR_CHARSET (c) == CHARSET_COMPOSITION)
3904 break;
3905 s->face = x_get_char_face_and_encoding (s->f, c, face_id,
3906 s->char2b + s->nchars, 1);
3907 s->font = s->face->font;
3908 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3909 ++s->nchars;
3910 }
3911
3912 /* If we find another composite char in the glyph definition of
3913 work->cmpcharp, put back the rest of the glyphs on the work
3914 stack, and make a new entry for the composite char. */
3915 if (i < work->cmpcharp->glyph_len)
3916 {
3917 /* Push back an unprocessed rest of this glyph spec. */
3918 if (i < work->cmpcharp->glyph_len - 1)
3919 {
3920 work->gidx = i + 1;
3921 work->next = *stack;
3922 *stack = work;
3923 work = *new;
3924 *new = NULL;
3925 }
3926
3927 /* Make an entry for the composite char on the work stack. */
3928 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)];
3929 work->gidx = 0;
3930 work->next = *stack;
3931 *stack = work;
3932 }
3933
3934 /* The width of this glyph string equals the width of the first
3935 glyph. All characters are drawn at the same x-position. */
3936 s->width = s->first_glyph->pixel_width;
3937
3938 /* If the specified font could not be loaded, use the frame's
3939 default font, but record the fact that we couldn't load it in
3940 the glyph string so that we can draw rectangles for the
3941 characters of the glyph string. */
3942 if (s->font == NULL)
3943 {
3944 s->font_not_found_p = 1;
3945 s->font = FRAME_FONT (s->f);
3946 }
3947
3948 /* Adjust base line for subscript/superscript text. */
3949 s->ybase += s->first_glyph->voffset;
3950
3951 xassert (s->face && s->face->gc);
3952
3953 /* This glyph string must always be drawn with 16-bit functions. */
3954 s->two_byte_p = 1;
3955 }
3956
3957
3958 /* Load glyph string S with a sequence of non-composite characters.
3959 FACE_ID is the face id of the string. START is the index of the
3960 first glyph to consider, END is the index of the last + 1.
3961 OVERLAPS_P non-zero means S should draw the foreground only, and
3962 use its lines physical height for clipping.
3963
3964 Value is the index of the first glyph not in S. */
3965
3966 static int
3967 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
3968 struct glyph_string *s;
3969 int face_id;
3970 int start, end, overlaps_p;
3971 {
3972 struct glyph *glyph, *last;
3973 int voffset;
3974
3975 xassert (s->charset != CHARSET_COMPOSITION);
3976 xassert (s->f == XFRAME (s->w->frame));
3977 xassert (s->nchars == 0);
3978 xassert (start >= 0 && end > start);
3979
3980 s->for_overlaps_p = overlaps_p,
3981 glyph = s->row->glyphs[s->area] + start;
3982 last = s->row->glyphs[s->area] + end;
3983 voffset = glyph->voffset;
3984
3985 while (glyph < last
3986 && glyph->type == CHAR_GLYPH
3987 && glyph->voffset == voffset
3988 /* Same face id implies same charset, nowadays. */
3989 && glyph->u.ch.face_id == face_id)
3990 {
3991 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
3992 s->char2b + s->nchars);
3993 if (s->char2b[s->nchars].byte2 != 0)
3994 s->two_byte_p = 1;
3995
3996 ++s->nchars;
3997 xassert (s->nchars <= end - start);
3998 s->width += glyph->pixel_width;
3999 ++glyph;
4000 }
4001
4002 s->font = s->face->font;
4003 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4004
4005 /* If the specified font could not be loaded, use the frame's font,
4006 but record the fact that we couldn't load it in
4007 S->font_not_found_p so that we can draw rectangles for the
4008 characters of the glyph string. */
4009 if (s->font == NULL)
4010 {
4011 s->font_not_found_p = 1;
4012 s->font = FRAME_FONT (s->f);
4013 }
4014
4015 /* Adjust base line for subscript/superscript text. */
4016 s->ybase += voffset;
4017
4018 xassert (s->face && s->face->gc);
4019 return glyph - s->row->glyphs[s->area];
4020 }
4021
4022
4023 /* Fill glyph string S from image glyph S->first_glyph. */
4024
4025 static void
4026 x_fill_image_glyph_string (s)
4027 struct glyph_string *s;
4028 {
4029 xassert (s->first_glyph->type == IMAGE_GLYPH);
4030 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img.id);
4031 xassert (s->img);
4032 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.img.face_id);
4033 s->font = s->face->font;
4034 s->width = s->first_glyph->pixel_width;
4035
4036 /* Adjust base line for subscript/superscript text. */
4037 s->ybase += s->first_glyph->voffset;
4038 }
4039
4040
4041 /* Fill glyph string S from stretch glyph S->first_glyph. */
4042
4043 static void
4044 x_fill_stretch_glyph_string (s)
4045 struct glyph_string *s;
4046 {
4047 xassert (s->first_glyph->type == STRETCH_GLYPH);
4048 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.stretch.face_id);
4049 s->font = s->face->font;
4050 s->width = s->first_glyph->pixel_width;
4051
4052 /* Adjust base line for subscript/superscript text. */
4053 s->ybase += s->first_glyph->voffset;
4054 }
4055
4056
4057 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4058 of XChar2b structures for S; it can't be allocated in
4059 x_init_glyph_string because it must be allocated via `alloca'. W
4060 is the window on which S is drawn. ROW and AREA are the glyph row
4061 and area within the row from which S is constructed. START is the
4062 index of the first glyph structure covered by S. HL is a
4063 face-override for drawing S. */
4064
4065 static void
4066 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4067 struct glyph_string *s;
4068 XChar2b *char2b;
4069 struct window *w;
4070 struct glyph_row *row;
4071 enum glyph_row_area area;
4072 int start;
4073 enum draw_glyphs_face hl;
4074 {
4075 bzero (s, sizeof *s);
4076 s->w = w;
4077 s->f = XFRAME (w->frame);
4078 s->display = FRAME_X_DISPLAY (s->f);
4079 s->window = FRAME_X_WINDOW (s->f);
4080 s->char2b = char2b;
4081 s->hl = hl;
4082 s->row = row;
4083 s->area = area;
4084 s->first_glyph = row->glyphs[area] + start;
4085 s->height = row->height;
4086 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4087
4088 /* Display the internal border below the tool-bar window. */
4089 if (s->w == XWINDOW (s->f->tool_bar_window))
4090 s->y -= s->f->output_data.x->internal_border_width;
4091
4092 s->ybase = s->y + row->ascent;
4093 }
4094
4095
4096 /* Set background width of glyph string S. START is the index of the
4097 first glyph following S. LAST_X is the right-most x-position + 1
4098 in the drawing area. */
4099
4100 static INLINE void
4101 x_set_glyph_string_background_width (s, start, last_x)
4102 struct glyph_string *s;
4103 int start;
4104 int last_x;
4105 {
4106 /* If the face of this glyph string has to be drawn to the end of
4107 the drawing area, set S->extends_to_end_of_line_p. */
4108 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4109
4110 if (start == s->row->used[s->area]
4111 && s->hl == DRAW_NORMAL_TEXT
4112 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4113 || s->face->background != default_face->background
4114 || s->face->stipple != default_face->stipple))
4115 s->extends_to_end_of_line_p = 1;
4116
4117 /* If S extends its face to the end of the line, set its
4118 background_width to the distance to the right edge of the drawing
4119 area. */
4120 if (s->extends_to_end_of_line_p)
4121 s->background_width = last_x - s->x + 1;
4122 else
4123 s->background_width = s->width;
4124 }
4125
4126
4127 /* Add a glyph string for a stretch glyph to the list of strings
4128 between HEAD and TAIL. START is the index of the stretch glyph in
4129 row area AREA of glyph row ROW. END is the index of the last glyph
4130 in that glyph row area. X is the current output position assigned
4131 to the new glyph string constructed. HL overrides that face of the
4132 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4133 is the right-most x-position of the drawing area. */
4134
4135 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4136 and below -- keep them on one line. */
4137 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4138 do \
4139 { \
4140 s = (struct glyph_string *) alloca (sizeof *s); \
4141 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4142 x_fill_stretch_glyph_string (s); \
4143 x_append_glyph_string (&HEAD, &TAIL, s); \
4144 ++START; \
4145 s->x = (X); \
4146 } \
4147 while (0)
4148
4149
4150 /* Add a glyph string for an image glyph to the list of strings
4151 between HEAD and TAIL. START is the index of the image glyph in
4152 row area AREA of glyph row ROW. END is the index of the last glyph
4153 in that glyph row area. X is the current output position assigned
4154 to the new glyph string constructed. HL overrides that face of the
4155 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4156 is the right-most x-position of the drawing area. */
4157
4158 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4159 do \
4160 { \
4161 s = (struct glyph_string *) alloca (sizeof *s); \
4162 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4163 x_fill_image_glyph_string (s); \
4164 x_append_glyph_string (&HEAD, &TAIL, s); \
4165 ++START; \
4166 s->x = (X); \
4167 } \
4168 while (0)
4169
4170
4171 /* Add a glyph string for a sequence of character glyphs to the list
4172 of strings between HEAD and TAIL. START is the index of the first
4173 glyph in row area AREA of glyph row ROW that is part of the new
4174 glyph string. END is the index of the last glyph in that glyph row
4175 area. X is the current output position assigned to the new glyph
4176 string constructed. HL overrides that face of the glyph; e.g. it
4177 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4178 right-most x-position of the drawing area. */
4179
4180 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4181 do \
4182 { \
4183 int c, charset, face_id; \
4184 XChar2b *char2b; \
4185 \
4186 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4187 charset = CHAR_CHARSET (c); \
4188 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4189 \
4190 if (charset == CHARSET_COMPOSITION) \
4191 { \
4192 struct work *stack, *work, *new = NULL; \
4193 int n = 0; \
4194 struct glyph_string *first_s = NULL; \
4195 \
4196 /* Push an initial entry for character c on the stack. */ \
4197 stack = NULL; \
4198 work = (struct work *) alloca (sizeof *work); \
4199 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; \
4200 work->gidx = 0; \
4201 work->next = stack; \
4202 stack = work; \
4203 \
4204 /* While the stack is not empty, append glyph_strings \
4205 to head/tail for glyphs to draw. */ \
4206 while (stack) \
4207 { \
4208 s = (struct glyph_string *) alloca (sizeof *s); \
4209 char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len \
4210 * sizeof (XChar2b)); \
4211 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4212 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4213 s->cmpcharp = stack->cmpcharp; \
4214 s->gidx = stack->gidx; \
4215 s->charset = charset; \
4216 s->x = (X); \
4217 \
4218 if (n == 0) \
4219 { \
4220 /* Don't draw the background except for the \
4221 first glyph string. */ \
4222 s->background_filled_p = n > 0; \
4223 first_s = s; \
4224 } \
4225 ++n; \
4226 \
4227 if (new == NULL) \
4228 new = (struct work *) alloca (sizeof *new); \
4229 x_fill_composite_glyph_string (s, face_id, &stack, \
4230 &new, OVERLAPS_P); \
4231 } \
4232 \
4233 ++START; \
4234 s = first_s; \
4235 } \
4236 else \
4237 { \
4238 s = (struct glyph_string *) alloca (sizeof *s); \
4239 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4240 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4241 x_append_glyph_string (&HEAD, &TAIL, s); \
4242 s->charset = charset; \
4243 s->x = (X); \
4244 START = x_fill_glyph_string (s, face_id, START, END, \
4245 OVERLAPS_P); \
4246 } \
4247 } \
4248 while (0)
4249
4250
4251 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4252 of AREA of glyph row ROW on window W between indices START and END.
4253 HL overrides the face for drawing glyph strings, e.g. it is
4254 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4255 x-positions of the drawing area.
4256
4257 This is an ugly monster macro construct because we must use alloca
4258 to allocate glyph strings (because x_draw_glyphs can be called
4259 asynchronously). */
4260
4261 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4262 do \
4263 { \
4264 HEAD = TAIL = NULL; \
4265 while (START < END) \
4266 { \
4267 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4268 switch (first_glyph->type) \
4269 { \
4270 case CHAR_GLYPH: \
4271 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4272 TAIL, HL, X, LAST_X, \
4273 OVERLAPS_P); \
4274 break; \
4275 \
4276 case STRETCH_GLYPH: \
4277 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4278 HEAD, TAIL, HL, X, LAST_X); \
4279 break; \
4280 \
4281 case IMAGE_GLYPH: \
4282 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4283 TAIL, HL, X, LAST_X); \
4284 break; \
4285 \
4286 default: \
4287 abort (); \
4288 } \
4289 \
4290 x_set_glyph_string_background_width (s, START, LAST_X); \
4291 (X) += s->width; \
4292 } \
4293 } \
4294 while (0)
4295
4296
4297 /* Draw glyphs between START and END in AREA of ROW on window W,
4298 starting at x-position X. X is relative to AREA in W. HL is a
4299 face-override with the following meaning:
4300
4301 DRAW_NORMAL_TEXT draw normally
4302 DRAW_CURSOR draw in cursor face
4303 DRAW_MOUSE_FACE draw in mouse face.
4304 DRAW_INVERSE_VIDEO draw in mode line face
4305 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4306 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4307
4308 If REAL_START is non-null, return in *REAL_START the real starting
4309 position for display. This can be different from START in case
4310 overlapping glyphs must be displayed. If REAL_END is non-null,
4311 return in *REAL_END the real end position for display. This can be
4312 different from END in case overlapping glyphs must be displayed.
4313
4314 If OVERLAPS_P is non-zero, draw only the foreground of characters
4315 and clip to the physical height of ROW.
4316
4317 Value is the x-position reached, relative to AREA of W. */
4318
4319 static int
4320 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4321 overlaps_p)
4322 struct window *w;
4323 int x;
4324 struct glyph_row *row;
4325 enum glyph_row_area area;
4326 int start, end;
4327 enum draw_glyphs_face hl;
4328 int *real_start, *real_end;
4329 int overlaps_p;
4330 {
4331 struct glyph_string *head, *tail;
4332 struct glyph_string *s;
4333 int last_x, area_width;
4334 int x_reached;
4335 int i, j;
4336
4337 /* Let's rather be paranoid than getting a SEGV. */
4338 start = max (0, start);
4339 end = min (end, row->used[area]);
4340 if (real_start)
4341 *real_start = start;
4342 if (real_end)
4343 *real_end = end;
4344
4345 /* Translate X to frame coordinates. Set last_x to the right
4346 end of the drawing area. */
4347 if (row->full_width_p)
4348 {
4349 /* X is relative to the left edge of W, without scroll bars
4350 or flag areas. */
4351 struct frame *f = XFRAME (w->frame);
4352 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4353 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4354
4355 x += window_left_x;
4356 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4357 last_x = window_left_x + area_width;
4358
4359 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4360 {
4361 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4362 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4363 last_x += width;
4364 else
4365 x -= width;
4366 }
4367
4368 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4369 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4370 }
4371 else
4372 {
4373 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4374 area_width = window_box_width (w, area);
4375 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4376 }
4377
4378 /* Build a doubly-linked list of glyph_string structures between
4379 head and tail from what we have to draw. Note that the macro
4380 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4381 the reason we use a separate variable `i'. */
4382 i = start;
4383 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4384 overlaps_p);
4385 if (tail)
4386 x_reached = tail->x + tail->background_width;
4387 else
4388 x_reached = x;
4389
4390 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4391 the row, redraw some glyphs in front or following the glyph
4392 strings built above. */
4393 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4394 {
4395 int dummy_x = 0;
4396 struct glyph_string *h, *t;
4397
4398 /* Compute overhangs for all glyph strings. */
4399 for (s = head; s; s = s->next)
4400 x_compute_glyph_string_overhangs (s);
4401
4402 /* Prepend glyph strings for glyphs in front of the first glyph
4403 string that are overwritten because of the first glyph
4404 string's left overhang. The background of all strings
4405 prepended must be drawn because the first glyph string
4406 draws over it. */
4407 i = x_left_overwritten (head);
4408 if (i >= 0)
4409 {
4410 j = i;
4411 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4412 DRAW_NORMAL_TEXT, dummy_x, last_x,
4413 overlaps_p);
4414 start = i;
4415 if (real_start)
4416 *real_start = start;
4417 x_compute_overhangs_and_x (t, head->x, 1);
4418 x_prepend_glyph_string_lists (&head, &tail, h, t);
4419 }
4420
4421 /* Prepend glyph strings for glyphs in front of the first glyph
4422 string that overwrite that glyph string because of their
4423 right overhang. For these strings, only the foreground must
4424 be drawn, because it draws over the glyph string at `head'.
4425 The background must not be drawn because this would overwrite
4426 right overhangs of preceding glyphs for which no glyph
4427 strings exist. */
4428 i = x_left_overwriting (head);
4429 if (i >= 0)
4430 {
4431 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4432 DRAW_NORMAL_TEXT, dummy_x, last_x,
4433 overlaps_p);
4434 for (s = h; s; s = s->next)
4435 s->background_filled_p = 1;
4436 if (real_start)
4437 *real_start = i;
4438 x_compute_overhangs_and_x (t, head->x, 1);
4439 x_prepend_glyph_string_lists (&head, &tail, h, t);
4440 }
4441
4442 /* Append glyphs strings for glyphs following the last glyph
4443 string tail that are overwritten by tail. The background of
4444 these strings has to be drawn because tail's foreground draws
4445 over it. */
4446 i = x_right_overwritten (tail);
4447 if (i >= 0)
4448 {
4449 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4450 DRAW_NORMAL_TEXT, x, last_x,
4451 overlaps_p);
4452 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4453 x_append_glyph_string_lists (&head, &tail, h, t);
4454 if (real_end)
4455 *real_end = i;
4456 }
4457
4458 /* Append glyph strings for glyphs following the last glyph
4459 string tail that overwrite tail. The foreground of such
4460 glyphs has to be drawn because it writes into the background
4461 of tail. The background must not be drawn because it could
4462 paint over the foreground of following glyphs. */
4463 i = x_right_overwriting (tail);
4464 if (i >= 0)
4465 {
4466 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4467 DRAW_NORMAL_TEXT, x, last_x,
4468 overlaps_p);
4469 for (s = h; s; s = s->next)
4470 s->background_filled_p = 1;
4471 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4472 x_append_glyph_string_lists (&head, &tail, h, t);
4473 if (real_end)
4474 *real_end = i;
4475 }
4476 }
4477
4478 /* Draw all strings. */
4479 for (s = head; s; s = s->next)
4480 x_draw_glyph_string (s);
4481
4482 /* Value is the x-position up to which drawn, relative to AREA of W.
4483 This doesn't include parts drawn because of overhangs. */
4484 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4485 if (!row->full_width_p)
4486 {
4487 if (area > LEFT_MARGIN_AREA)
4488 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4489 if (area > TEXT_AREA)
4490 x_reached -= window_box_width (w, TEXT_AREA);
4491 }
4492 return x_reached;
4493 }
4494
4495
4496 /* Fix the display of area AREA of overlapping row ROW in window W. */
4497
4498 static void
4499 x_fix_overlapping_area (w, row, area)
4500 struct window *w;
4501 struct glyph_row *row;
4502 enum glyph_row_area area;
4503 {
4504 int i, x;
4505
4506 BLOCK_INPUT;
4507
4508 if (area == LEFT_MARGIN_AREA)
4509 x = 0;
4510 else if (area == TEXT_AREA)
4511 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4512 else
4513 x = (window_box_width (w, LEFT_MARGIN_AREA)
4514 + window_box_width (w, TEXT_AREA));
4515
4516 for (i = 0; i < row->used[area];)
4517 {
4518 if (row->glyphs[area][i].overlaps_vertically_p)
4519 {
4520 int start = i, start_x = x;
4521
4522 do
4523 {
4524 x += row->glyphs[area][i].pixel_width;
4525 ++i;
4526 }
4527 while (i < row->used[area]
4528 && row->glyphs[area][i].overlaps_vertically_p);
4529
4530 x_draw_glyphs (w, start_x, row, area, start, i,
4531 (row->inverse_p
4532 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4533 NULL, NULL, 1);
4534 }
4535 else
4536 {
4537 x += row->glyphs[area][i].pixel_width;
4538 ++i;
4539 }
4540 }
4541
4542 UNBLOCK_INPUT;
4543 }
4544
4545
4546 /* Output LEN glyphs starting at START at the nominal cursor position.
4547 Advance the nominal cursor over the text. The global variable
4548 updated_window contains the window being updated, updated_row is
4549 the glyph row being updated, and updated_area is the area of that
4550 row being updated. */
4551
4552 static void
4553 x_write_glyphs (start, len)
4554 struct glyph *start;
4555 int len;
4556 {
4557 int x, hpos, real_start, real_end;
4558
4559 xassert (updated_window && updated_row);
4560 BLOCK_INPUT;
4561
4562 /* Write glyphs. */
4563
4564 hpos = start - updated_row->glyphs[updated_area];
4565 x = x_draw_glyphs (updated_window, output_cursor.x,
4566 updated_row, updated_area,
4567 hpos, hpos + len,
4568 (updated_row->inverse_p
4569 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4570 &real_start, &real_end, 0);
4571
4572 /* If we drew over the cursor, note that it is not visible any more. */
4573 note_overwritten_text_cursor (updated_window, real_start,
4574 real_end - real_start);
4575
4576 UNBLOCK_INPUT;
4577
4578 /* Advance the output cursor. */
4579 output_cursor.hpos += len;
4580 output_cursor.x = x;
4581 }
4582
4583
4584 /* Insert LEN glyphs from START at the nominal cursor position. */
4585
4586 static void
4587 x_insert_glyphs (start, len)
4588 struct glyph *start;
4589 register int len;
4590 {
4591 struct frame *f;
4592 struct window *w;
4593 int line_height, shift_by_width, shifted_region_width;
4594 struct glyph_row *row;
4595 struct glyph *glyph;
4596 int frame_x, frame_y, hpos, real_start, real_end;
4597
4598 xassert (updated_window && updated_row);
4599 BLOCK_INPUT;
4600 w = updated_window;
4601 f = XFRAME (WINDOW_FRAME (w));
4602
4603 /* Get the height of the line we are in. */
4604 row = updated_row;
4605 line_height = row->height;
4606
4607 /* Get the width of the glyphs to insert. */
4608 shift_by_width = 0;
4609 for (glyph = start; glyph < start + len; ++glyph)
4610 shift_by_width += glyph->pixel_width;
4611
4612 /* Get the width of the region to shift right. */
4613 shifted_region_width = (window_box_width (w, updated_area)
4614 - output_cursor.x
4615 - shift_by_width);
4616
4617 /* Shift right. */
4618 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4619 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4620 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4621 f->output_data.x->normal_gc,
4622 frame_x, frame_y,
4623 shifted_region_width, line_height,
4624 frame_x + shift_by_width, frame_y);
4625
4626 /* Write the glyphs. */
4627 hpos = start - row->glyphs[updated_area];
4628 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4629 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4630 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4631
4632 /* Advance the output cursor. */
4633 output_cursor.hpos += len;
4634 output_cursor.x += shift_by_width;
4635 UNBLOCK_INPUT;
4636 }
4637
4638
4639 /* Delete N glyphs at the nominal cursor position. Not implemented
4640 for X frames. */
4641
4642 static void
4643 x_delete_glyphs (n)
4644 register int n;
4645 {
4646 abort ();
4647 }
4648
4649
4650 /* Erase the current text line from the nominal cursor position
4651 (inclusive) to pixel column TO_X (exclusive). The idea is that
4652 everything from TO_X onward is already erased.
4653
4654 TO_X is a pixel position relative to updated_area of
4655 updated_window. TO_X == -1 means clear to the end of this area. */
4656
4657 static void
4658 x_clear_end_of_line (to_x)
4659 int to_x;
4660 {
4661 struct frame *f;
4662 struct window *w = updated_window;
4663 int max_x, min_y, max_y;
4664 int from_x, from_y, to_y;
4665
4666 xassert (updated_window && updated_row);
4667 f = XFRAME (w->frame);
4668
4669 if (updated_row->full_width_p)
4670 {
4671 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4672 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4673 && !w->pseudo_window_p)
4674 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4675 }
4676 else
4677 max_x = window_box_width (w, updated_area);
4678 max_y = window_text_bottom_y (w);
4679
4680 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4681 of window. For TO_X > 0, truncate to end of drawing area. */
4682 if (to_x == 0)
4683 return;
4684 else if (to_x < 0)
4685 to_x = max_x;
4686 else
4687 to_x = min (to_x, max_x);
4688
4689 to_y = min (max_y, output_cursor.y + updated_row->height);
4690
4691 /* Notice if the cursor will be cleared by this operation. */
4692 if (!updated_row->full_width_p)
4693 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4694
4695 from_x = output_cursor.x;
4696
4697 /* Translate to frame coordinates. */
4698 if (updated_row->full_width_p)
4699 {
4700 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4701 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4702 }
4703 else
4704 {
4705 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4706 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4707 }
4708
4709 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4710 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4711 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4712
4713 /* Prevent inadvertently clearing to end of the X window. */
4714 if (to_x > from_x && to_y > from_y)
4715 {
4716 BLOCK_INPUT;
4717 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4718 from_x, from_y, to_x - from_x, to_y - from_y,
4719 False);
4720 UNBLOCK_INPUT;
4721 }
4722 }
4723
4724
4725 /* Clear entire frame. If updating_frame is non-null, clear that
4726 frame. Otherwise clear the selected frame. */
4727
4728 static void
4729 x_clear_frame ()
4730 {
4731 struct frame *f;
4732
4733 if (updating_frame)
4734 f = updating_frame;
4735 else
4736 f = SELECTED_FRAME ();
4737
4738 /* Clearing the frame will erase any cursor, so mark them all as no
4739 longer visible. */
4740 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4741 output_cursor.hpos = output_cursor.vpos = 0;
4742 output_cursor.x = -1;
4743
4744 /* We don't set the output cursor here because there will always
4745 follow an explicit cursor_to. */
4746 BLOCK_INPUT;
4747 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4748
4749 /* We have to clear the scroll bars, too. If we have changed
4750 colors or something like that, then they should be notified. */
4751 x_scroll_bar_clear (f);
4752
4753 XFlush (FRAME_X_DISPLAY (f));
4754 UNBLOCK_INPUT;
4755 }
4756
4757
4758 \f
4759 /* Invert the middle quarter of the frame for .15 sec. */
4760
4761 /* We use the select system call to do the waiting, so we have to make
4762 sure it's available. If it isn't, we just won't do visual bells. */
4763
4764 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4765
4766
4767 /* Subtract the `struct timeval' values X and Y, storing the result in
4768 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4769
4770 static int
4771 timeval_subtract (result, x, y)
4772 struct timeval *result, x, y;
4773 {
4774 /* Perform the carry for the later subtraction by updating y. This
4775 is safer because on some systems the tv_sec member is unsigned. */
4776 if (x.tv_usec < y.tv_usec)
4777 {
4778 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4779 y.tv_usec -= 1000000 * nsec;
4780 y.tv_sec += nsec;
4781 }
4782
4783 if (x.tv_usec - y.tv_usec > 1000000)
4784 {
4785 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4786 y.tv_usec += 1000000 * nsec;
4787 y.tv_sec -= nsec;
4788 }
4789
4790 /* Compute the time remaining to wait. tv_usec is certainly
4791 positive. */
4792 result->tv_sec = x.tv_sec - y.tv_sec;
4793 result->tv_usec = x.tv_usec - y.tv_usec;
4794
4795 /* Return indication of whether the result should be considered
4796 negative. */
4797 return x.tv_sec < y.tv_sec;
4798 }
4799
4800 void
4801 XTflash (f)
4802 struct frame *f;
4803 {
4804 BLOCK_INPUT;
4805
4806 {
4807 GC gc;
4808
4809 /* Create a GC that will use the GXxor function to flip foreground
4810 pixels into background pixels. */
4811 {
4812 XGCValues values;
4813
4814 values.function = GXxor;
4815 values.foreground = (f->output_data.x->foreground_pixel
4816 ^ f->output_data.x->background_pixel);
4817
4818 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4819 GCFunction | GCForeground, &values);
4820 }
4821
4822 {
4823 /* Get the height not including a menu bar widget. */
4824 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
4825 /* Height of each line to flash. */
4826 int flash_height = FRAME_LINE_HEIGHT (f);
4827 /* These will be the left and right margins of the rectangles. */
4828 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4829 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4830
4831 int width;
4832
4833 /* Don't flash the area between a scroll bar and the frame
4834 edge it is next to. */
4835 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4836 {
4837 case vertical_scroll_bar_left:
4838 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4839 break;
4840
4841 case vertical_scroll_bar_right:
4842 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4843 break;
4844
4845 default:
4846 break;
4847 }
4848
4849 width = flash_right - flash_left;
4850
4851 /* If window is tall, flash top and bottom line. */
4852 if (height > 3 * FRAME_LINE_HEIGHT (f))
4853 {
4854 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4855 flash_left,
4856 (FRAME_INTERNAL_BORDER_WIDTH (f)
4857 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
4858 width, flash_height);
4859 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4860 flash_left,
4861 (height - flash_height
4862 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4863 width, flash_height);
4864 }
4865 else
4866 /* If it is short, flash it all. */
4867 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4868 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4869 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4870
4871 x_flush (f);
4872
4873 {
4874 struct timeval wakeup;
4875
4876 EMACS_GET_TIME (wakeup);
4877
4878 /* Compute time to wait until, propagating carry from usecs. */
4879 wakeup.tv_usec += 150000;
4880 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4881 wakeup.tv_usec %= 1000000;
4882
4883 /* Keep waiting until past the time wakeup. */
4884 while (1)
4885 {
4886 struct timeval timeout;
4887
4888 EMACS_GET_TIME (timeout);
4889
4890 /* In effect, timeout = wakeup - timeout.
4891 Break if result would be negative. */
4892 if (timeval_subtract (&timeout, wakeup, timeout))
4893 break;
4894
4895 /* Try to wait that long--but we might wake up sooner. */
4896 select (0, NULL, NULL, NULL, &timeout);
4897 }
4898 }
4899
4900 /* If window is tall, flash top and bottom line. */
4901 if (height > 3 * FRAME_LINE_HEIGHT (f))
4902 {
4903 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4904 flash_left,
4905 (FRAME_INTERNAL_BORDER_WIDTH (f)
4906 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
4907 width, flash_height);
4908 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4909 flash_left,
4910 (height - flash_height
4911 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4912 width, flash_height);
4913 }
4914 else
4915 /* If it is short, flash it all. */
4916 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4917 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4918 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4919
4920 XFreeGC (FRAME_X_DISPLAY (f), gc);
4921 x_flush (f);
4922 }
4923 }
4924
4925 UNBLOCK_INPUT;
4926 }
4927
4928 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4929
4930
4931 /* Make audible bell. */
4932
4933 void
4934 XTring_bell ()
4935 {
4936 struct frame *f = SELECTED_FRAME ();
4937
4938 if (FRAME_X_DISPLAY (f))
4939 {
4940 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4941 if (visible_bell)
4942 XTflash (f);
4943 else
4944 #endif
4945 {
4946 BLOCK_INPUT;
4947 XBell (FRAME_X_DISPLAY (f), 0);
4948 XFlush (FRAME_X_DISPLAY (f));
4949 UNBLOCK_INPUT;
4950 }
4951 }
4952 }
4953
4954 \f
4955 /* Specify how many text lines, from the top of the window,
4956 should be affected by insert-lines and delete-lines operations.
4957 This, and those operations, are used only within an update
4958 that is bounded by calls to x_update_begin and x_update_end. */
4959
4960 static void
4961 XTset_terminal_window (n)
4962 register int n;
4963 {
4964 /* This function intentionally left blank. */
4965 }
4966
4967
4968 \f
4969 /***********************************************************************
4970 Line Dance
4971 ***********************************************************************/
4972
4973 /* Perform an insert-lines or delete-lines operation, inserting N
4974 lines or deleting -N lines at vertical position VPOS. */
4975
4976 static void
4977 x_ins_del_lines (vpos, n)
4978 int vpos, n;
4979 {
4980 abort ();
4981 }
4982
4983
4984 /* Scroll part of the display as described by RUN. */
4985
4986 static void
4987 x_scroll_run (w, run)
4988 struct window *w;
4989 struct run *run;
4990 {
4991 struct frame *f = XFRAME (w->frame);
4992 int x, y, width, height, from_y, to_y, bottom_y;
4993
4994 /* Get frame-relative bounding box of the text display area of W,
4995 without mode lines. Include in this box the flags areas to the
4996 left and right of W. */
4997 window_box (w, -1, &x, &y, &width, &height);
4998 width += FRAME_X_FLAGS_AREA_WIDTH (f);
4999 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5000
5001 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5002 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5003 bottom_y = y + height;
5004
5005 if (to_y < from_y)
5006 {
5007 /* Scrolling up. Make sure we don't copy part of the mode
5008 line at the bottom. */
5009 if (from_y + run->height > bottom_y)
5010 height = bottom_y - from_y;
5011 else
5012 height = run->height;
5013 }
5014 else
5015 {
5016 /* Scolling down. Make sure we don't copy over the mode line.
5017 at the bottom. */
5018 if (to_y + run->height > bottom_y)
5019 height = bottom_y - to_y;
5020 else
5021 height = run->height;
5022 }
5023
5024 BLOCK_INPUT;
5025
5026 /* Cursor off. Will be switched on again in x_update_window_end. */
5027 updated_window = w;
5028 x_clear_cursor (w);
5029
5030 XCopyArea (FRAME_X_DISPLAY (f),
5031 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5032 f->output_data.x->normal_gc,
5033 x, from_y,
5034 width, height,
5035 x, to_y);
5036
5037 UNBLOCK_INPUT;
5038 }
5039
5040
5041 \f
5042 /***********************************************************************
5043 Exposure Events
5044 ***********************************************************************/
5045
5046 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5047 corner of the exposed rectangle. W and H are width and height of
5048 the exposed area. All are pixel values. W or H zero means redraw
5049 the entire frame. */
5050
5051 static void
5052 expose_frame (f, x, y, w, h)
5053 struct frame *f;
5054 int x, y, w, h;
5055 {
5056 XRectangle r;
5057
5058 TRACE ((stderr, "expose_frame "));
5059
5060 /* No need to redraw if frame will be redrawn soon. */
5061 if (FRAME_GARBAGED_P (f))
5062 {
5063 TRACE ((stderr, " garbaged\n"));
5064 return;
5065 }
5066
5067 /* If basic faces haven't been realized yet, there is no point in
5068 trying to redraw anything. This can happen when we get an expose
5069 event while Emacs is starting, e.g. by moving another window. */
5070 if (FRAME_FACE_CACHE (f) == NULL
5071 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5072 {
5073 TRACE ((stderr, " no faces\n"));
5074 return;
5075 }
5076
5077 if (w == 0 || h == 0)
5078 {
5079 r.x = r.y = 0;
5080 r.width = CANON_X_UNIT (f) * f->width;
5081 r.height = CANON_Y_UNIT (f) * f->height;
5082 }
5083 else
5084 {
5085 r.x = x;
5086 r.y = y;
5087 r.width = w;
5088 r.height = h;
5089 }
5090
5091 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5092 expose_window_tree (XWINDOW (f->root_window), &r);
5093
5094 if (WINDOWP (f->tool_bar_window))
5095 {
5096 struct window *w = XWINDOW (f->tool_bar_window);
5097 XRectangle window_rect;
5098 XRectangle intersection_rect;
5099 int window_x, window_y, window_width, window_height;
5100
5101
5102 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5103 window_rect.x = window_x;
5104 window_rect.y = window_y;
5105 window_rect.width = window_width;
5106 window_rect.height = window_height;
5107
5108 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5109 expose_window (w, &intersection_rect);
5110 }
5111
5112 #ifndef USE_X_TOOLKIT
5113 if (WINDOWP (f->menu_bar_window))
5114 {
5115 struct window *w = XWINDOW (f->menu_bar_window);
5116 XRectangle window_rect;
5117 XRectangle intersection_rect;
5118 int window_x, window_y, window_width, window_height;
5119
5120
5121 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5122 window_rect.x = window_x;
5123 window_rect.y = window_y;
5124 window_rect.width = window_width;
5125 window_rect.height = window_height;
5126
5127 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5128 expose_window (w, &intersection_rect);
5129 }
5130 #endif /* not USE_X_TOOLKIT */
5131 }
5132
5133
5134 /* Redraw (parts) of all windows in the window tree rooted at W that
5135 intersect R. R contains frame pixel coordinates. */
5136
5137 static void
5138 expose_window_tree (w, r)
5139 struct window *w;
5140 XRectangle *r;
5141 {
5142 while (w)
5143 {
5144 if (!NILP (w->hchild))
5145 expose_window_tree (XWINDOW (w->hchild), r);
5146 else if (!NILP (w->vchild))
5147 expose_window_tree (XWINDOW (w->vchild), r);
5148 else
5149 {
5150 XRectangle window_rect;
5151 XRectangle intersection_rect;
5152 struct frame *f = XFRAME (w->frame);
5153 int window_x, window_y, window_width, window_height;
5154
5155 /* Frame-relative pixel rectangle of W. */
5156 window_box (w, -1, &window_x, &window_y, &window_width,
5157 &window_height);
5158 window_rect.x
5159 = (window_x
5160 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5161 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5162 window_rect.y = window_y;
5163 window_rect.width
5164 = (window_width
5165 + FRAME_X_FLAGS_AREA_WIDTH (f)
5166 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5167 window_rect.height
5168 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5169
5170 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5171 expose_window (w, &intersection_rect);
5172 }
5173
5174 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5175 }
5176 }
5177
5178
5179 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5180 which intersects rectangle R. R is in window-relative coordinates. */
5181
5182 static void
5183 expose_area (w, row, r, area)
5184 struct window *w;
5185 struct glyph_row *row;
5186 XRectangle *r;
5187 enum glyph_row_area area;
5188 {
5189 int x;
5190 struct glyph *first = row->glyphs[area];
5191 struct glyph *end = row->glyphs[area] + row->used[area];
5192 struct glyph *last;
5193 int first_x;
5194
5195 /* Set x to the window-relative start position for drawing glyphs of
5196 AREA. The first glyph of the text area can be partially visible.
5197 The first glyphs of other areas cannot. */
5198 if (area == LEFT_MARGIN_AREA)
5199 x = 0;
5200 else if (area == TEXT_AREA)
5201 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5202 else
5203 x = (window_box_width (w, LEFT_MARGIN_AREA)
5204 + window_box_width (w, TEXT_AREA));
5205
5206 if (area == TEXT_AREA && row->fill_line_p)
5207 /* If row extends face to end of line write the whole line. */
5208 x_draw_glyphs (w, x, row, area,
5209 0, row->used[area],
5210 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5211 NULL, NULL, 0);
5212 else
5213 {
5214 /* Find the first glyph that must be redrawn. */
5215 while (first < end
5216 && x + first->pixel_width < r->x)
5217 {
5218 x += first->pixel_width;
5219 ++first;
5220 }
5221
5222 /* Find the last one. */
5223 last = first;
5224 first_x = x;
5225 while (last < end
5226 && x < r->x + r->width)
5227 {
5228 x += last->pixel_width;
5229 ++last;
5230 }
5231
5232 /* Repaint. */
5233 if (last > first)
5234 x_draw_glyphs (w, first_x, row, area,
5235 first - row->glyphs[area],
5236 last - row->glyphs[area],
5237 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5238 NULL, NULL, 0);
5239 }
5240 }
5241
5242
5243 /* Redraw the parts of the glyph row ROW on window W intersecting
5244 rectangle R. R is in window-relative coordinates. */
5245
5246 static void
5247 expose_line (w, row, r)
5248 struct window *w;
5249 struct glyph_row *row;
5250 XRectangle *r;
5251 {
5252 xassert (row->enabled_p);
5253
5254 if (row->mode_line_p || w->pseudo_window_p)
5255 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5256 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5257 NULL, NULL, 0);
5258 else
5259 {
5260 if (row->used[LEFT_MARGIN_AREA])
5261 expose_area (w, row, r, LEFT_MARGIN_AREA);
5262 if (row->used[TEXT_AREA])
5263 expose_area (w, row, r, TEXT_AREA);
5264 if (row->used[RIGHT_MARGIN_AREA])
5265 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5266 x_draw_row_bitmaps (w, row);
5267 }
5268 }
5269
5270
5271 /* Return non-zero if W's cursor intersects rectangle R. */
5272
5273 static int
5274 x_phys_cursor_in_rect_p (w, r)
5275 struct window *w;
5276 XRectangle *r;
5277 {
5278 XRectangle cr, result;
5279 struct glyph *cursor_glyph;
5280
5281 cursor_glyph = get_phys_cursor_glyph (w);
5282 if (cursor_glyph)
5283 {
5284 cr.x = w->phys_cursor.x;
5285 cr.y = w->phys_cursor.y;
5286 cr.width = cursor_glyph->pixel_width;
5287 cr.height = w->phys_cursor_height;
5288 return x_intersect_rectangles (&cr, r, &result);
5289 }
5290 else
5291 return 0;
5292 }
5293
5294
5295 /* Redraw a rectangle of window W. R is a rectangle in window
5296 relative coordinates. Call this function with input blocked. */
5297
5298 static void
5299 expose_window (w, r)
5300 struct window *w;
5301 XRectangle *r;
5302 {
5303 struct glyph_row *row;
5304 int y;
5305 int yb = window_text_bottom_y (w);
5306 int cursor_cleared_p;
5307
5308 /* If window is not yet fully initialized, do nothing. This can
5309 happen when toolkit scroll bars are used and a window is split.
5310 Reconfiguring the scroll bar will generate an expose for a newly
5311 created window. */
5312 if (w->current_matrix == NULL)
5313 return;
5314
5315 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5316 r->x, r->y, r->width, r->height));
5317
5318 /* Convert to window coordinates. */
5319 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5320 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5321
5322 /* Turn off the cursor. */
5323 if (!w->pseudo_window_p
5324 && x_phys_cursor_in_rect_p (w, r))
5325 {
5326 x_clear_cursor (w);
5327 cursor_cleared_p = 1;
5328 }
5329 else
5330 cursor_cleared_p = 0;
5331
5332 /* Find the first row intersecting the rectangle R. */
5333 row = w->current_matrix->rows;
5334 y = 0;
5335 while (row->enabled_p
5336 && y < yb
5337 && y + row->height < r->y)
5338 {
5339 y += row->height;
5340 ++row;
5341 }
5342
5343 /* Display the text in the rectangle, one text line at a time. */
5344 while (row->enabled_p
5345 && y < yb
5346 && y < r->y + r->height)
5347 {
5348 expose_line (w, row, r);
5349 y += row->height;
5350 ++row;
5351 }
5352
5353 /* Display the mode line if there is one. */
5354 if (WINDOW_WANTS_MODELINE_P (w)
5355 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5356 row->enabled_p)
5357 && row->y < r->y + r->height)
5358 expose_line (w, row, r);
5359
5360 if (!w->pseudo_window_p)
5361 {
5362 /* Draw border between windows. */
5363 x_draw_vertical_border (w);
5364
5365 /* Turn the cursor on again. */
5366 if (cursor_cleared_p)
5367 x_update_window_cursor (w, 1);
5368 }
5369 }
5370
5371
5372 /* Determine the intersection of two rectangles R1 and R2. Return
5373 the intersection in *RESULT. Value is non-zero if RESULT is not
5374 empty. */
5375
5376 static int
5377 x_intersect_rectangles (r1, r2, result)
5378 XRectangle *r1, *r2, *result;
5379 {
5380 XRectangle *left, *right;
5381 XRectangle *upper, *lower;
5382 int intersection_p = 0;
5383
5384 /* Rearrange so that R1 is the left-most rectangle. */
5385 if (r1->x < r2->x)
5386 left = r1, right = r2;
5387 else
5388 left = r2, right = r1;
5389
5390 /* X0 of the intersection is right.x0, if this is inside R1,
5391 otherwise there is no intersection. */
5392 if (right->x <= left->x + left->width)
5393 {
5394 result->x = right->x;
5395
5396 /* The right end of the intersection is the minimum of the
5397 the right ends of left and right. */
5398 result->width = (min (left->x + left->width, right->x + right->width)
5399 - result->x);
5400
5401 /* Same game for Y. */
5402 if (r1->y < r2->y)
5403 upper = r1, lower = r2;
5404 else
5405 upper = r2, lower = r1;
5406
5407 /* The upper end of the intersection is lower.y0, if this is inside
5408 of upper. Otherwise, there is no intersection. */
5409 if (lower->y <= upper->y + upper->height)
5410 {
5411 result->y = lower->y;
5412
5413 /* The lower end of the intersection is the minimum of the lower
5414 ends of upper and lower. */
5415 result->height = (min (lower->y + lower->height,
5416 upper->y + upper->height)
5417 - result->y);
5418 intersection_p = 1;
5419 }
5420 }
5421
5422 return intersection_p;
5423 }
5424
5425
5426
5427
5428 \f
5429 static void
5430 frame_highlight (f)
5431 struct frame *f;
5432 {
5433 /* We used to only do this if Vx_no_window_manager was non-nil, but
5434 the ICCCM (section 4.1.6) says that the window's border pixmap
5435 and border pixel are window attributes which are "private to the
5436 client", so we can always change it to whatever we want. */
5437 BLOCK_INPUT;
5438 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5439 f->output_data.x->border_pixel);
5440 UNBLOCK_INPUT;
5441 x_update_cursor (f, 1);
5442 }
5443
5444 static void
5445 frame_unhighlight (f)
5446 struct frame *f;
5447 {
5448 /* We used to only do this if Vx_no_window_manager was non-nil, but
5449 the ICCCM (section 4.1.6) says that the window's border pixmap
5450 and border pixel are window attributes which are "private to the
5451 client", so we can always change it to whatever we want. */
5452 BLOCK_INPUT;
5453 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5454 f->output_data.x->border_tile);
5455 UNBLOCK_INPUT;
5456 x_update_cursor (f, 1);
5457 }
5458
5459 /* The focus has changed. Update the frames as necessary to reflect
5460 the new situation. Note that we can't change the selected frame
5461 here, because the Lisp code we are interrupting might become confused.
5462 Each event gets marked with the frame in which it occurred, so the
5463 Lisp code can tell when the switch took place by examining the events. */
5464
5465 static void
5466 x_new_focus_frame (dpyinfo, frame)
5467 struct x_display_info *dpyinfo;
5468 struct frame *frame;
5469 {
5470 struct frame *old_focus = dpyinfo->x_focus_frame;
5471
5472 if (frame != dpyinfo->x_focus_frame)
5473 {
5474 /* Set this before calling other routines, so that they see
5475 the correct value of x_focus_frame. */
5476 dpyinfo->x_focus_frame = frame;
5477
5478 if (old_focus && old_focus->auto_lower)
5479 x_lower_frame (old_focus);
5480
5481 #if 0
5482 selected_frame = frame;
5483 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5484 selected_frame);
5485 Fselect_window (selected_frame->selected_window);
5486 choose_minibuf_frame ();
5487 #endif /* ! 0 */
5488
5489 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5490 pending_autoraise_frame = dpyinfo->x_focus_frame;
5491 else
5492 pending_autoraise_frame = 0;
5493 }
5494
5495 x_frame_rehighlight (dpyinfo);
5496 }
5497
5498 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5499
5500 void
5501 x_mouse_leave (dpyinfo)
5502 struct x_display_info *dpyinfo;
5503 {
5504 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5505 }
5506
5507 /* The focus has changed, or we have redirected a frame's focus to
5508 another frame (this happens when a frame uses a surrogate
5509 mini-buffer frame). Shift the highlight as appropriate.
5510
5511 The FRAME argument doesn't necessarily have anything to do with which
5512 frame is being highlighted or un-highlighted; we only use it to find
5513 the appropriate X display info. */
5514
5515 static void
5516 XTframe_rehighlight (frame)
5517 struct frame *frame;
5518 {
5519 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5520 }
5521
5522 static void
5523 x_frame_rehighlight (dpyinfo)
5524 struct x_display_info *dpyinfo;
5525 {
5526 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5527
5528 if (dpyinfo->x_focus_frame)
5529 {
5530 dpyinfo->x_highlight_frame
5531 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5532 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5533 : dpyinfo->x_focus_frame);
5534 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
5535 {
5536 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5537 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
5538 }
5539 }
5540 else
5541 dpyinfo->x_highlight_frame = 0;
5542
5543 if (dpyinfo->x_highlight_frame != old_highlight)
5544 {
5545 if (old_highlight)
5546 frame_unhighlight (old_highlight);
5547 if (dpyinfo->x_highlight_frame)
5548 frame_highlight (dpyinfo->x_highlight_frame);
5549 }
5550 }
5551
5552
5553 \f
5554 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5555
5556 /* Initialize mode_switch_bit and modifier_meaning. */
5557 static void
5558 x_find_modifier_meanings (dpyinfo)
5559 struct x_display_info *dpyinfo;
5560 {
5561 int min_code, max_code;
5562 KeySym *syms;
5563 int syms_per_code;
5564 XModifierKeymap *mods;
5565
5566 dpyinfo->meta_mod_mask = 0;
5567 dpyinfo->shift_lock_mask = 0;
5568 dpyinfo->alt_mod_mask = 0;
5569 dpyinfo->super_mod_mask = 0;
5570 dpyinfo->hyper_mod_mask = 0;
5571
5572 #ifdef HAVE_X11R4
5573 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5574 #else
5575 min_code = dpyinfo->display->min_keycode;
5576 max_code = dpyinfo->display->max_keycode;
5577 #endif
5578
5579 syms = XGetKeyboardMapping (dpyinfo->display,
5580 min_code, max_code - min_code + 1,
5581 &syms_per_code);
5582 mods = XGetModifierMapping (dpyinfo->display);
5583
5584 /* Scan the modifier table to see which modifier bits the Meta and
5585 Alt keysyms are on. */
5586 {
5587 int row, col; /* The row and column in the modifier table. */
5588
5589 for (row = 3; row < 8; row++)
5590 for (col = 0; col < mods->max_keypermod; col++)
5591 {
5592 KeyCode code
5593 = mods->modifiermap[(row * mods->max_keypermod) + col];
5594
5595 /* Zeroes are used for filler. Skip them. */
5596 if (code == 0)
5597 continue;
5598
5599 /* Are any of this keycode's keysyms a meta key? */
5600 {
5601 int code_col;
5602
5603 for (code_col = 0; code_col < syms_per_code; code_col++)
5604 {
5605 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5606
5607 switch (sym)
5608 {
5609 case XK_Meta_L:
5610 case XK_Meta_R:
5611 dpyinfo->meta_mod_mask |= (1 << row);
5612 break;
5613
5614 case XK_Alt_L:
5615 case XK_Alt_R:
5616 dpyinfo->alt_mod_mask |= (1 << row);
5617 break;
5618
5619 case XK_Hyper_L:
5620 case XK_Hyper_R:
5621 dpyinfo->hyper_mod_mask |= (1 << row);
5622 break;
5623
5624 case XK_Super_L:
5625 case XK_Super_R:
5626 dpyinfo->super_mod_mask |= (1 << row);
5627 break;
5628
5629 case XK_Shift_Lock:
5630 /* Ignore this if it's not on the lock modifier. */
5631 if ((1 << row) == LockMask)
5632 dpyinfo->shift_lock_mask = LockMask;
5633 break;
5634 }
5635 }
5636 }
5637 }
5638 }
5639
5640 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5641 if (! dpyinfo->meta_mod_mask)
5642 {
5643 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5644 dpyinfo->alt_mod_mask = 0;
5645 }
5646
5647 /* If some keys are both alt and meta,
5648 make them just meta, not alt. */
5649 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
5650 {
5651 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
5652 }
5653
5654 XFree ((char *) syms);
5655 XFreeModifiermap (mods);
5656 }
5657
5658 /* Convert between the modifier bits X uses and the modifier bits
5659 Emacs uses. */
5660
5661 static unsigned int
5662 x_x_to_emacs_modifiers (dpyinfo, state)
5663 struct x_display_info *dpyinfo;
5664 unsigned int state;
5665 {
5666 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5667 | ((state & ControlMask) ? ctrl_modifier : 0)
5668 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5669 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5670 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5671 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
5672 }
5673
5674 static unsigned int
5675 x_emacs_to_x_modifiers (dpyinfo, state)
5676 struct x_display_info *dpyinfo;
5677 unsigned int state;
5678 {
5679 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5680 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5681 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5682 | ((state & shift_modifier) ? ShiftMask : 0)
5683 | ((state & ctrl_modifier) ? ControlMask : 0)
5684 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
5685 }
5686
5687 /* Convert a keysym to its name. */
5688
5689 char *
5690 x_get_keysym_name (keysym)
5691 KeySym keysym;
5692 {
5693 char *value;
5694
5695 BLOCK_INPUT;
5696 value = XKeysymToString (keysym);
5697 UNBLOCK_INPUT;
5698
5699 return value;
5700 }
5701
5702
5703 \f
5704 /* Mouse clicks and mouse movement. Rah. */
5705
5706 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5707 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5708 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5709 not force the value into range. */
5710
5711 void
5712 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5713 FRAME_PTR f;
5714 register int pix_x, pix_y;
5715 register int *x, *y;
5716 XRectangle *bounds;
5717 int noclip;
5718 {
5719 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5720 even for negative values. */
5721 if (pix_x < 0)
5722 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
5723 if (pix_y < 0)
5724 pix_y -= (f)->output_data.x->line_height - 1;
5725
5726 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5727 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5728
5729 if (bounds)
5730 {
5731 bounds->width = FONT_WIDTH (f->output_data.x->font);
5732 bounds->height = f->output_data.x->line_height;
5733 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5734 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5735 }
5736
5737 if (!noclip)
5738 {
5739 if (pix_x < 0)
5740 pix_x = 0;
5741 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5742 pix_x = FRAME_WINDOW_WIDTH (f);
5743
5744 if (pix_y < 0)
5745 pix_y = 0;
5746 else if (pix_y > f->height)
5747 pix_y = f->height;
5748 }
5749
5750 *x = pix_x;
5751 *y = pix_y;
5752 }
5753
5754
5755 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5756 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5757 can't tell the positions because W's display is not up to date,
5758 return 0. */
5759
5760 int
5761 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5762 struct window *w;
5763 int hpos, vpos;
5764 int *frame_x, *frame_y;
5765 {
5766 int success_p;
5767
5768 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5769 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5770
5771 if (display_completed)
5772 {
5773 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5774 struct glyph *glyph = row->glyphs[TEXT_AREA];
5775 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5776
5777 *frame_y = row->y;
5778 *frame_x = row->x;
5779 while (glyph < end)
5780 {
5781 *frame_x += glyph->pixel_width;
5782 ++glyph;
5783 }
5784
5785 success_p = 1;
5786 }
5787 else
5788 {
5789 *frame_y = *frame_x = 0;
5790 success_p = 0;
5791 }
5792
5793 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5794 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5795 return success_p;
5796 }
5797
5798
5799 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5800
5801 If the event is a button press, then note that we have grabbed
5802 the mouse. */
5803
5804 static Lisp_Object
5805 construct_mouse_click (result, event, f)
5806 struct input_event *result;
5807 XButtonEvent *event;
5808 struct frame *f;
5809 {
5810 /* Make the event type no_event; we'll change that when we decide
5811 otherwise. */
5812 result->kind = mouse_click;
5813 result->code = event->button - Button1;
5814 result->timestamp = event->time;
5815 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5816 event->state)
5817 | (event->type == ButtonRelease
5818 ? up_modifier
5819 : down_modifier));
5820
5821 XSETINT (result->x, event->x);
5822 XSETINT (result->y, event->y);
5823 XSETFRAME (result->frame_or_window, f);
5824 return Qnil;
5825 }
5826
5827 #if 0 /* This function isn't called. --gerd */
5828
5829 /* Prepare a menu-event in *RESULT for placement in the input queue. */
5830
5831 static Lisp_Object
5832 construct_menu_click (result, event, f)
5833 struct input_event *result;
5834 XButtonEvent *event;
5835 struct frame *f;
5836 {
5837 /* Make the event type no_event; we'll change that when we decide
5838 otherwise. */
5839 result->kind = mouse_click;
5840 result->code = event->button - Button1;
5841 result->timestamp = event->time;
5842 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5843 event->state)
5844 | (event->type == ButtonRelease
5845 ? up_modifier
5846 : down_modifier));
5847
5848 XSETINT (result->x, event->x);
5849 XSETINT (result->y, -1);
5850 XSETFRAME (result->frame_or_window, f);
5851 }
5852
5853 #endif /* 0 */
5854
5855 \f
5856 /* Function to report a mouse movement to the mainstream Emacs code.
5857 The input handler calls this.
5858
5859 We have received a mouse movement event, which is given in *event.
5860 If the mouse is over a different glyph than it was last time, tell
5861 the mainstream emacs code by setting mouse_moved. If not, ask for
5862 another motion event, so we can check again the next time it moves. */
5863
5864 static XMotionEvent last_mouse_motion_event;
5865 static Lisp_Object last_mouse_motion_frame;
5866
5867 static void
5868 note_mouse_movement (frame, event)
5869 FRAME_PTR frame;
5870 XMotionEvent *event;
5871 {
5872 last_mouse_movement_time = event->time;
5873 last_mouse_motion_event = *event;
5874 XSETFRAME (last_mouse_motion_frame, frame);
5875
5876 if (event->window != FRAME_X_WINDOW (frame))
5877 {
5878 frame->mouse_moved = 1;
5879 last_mouse_scroll_bar = Qnil;
5880 note_mouse_highlight (frame, -1, -1);
5881 }
5882
5883 /* Has the mouse moved off the glyph it was on at the last sighting? */
5884 else if (event->x < last_mouse_glyph.x
5885 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
5886 || event->y < last_mouse_glyph.y
5887 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
5888 {
5889 frame->mouse_moved = 1;
5890 last_mouse_scroll_bar = Qnil;
5891 note_mouse_highlight (frame, event->x, event->y);
5892 }
5893 }
5894
5895 /* This is used for debugging, to turn off note_mouse_highlight. */
5896
5897 int disable_mouse_highlight;
5898
5899
5900 \f
5901 /************************************************************************
5902 Mouse Face
5903 ************************************************************************/
5904
5905 /* Find the glyph under window-relative coordinates X/Y in window W.
5906 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5907 strings. Return in *HPOS and *VPOS the row and column number of
5908 the glyph found. Return in *AREA the glyph area containing X.
5909 Value is a pointer to the glyph found or null if X/Y is not on
5910 text, or we can't tell because W's current matrix is not up to
5911 date. */
5912
5913 static struct glyph *
5914 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5915 struct window *w;
5916 int x, y;
5917 int *hpos, *vpos, *area;
5918 {
5919 struct glyph *glyph, *end;
5920 struct glyph_row *row;
5921 int x0, i, left_area_width;
5922
5923 /* Find row containing Y. Give up if some row is not enabled. */
5924 for (i = 0; i < w->current_matrix->nrows; ++i)
5925 {
5926 row = MATRIX_ROW (w->current_matrix, i);
5927 if (!row->enabled_p)
5928 return NULL;
5929 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5930 break;
5931 }
5932
5933 *vpos = i;
5934 *hpos = 0;
5935
5936 /* Give up if Y is not in the window. */
5937 if (i == w->current_matrix->nrows)
5938 return NULL;
5939
5940 /* Get the glyph area containing X. */
5941 if (w->pseudo_window_p)
5942 {
5943 *area = TEXT_AREA;
5944 x0 = 0;
5945 }
5946 else
5947 {
5948 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5949 if (x < left_area_width)
5950 {
5951 *area = LEFT_MARGIN_AREA;
5952 x0 = 0;
5953 }
5954 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5955 {
5956 *area = TEXT_AREA;
5957 x0 = row->x + left_area_width;
5958 }
5959 else
5960 {
5961 *area = RIGHT_MARGIN_AREA;
5962 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5963 }
5964 }
5965
5966 /* Find glyph containing X. */
5967 glyph = row->glyphs[*area];
5968 end = glyph + row->used[*area];
5969 while (glyph < end)
5970 {
5971 if (x < x0 + glyph->pixel_width)
5972 {
5973 if (w->pseudo_window_p)
5974 break;
5975 else if (BUFFERP (glyph->object))
5976 break;
5977 }
5978
5979 x0 += glyph->pixel_width;
5980 ++glyph;
5981 }
5982
5983 if (glyph == end)
5984 return NULL;
5985
5986 *hpos = glyph - row->glyphs[*area];
5987 return glyph;
5988 }
5989
5990
5991 /* Convert frame-relative x/y to coordinates relative to window W.
5992 Takes pseudo-windows into account. */
5993
5994 static void
5995 frame_to_window_pixel_xy (w, x, y)
5996 struct window *w;
5997 int *x, *y;
5998 {
5999 if (w->pseudo_window_p)
6000 {
6001 /* A pseudo-window is always full-width, and starts at the
6002 left edge of the frame, plus a frame border. */
6003 struct frame *f = XFRAME (w->frame);
6004 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6005 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6006 }
6007 else
6008 {
6009 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6010 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6011 }
6012 }
6013
6014
6015 /* Take proper action when mouse has moved to the mode or top line of
6016 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6017 mode line. X is relative to the start of the text display area of
6018 W, so the width of bitmap areas and scroll bars must be subtracted
6019 to get a position relative to the start of the mode line. */
6020
6021 static void
6022 note_mode_line_highlight (w, x, mode_line_p)
6023 struct window *w;
6024 int x, mode_line_p;
6025 {
6026 struct frame *f = XFRAME (w->frame);
6027 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6028 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6029 struct glyph_row *row;
6030
6031 if (mode_line_p)
6032 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6033 else
6034 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6035
6036 if (row->enabled_p)
6037 {
6038 struct glyph *glyph, *end;
6039 Lisp_Object help, map;
6040 int x0;
6041
6042 /* Find the glyph under X. */
6043 glyph = row->glyphs[TEXT_AREA];
6044 end = glyph + row->used[TEXT_AREA];
6045 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6046 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6047 while (glyph < end
6048 && x >= x0 + glyph->pixel_width)
6049 {
6050 x0 += glyph->pixel_width;
6051 ++glyph;
6052 }
6053
6054 if (glyph < end
6055 && STRINGP (glyph->object)
6056 && XSTRING (glyph->object)->intervals
6057 && glyph->charpos >= 0
6058 && glyph->charpos < XSTRING (glyph->object)->size)
6059 {
6060 /* If we're on a string with `help-echo' text property,
6061 arrange for the help to be displayed. This is done by
6062 setting the global variable help_echo to the help string. */
6063 help = Fget_text_property (make_number (glyph->charpos),
6064 Qhelp_echo, glyph->object);
6065 if (STRINGP (help))
6066 help_echo = help;
6067
6068 /* Change the mouse pointer according to what is under X/Y. */
6069 map = Fget_text_property (make_number (glyph->charpos),
6070 Qlocal_map, glyph->object);
6071 if (!NILP (Fkeymapp (map)))
6072 cursor = f->output_data.x->nontext_cursor;
6073 }
6074 }
6075
6076 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6077 }
6078
6079
6080 /* Take proper action when the mouse has moved to position X, Y on
6081 frame F as regards highlighting characters that have mouse-face
6082 properties. Also de-highlighting chars where the mouse was before.
6083 X and Y can be negative or out of range. */
6084
6085 static void
6086 note_mouse_highlight (f, x, y)
6087 struct frame *f;
6088 int x, y;
6089 {
6090 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6091 int portion;
6092 Lisp_Object window;
6093 struct window *w;
6094
6095 /* When a menu is active, don't highlight because this looks odd. */
6096 #ifdef USE_X_TOOLKIT
6097 if (popup_activated ())
6098 return;
6099 #endif
6100
6101 if (disable_mouse_highlight)
6102 return;
6103
6104 dpyinfo->mouse_face_mouse_x = x;
6105 dpyinfo->mouse_face_mouse_y = y;
6106 dpyinfo->mouse_face_mouse_frame = f;
6107
6108 if (dpyinfo->mouse_face_defer)
6109 return;
6110
6111 if (gc_in_progress)
6112 {
6113 dpyinfo->mouse_face_deferred_gc = 1;
6114 return;
6115 }
6116
6117 /* Which window is that in? */
6118 window = window_from_coordinates (f, x, y, &portion, 1);
6119
6120 /* If we were displaying active text in another window, clear that. */
6121 if (! EQ (window, dpyinfo->mouse_face_window))
6122 clear_mouse_face (dpyinfo);
6123
6124 /* Not on a window -> return. */
6125 if (!WINDOWP (window))
6126 return;
6127
6128 /* Convert to window-relative pixel coordinates. */
6129 w = XWINDOW (window);
6130 frame_to_window_pixel_xy (w, &x, &y);
6131
6132 /* Handle tool-bar window differently since it doesn't display a
6133 buffer. */
6134 if (EQ (window, f->tool_bar_window))
6135 {
6136 note_tool_bar_highlight (f, x, y);
6137 return;
6138 }
6139
6140 if (portion == 1 || portion == 3)
6141 {
6142 /* Mouse is on the mode or top line. */
6143 note_mode_line_highlight (w, x, portion == 1);
6144 return;
6145 }
6146 else
6147 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6148 f->output_data.x->text_cursor);
6149
6150 /* Are we in a window whose display is up to date?
6151 And verify the buffer's text has not changed. */
6152 if (/* Within text portion of the window. */
6153 portion == 0
6154 && EQ (w->window_end_valid, w->buffer)
6155 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6156 && (XFASTINT (w->last_overlay_modified)
6157 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6158 {
6159 int hpos, vpos, pos, i, area;
6160 struct glyph *glyph;
6161
6162 /* Find the glyph under X/Y. */
6163 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6164
6165 /* Clear mouse face if X/Y not over text. */
6166 if (glyph == NULL
6167 || area != TEXT_AREA
6168 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6169 {
6170 clear_mouse_face (dpyinfo);
6171 return;
6172 }
6173
6174 pos = glyph->charpos;
6175 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6176
6177 /* Check for mouse-face and help-echo. */
6178 {
6179 Lisp_Object mouse_face, overlay, position;
6180 Lisp_Object *overlay_vec;
6181 int len, noverlays;
6182 struct buffer *obuf;
6183 int obegv, ozv;
6184
6185 /* If we get an out-of-range value, return now; avoid an error. */
6186 if (pos > BUF_Z (XBUFFER (w->buffer)))
6187 return;
6188
6189 /* Make the window's buffer temporarily current for
6190 overlays_at and compute_char_face. */
6191 obuf = current_buffer;
6192 current_buffer = XBUFFER (w->buffer);
6193 obegv = BEGV;
6194 ozv = ZV;
6195 BEGV = BEG;
6196 ZV = Z;
6197
6198 /* Is this char mouse-active or does it have help-echo? */
6199 XSETINT (position, pos);
6200
6201 /* Put all the overlays we want in a vector in overlay_vec.
6202 Store the length in len. If there are more than 10, make
6203 enough space for all, and try again. */
6204 len = 10;
6205 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6206 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6207 if (noverlays > len)
6208 {
6209 len = noverlays;
6210 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6211 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6212 }
6213
6214 noverlays = sort_overlays (overlay_vec, noverlays, w);
6215
6216 /* Check mouse-face highlighting. */
6217 if (! (EQ (window, dpyinfo->mouse_face_window)
6218 && vpos >= dpyinfo->mouse_face_beg_row
6219 && vpos <= dpyinfo->mouse_face_end_row
6220 && (vpos > dpyinfo->mouse_face_beg_row
6221 || hpos >= dpyinfo->mouse_face_beg_col)
6222 && (vpos < dpyinfo->mouse_face_end_row
6223 || hpos < dpyinfo->mouse_face_end_col
6224 || dpyinfo->mouse_face_past_end)))
6225 {
6226 /* Clear the display of the old active region, if any. */
6227 clear_mouse_face (dpyinfo);
6228
6229 /* Find the highest priority overlay that has a mouse-face prop. */
6230 overlay = Qnil;
6231 for (i = 0; i < noverlays; i++)
6232 {
6233 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6234 if (!NILP (mouse_face))
6235 {
6236 overlay = overlay_vec[i];
6237 break;
6238 }
6239 }
6240
6241 /* If no overlay applies, get a text property. */
6242 if (NILP (overlay))
6243 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6244
6245 /* Handle the overlay case. */
6246 if (! NILP (overlay))
6247 {
6248 /* Find the range of text around this char that
6249 should be active. */
6250 Lisp_Object before, after;
6251 int ignore;
6252
6253 before = Foverlay_start (overlay);
6254 after = Foverlay_end (overlay);
6255 /* Record this as the current active region. */
6256 fast_find_position (w, XFASTINT (before),
6257 &dpyinfo->mouse_face_beg_col,
6258 &dpyinfo->mouse_face_beg_row,
6259 &dpyinfo->mouse_face_beg_x,
6260 &dpyinfo->mouse_face_beg_y);
6261 dpyinfo->mouse_face_past_end
6262 = !fast_find_position (w, XFASTINT (after),
6263 &dpyinfo->mouse_face_end_col,
6264 &dpyinfo->mouse_face_end_row,
6265 &dpyinfo->mouse_face_end_x,
6266 &dpyinfo->mouse_face_end_y);
6267 dpyinfo->mouse_face_window = window;
6268 dpyinfo->mouse_face_face_id
6269 = face_at_buffer_position (w, pos, 0, 0,
6270 &ignore, pos + 1, 1);
6271
6272 /* Display it as active. */
6273 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6274 }
6275 /* Handle the text property case. */
6276 else if (! NILP (mouse_face))
6277 {
6278 /* Find the range of text around this char that
6279 should be active. */
6280 Lisp_Object before, after, beginning, end;
6281 int ignore;
6282
6283 beginning = Fmarker_position (w->start);
6284 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6285 - XFASTINT (w->window_end_pos)));
6286 before
6287 = Fprevious_single_property_change (make_number (pos + 1),
6288 Qmouse_face,
6289 w->buffer, beginning);
6290 after
6291 = Fnext_single_property_change (position, Qmouse_face,
6292 w->buffer, end);
6293 /* Record this as the current active region. */
6294 fast_find_position (w, XFASTINT (before),
6295 &dpyinfo->mouse_face_beg_col,
6296 &dpyinfo->mouse_face_beg_row,
6297 &dpyinfo->mouse_face_beg_x,
6298 &dpyinfo->mouse_face_beg_y);
6299 dpyinfo->mouse_face_past_end
6300 = !fast_find_position (w, XFASTINT (after),
6301 &dpyinfo->mouse_face_end_col,
6302 &dpyinfo->mouse_face_end_row,
6303 &dpyinfo->mouse_face_end_x,
6304 &dpyinfo->mouse_face_end_y);
6305 dpyinfo->mouse_face_window = window;
6306 dpyinfo->mouse_face_face_id
6307 = face_at_buffer_position (w, pos, 0, 0,
6308 &ignore, pos + 1, 1);
6309
6310 /* Display it as active. */
6311 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6312 }
6313 }
6314
6315 /* Look for a `help-echo' property. */
6316 {
6317 Lisp_Object help;
6318
6319 /* Check overlays first. */
6320 help = Qnil;
6321 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6322 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6323
6324 /* Try text properties. */
6325 if (!STRINGP (help)
6326 && ((STRINGP (glyph->object)
6327 && glyph->charpos >= 0
6328 && glyph->charpos < XSTRING (glyph->object)->size)
6329 || (BUFFERP (glyph->object)
6330 && glyph->charpos >= BEGV
6331 && glyph->charpos < ZV)))
6332 help = Fget_text_property (make_number (glyph->charpos),
6333 Qhelp_echo, glyph->object);
6334
6335 if (STRINGP (help))
6336 help_echo = help;
6337 }
6338
6339 BEGV = obegv;
6340 ZV = ozv;
6341 current_buffer = obuf;
6342 }
6343 }
6344 }
6345
6346 static void
6347 redo_mouse_highlight ()
6348 {
6349 if (!NILP (last_mouse_motion_frame)
6350 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6351 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6352 last_mouse_motion_event.x,
6353 last_mouse_motion_event.y);
6354 }
6355
6356
6357 \f
6358 /***********************************************************************
6359 Tool-bars
6360 ***********************************************************************/
6361
6362 static int x_tool_bar_item P_ ((struct frame *, int, int,
6363 struct glyph **, int *, int *, int *));
6364
6365 /* Tool-bar item index of the item on which a mouse button was pressed
6366 or -1. */
6367
6368 static int last_tool_bar_item;
6369
6370
6371 /* Get information about the tool-bar item at position X/Y on frame F.
6372 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6373 the current matrix of the tool-bar window of F, or NULL if not
6374 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6375 item in F->current_tool_bar_items. Value is
6376
6377 -1 if X/Y is not on a tool-bar item
6378 0 if X/Y is on the same item that was highlighted before.
6379 1 otherwise. */
6380
6381 static int
6382 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6383 struct frame *f;
6384 int x, y;
6385 struct glyph **glyph;
6386 int *hpos, *vpos, *prop_idx;
6387 {
6388 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6389 struct window *w = XWINDOW (f->tool_bar_window);
6390 int area;
6391
6392 /* Find the glyph under X/Y. */
6393 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6394 if (*glyph == NULL)
6395 return -1;
6396
6397 /* Get the start of this tool-bar item's properties in
6398 f->current_tool_bar_items. */
6399 if (!tool_bar_item_info (f, *glyph, prop_idx))
6400 return -1;
6401
6402 /* Is mouse on the highlighted item? */
6403 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6404 && *vpos >= dpyinfo->mouse_face_beg_row
6405 && *vpos <= dpyinfo->mouse_face_end_row
6406 && (*vpos > dpyinfo->mouse_face_beg_row
6407 || *hpos >= dpyinfo->mouse_face_beg_col)
6408 && (*vpos < dpyinfo->mouse_face_end_row
6409 || *hpos < dpyinfo->mouse_face_end_col
6410 || dpyinfo->mouse_face_past_end))
6411 return 0;
6412
6413 return 1;
6414 }
6415
6416
6417 /* Handle mouse button event on the tool-bar of frame F, at
6418 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6419 or ButtonRelase. */
6420
6421 static void
6422 x_handle_tool_bar_click (f, button_event)
6423 struct frame *f;
6424 XButtonEvent *button_event;
6425 {
6426 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6427 struct window *w = XWINDOW (f->tool_bar_window);
6428 int hpos, vpos, prop_idx;
6429 struct glyph *glyph;
6430 Lisp_Object enabled_p;
6431 int x = button_event->x;
6432 int y = button_event->y;
6433
6434 /* If not on the highlighted tool-bar item, return. */
6435 frame_to_window_pixel_xy (w, &x, &y);
6436 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6437 return;
6438
6439 /* If item is disabled, do nothing. */
6440 enabled_p = (XVECTOR (f->current_tool_bar_items)
6441 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6442 if (NILP (enabled_p))
6443 return;
6444
6445 if (button_event->type == ButtonPress)
6446 {
6447 /* Show item in pressed state. */
6448 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6449 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6450 last_tool_bar_item = prop_idx;
6451 }
6452 else
6453 {
6454 Lisp_Object key, frame;
6455 struct input_event event;
6456
6457 /* Show item in released state. */
6458 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6459 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6460
6461 key = (XVECTOR (f->current_tool_bar_items)
6462 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6463
6464 XSETFRAME (frame, f);
6465 event.kind = TOOL_BAR_EVENT;
6466 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6467 kbd_buffer_store_event (&event);
6468
6469 event.kind = TOOL_BAR_EVENT;
6470 event.frame_or_window = Fcons (frame, key);
6471 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6472 button_event->state);
6473 kbd_buffer_store_event (&event);
6474 last_tool_bar_item = -1;
6475 }
6476 }
6477
6478
6479 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6480 tool-bar window-relative coordinates X/Y. Called from
6481 note_mouse_highlight. */
6482
6483 static void
6484 note_tool_bar_highlight (f, x, y)
6485 struct frame *f;
6486 int x, y;
6487 {
6488 Lisp_Object window = f->tool_bar_window;
6489 struct window *w = XWINDOW (window);
6490 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6491 int hpos, vpos;
6492 struct glyph *glyph;
6493 struct glyph_row *row;
6494 int i;
6495 Lisp_Object enabled_p;
6496 int prop_idx;
6497 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6498 int mouse_down_p, rc;
6499
6500 /* Function note_mouse_highlight is called with negative x(y
6501 values when mouse moves outside of the frame. */
6502 if (x <= 0 || y <= 0)
6503 {
6504 clear_mouse_face (dpyinfo);
6505 return;
6506 }
6507
6508 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6509 if (rc < 0)
6510 {
6511 /* Not on tool-bar item. */
6512 clear_mouse_face (dpyinfo);
6513 return;
6514 }
6515 else if (rc == 0)
6516 /* On same tool-bar item as before. */
6517 goto set_help_echo;
6518
6519 clear_mouse_face (dpyinfo);
6520
6521 /* Mouse is down, but on different tool-bar item? */
6522 mouse_down_p = (dpyinfo->grabbed
6523 && f == last_mouse_frame
6524 && FRAME_LIVE_P (f));
6525 if (mouse_down_p
6526 && last_tool_bar_item != prop_idx)
6527 return;
6528
6529 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6530 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6531
6532 /* If tool-bar item is not enabled, don't highlight it. */
6533 enabled_p = (XVECTOR (f->current_tool_bar_items)
6534 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6535 if (!NILP (enabled_p))
6536 {
6537 /* Compute the x-position of the glyph. In front and past the
6538 image is a space. We include this is the highlighted area. */
6539 row = MATRIX_ROW (w->current_matrix, vpos);
6540 for (i = x = 0; i < hpos; ++i)
6541 x += row->glyphs[TEXT_AREA][i].pixel_width;
6542
6543 /* Record this as the current active region. */
6544 dpyinfo->mouse_face_beg_col = hpos;
6545 dpyinfo->mouse_face_beg_row = vpos;
6546 dpyinfo->mouse_face_beg_x = x;
6547 dpyinfo->mouse_face_beg_y = row->y;
6548 dpyinfo->mouse_face_past_end = 0;
6549
6550 dpyinfo->mouse_face_end_col = hpos + 1;
6551 dpyinfo->mouse_face_end_row = vpos;
6552 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6553 dpyinfo->mouse_face_end_y = row->y;
6554 dpyinfo->mouse_face_window = window;
6555 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6556
6557 /* Display it as active. */
6558 show_mouse_face (dpyinfo, draw);
6559 dpyinfo->mouse_face_image_state = draw;
6560 }
6561
6562 set_help_echo:
6563
6564 /* Set help_echo to a help string.to display for this tool-bar item.
6565 XTread_socket does the rest. */
6566 help_echo = (XVECTOR (f->current_tool_bar_items)
6567 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6568 if (!STRINGP (help_echo))
6569 help_echo = (XVECTOR (f->current_tool_bar_items)
6570 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6571 }
6572
6573
6574 \f
6575 /* Find the glyph matrix position of buffer position POS in window W.
6576 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6577 current glyphs must be up to date. If POS is above window start
6578 return (0, 0, 0, 0). If POS is after end of W, return end of
6579 last line in W. */
6580
6581 static int
6582 fast_find_position (w, pos, hpos, vpos, x, y)
6583 struct window *w;
6584 int pos;
6585 int *hpos, *vpos, *x, *y;
6586 {
6587 int i;
6588 int lastcol;
6589 int maybe_next_line_p = 0;
6590 int line_start_position;
6591 int yb = window_text_bottom_y (w);
6592 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6593 struct glyph_row *best_row = row;
6594 int row_vpos = 0, best_row_vpos = 0;
6595 int current_x;
6596
6597 while (row->y < yb)
6598 {
6599 if (row->used[TEXT_AREA])
6600 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6601 else
6602 line_start_position = 0;
6603
6604 if (line_start_position > pos)
6605 break;
6606 /* If the position sought is the end of the buffer,
6607 don't include the blank lines at the bottom of the window. */
6608 else if (line_start_position == pos
6609 && pos == BUF_ZV (XBUFFER (w->buffer)))
6610 {
6611 maybe_next_line_p = 1;
6612 break;
6613 }
6614 else if (line_start_position > 0)
6615 {
6616 best_row = row;
6617 best_row_vpos = row_vpos;
6618 }
6619
6620 ++row;
6621 ++row_vpos;
6622 }
6623
6624 /* Find the right column within BEST_ROW. */
6625 lastcol = 0;
6626 current_x = best_row->x;
6627 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6628 {
6629 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6630 int charpos;
6631
6632 charpos = glyph->charpos;
6633 if (charpos == pos)
6634 {
6635 *hpos = i;
6636 *vpos = best_row_vpos;
6637 *x = current_x;
6638 *y = best_row->y;
6639 return 1;
6640 }
6641 else if (charpos > pos)
6642 break;
6643 else if (charpos > 0)
6644 lastcol = i;
6645
6646 current_x += glyph->pixel_width;
6647 }
6648
6649 /* If we're looking for the end of the buffer,
6650 and we didn't find it in the line we scanned,
6651 use the start of the following line. */
6652 if (maybe_next_line_p)
6653 {
6654 ++best_row;
6655 ++best_row_vpos;
6656 lastcol = 0;
6657 current_x = best_row->x;
6658 }
6659
6660 *vpos = best_row_vpos;
6661 *hpos = lastcol + 1;
6662 *x = current_x;
6663 *y = best_row->y;
6664 return 0;
6665 }
6666
6667
6668 /* Display the active region described by mouse_face_*
6669 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6670
6671 static void
6672 show_mouse_face (dpyinfo, draw)
6673 struct x_display_info *dpyinfo;
6674 enum draw_glyphs_face draw;
6675 {
6676 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6677 struct frame *f = XFRAME (WINDOW_FRAME (w));
6678 int i;
6679 int cursor_off_p = 0;
6680 struct cursor_pos saved_cursor;
6681
6682 saved_cursor = output_cursor;
6683
6684 /* If window is in the process of being destroyed, don't bother
6685 to do anything. */
6686 if (w->current_matrix == NULL)
6687 goto set_x_cursor;
6688
6689 /* Recognize when we are called to operate on rows that don't exist
6690 anymore. This can happen when a window is split. */
6691 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6692 goto set_x_cursor;
6693
6694 set_output_cursor (&w->phys_cursor);
6695
6696 /* Note that mouse_face_beg_row etc. are window relative. */
6697 for (i = dpyinfo->mouse_face_beg_row;
6698 i <= dpyinfo->mouse_face_end_row;
6699 i++)
6700 {
6701 int start_hpos, end_hpos, start_x;
6702 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6703
6704 /* Don't do anything if row doesn't have valid contents. */
6705 if (!row->enabled_p)
6706 continue;
6707
6708 /* For all but the first row, the highlight starts at column 0. */
6709 if (i == dpyinfo->mouse_face_beg_row)
6710 {
6711 start_hpos = dpyinfo->mouse_face_beg_col;
6712 start_x = dpyinfo->mouse_face_beg_x;
6713 }
6714 else
6715 {
6716 start_hpos = 0;
6717 start_x = 0;
6718 }
6719
6720 if (i == dpyinfo->mouse_face_end_row)
6721 end_hpos = dpyinfo->mouse_face_end_col;
6722 else
6723 end_hpos = row->used[TEXT_AREA];
6724
6725 /* If the cursor's in the text we are about to rewrite, turn the
6726 cursor off. */
6727 if (!w->pseudo_window_p
6728 && i == output_cursor.vpos
6729 && output_cursor.hpos >= start_hpos - 1
6730 && output_cursor.hpos <= end_hpos)
6731 {
6732 x_update_window_cursor (w, 0);
6733 cursor_off_p = 1;
6734 }
6735
6736 if (end_hpos > start_hpos)
6737 x_draw_glyphs (w, start_x, row, updated_area,
6738 start_hpos, end_hpos, draw, NULL, NULL, 0);
6739 }
6740
6741 /* If we turned the cursor off, turn it back on. */
6742 if (cursor_off_p)
6743 x_display_cursor (w, 1,
6744 output_cursor.hpos, output_cursor.vpos,
6745 output_cursor.x, output_cursor.y);
6746
6747 output_cursor = saved_cursor;
6748
6749 set_x_cursor:
6750
6751 /* Change the mouse cursor. */
6752 if (draw == DRAW_NORMAL_TEXT)
6753 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6754 f->output_data.x->text_cursor);
6755 else if (draw == DRAW_MOUSE_FACE)
6756 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6757 f->output_data.x->cross_cursor);
6758 else
6759 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6760 f->output_data.x->nontext_cursor);
6761 }
6762
6763 /* Clear out the mouse-highlighted active region.
6764 Redraw it un-highlighted first. */
6765
6766 void
6767 clear_mouse_face (dpyinfo)
6768 struct x_display_info *dpyinfo;
6769 {
6770 if (tip_frame)
6771 return;
6772
6773 if (! NILP (dpyinfo->mouse_face_window))
6774 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6775
6776 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6777 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6778 dpyinfo->mouse_face_window = Qnil;
6779 }
6780
6781 /* Just discard the mouse face information for frame F, if any.
6782 This is used when the size of F is changed. */
6783
6784 void
6785 cancel_mouse_face (f)
6786 FRAME_PTR f;
6787 {
6788 Lisp_Object window;
6789 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6790
6791 window = dpyinfo->mouse_face_window;
6792 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6793 {
6794 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6795 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6796 dpyinfo->mouse_face_window = Qnil;
6797 }
6798 }
6799 \f
6800 static struct scroll_bar *x_window_to_scroll_bar ();
6801 static void x_scroll_bar_report_motion ();
6802
6803 /* Return the current position of the mouse.
6804 *fp should be a frame which indicates which display to ask about.
6805
6806 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6807 and *part to the frame, window, and scroll bar part that the mouse
6808 is over. Set *x and *y to the portion and whole of the mouse's
6809 position on the scroll bar.
6810
6811 If the mouse movement started elsewhere, set *fp to the frame the
6812 mouse is on, *bar_window to nil, and *x and *y to the character cell
6813 the mouse is over.
6814
6815 Set *time to the server time-stamp for the time at which the mouse
6816 was at this position.
6817
6818 Don't store anything if we don't have a valid set of values to report.
6819
6820 This clears the mouse_moved flag, so we can wait for the next mouse
6821 movement. */
6822
6823 static void
6824 XTmouse_position (fp, insist, bar_window, part, x, y, time)
6825 FRAME_PTR *fp;
6826 int insist;
6827 Lisp_Object *bar_window;
6828 enum scroll_bar_part *part;
6829 Lisp_Object *x, *y;
6830 unsigned long *time;
6831 {
6832 FRAME_PTR f1;
6833
6834 BLOCK_INPUT;
6835
6836 if (! NILP (last_mouse_scroll_bar) && insist == 0)
6837 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
6838 else
6839 {
6840 Window root;
6841 int root_x, root_y;
6842
6843 Window dummy_window;
6844 int dummy;
6845
6846 Lisp_Object frame, tail;
6847
6848 /* Clear the mouse-moved flag for every frame on this display. */
6849 FOR_EACH_FRAME (tail, frame)
6850 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
6851 XFRAME (frame)->mouse_moved = 0;
6852
6853 last_mouse_scroll_bar = Qnil;
6854
6855 /* Figure out which root window we're on. */
6856 XQueryPointer (FRAME_X_DISPLAY (*fp),
6857 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
6858
6859 /* The root window which contains the pointer. */
6860 &root,
6861
6862 /* Trash which we can't trust if the pointer is on
6863 a different screen. */
6864 &dummy_window,
6865
6866 /* The position on that root window. */
6867 &root_x, &root_y,
6868
6869 /* More trash we can't trust. */
6870 &dummy, &dummy,
6871
6872 /* Modifier keys and pointer buttons, about which
6873 we don't care. */
6874 (unsigned int *) &dummy);
6875
6876 /* Now we have a position on the root; find the innermost window
6877 containing the pointer. */
6878 {
6879 Window win, child;
6880 int win_x, win_y;
6881 int parent_x = 0, parent_y = 0;
6882 int count;
6883
6884 win = root;
6885
6886 /* XTranslateCoordinates can get errors if the window
6887 structure is changing at the same time this function
6888 is running. So at least we must not crash from them. */
6889
6890 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
6891
6892 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
6893 && FRAME_LIVE_P (last_mouse_frame))
6894 {
6895 /* If mouse was grabbed on a frame, give coords for that frame
6896 even if the mouse is now outside it. */
6897 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
6898
6899 /* From-window, to-window. */
6900 root, FRAME_X_WINDOW (last_mouse_frame),
6901
6902 /* From-position, to-position. */
6903 root_x, root_y, &win_x, &win_y,
6904
6905 /* Child of win. */
6906 &child);
6907 f1 = last_mouse_frame;
6908 }
6909 else
6910 {
6911 while (1)
6912 {
6913 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
6914
6915 /* From-window, to-window. */
6916 root, win,
6917
6918 /* From-position, to-position. */
6919 root_x, root_y, &win_x, &win_y,
6920
6921 /* Child of win. */
6922 &child);
6923
6924 if (child == None || child == win)
6925 break;
6926
6927 win = child;
6928 parent_x = win_x;
6929 parent_y = win_y;
6930 }
6931
6932 /* Now we know that:
6933 win is the innermost window containing the pointer
6934 (XTC says it has no child containing the pointer),
6935 win_x and win_y are the pointer's position in it
6936 (XTC did this the last time through), and
6937 parent_x and parent_y are the pointer's position in win's parent.
6938 (They are what win_x and win_y were when win was child.
6939 If win is the root window, it has no parent, and
6940 parent_{x,y} are invalid, but that's okay, because we'll
6941 never use them in that case.) */
6942
6943 /* Is win one of our frames? */
6944 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
6945 }
6946
6947 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
6948 f1 = 0;
6949
6950 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
6951
6952 /* If not, is it one of our scroll bars? */
6953 if (! f1)
6954 {
6955 struct scroll_bar *bar = x_window_to_scroll_bar (win);
6956
6957 if (bar)
6958 {
6959 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6960 win_x = parent_x;
6961 win_y = parent_y;
6962 }
6963 }
6964
6965 if (f1 == 0 && insist > 0)
6966 f1 = SELECTED_FRAME ();
6967
6968 if (f1)
6969 {
6970 /* Ok, we found a frame. Store all the values.
6971 last_mouse_glyph is a rectangle used to reduce the
6972 generation of mouse events. To not miss any motion
6973 events, we must divide the frame into rectangles of the
6974 size of the smallest character that could be displayed
6975 on it, i.e. into the same rectangles that matrices on
6976 the frame are divided into. */
6977
6978 #if OLD_REDISPLAY_CODE
6979 int ignore1, ignore2;
6980 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
6981 &last_mouse_glyph,
6982 FRAME_X_DISPLAY_INFO (f1)->grabbed
6983 || insist);
6984 #else
6985 {
6986 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6987 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6988 int x = win_x;
6989 int y = win_y;
6990
6991 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6992 round down even for negative values. */
6993 if (x < 0)
6994 x -= width - 1;
6995 if (y < 0)
6996 y -= height - 1;
6997
6998 last_mouse_glyph.width = width;
6999 last_mouse_glyph.height = height;
7000 last_mouse_glyph.x = (x + width - 1) / width * width;
7001 last_mouse_glyph.y = (y + height - 1) / height * height;
7002 }
7003 #endif
7004
7005 *bar_window = Qnil;
7006 *part = 0;
7007 *fp = f1;
7008 XSETINT (*x, win_x);
7009 XSETINT (*y, win_y);
7010 *time = last_mouse_movement_time;
7011 }
7012 }
7013 }
7014
7015 UNBLOCK_INPUT;
7016 }
7017
7018
7019 DEFUN ("xt-process-timeouts", Fxt_process_timeouts, Sxt_process_timeouts,
7020 0, 0, 0,
7021 "Arrange for Xt timeout callbacks to be called.")
7022 ()
7023 {
7024 #ifdef USE_X_TOOLKIT
7025 BLOCK_INPUT;
7026 while (XtAppPending (Xt_app_con) & XtIMTimer)
7027 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7028 UNBLOCK_INPUT;
7029 #endif /* USE_X_TOOLKIT */
7030
7031 return Qnil;
7032 }
7033
7034
7035 \f
7036 /* Scroll bar support. */
7037
7038 /* Given an X window ID, find the struct scroll_bar which manages it.
7039 This can be called in GC, so we have to make sure to strip off mark
7040 bits. */
7041 static struct scroll_bar *
7042 x_window_to_scroll_bar (window_id)
7043 Window window_id;
7044 {
7045 Lisp_Object tail;
7046
7047 for (tail = Vframe_list;
7048 XGCTYPE (tail) == Lisp_Cons;
7049 tail = XCDR (tail))
7050 {
7051 Lisp_Object frame, bar, condemned;
7052
7053 frame = XCAR (tail);
7054 /* All elements of Vframe_list should be frames. */
7055 if (! GC_FRAMEP (frame))
7056 abort ();
7057
7058 /* Scan this frame's scroll bar list for a scroll bar with the
7059 right window ID. */
7060 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7061 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7062 /* This trick allows us to search both the ordinary and
7063 condemned scroll bar lists with one loop. */
7064 ! GC_NILP (bar) || (bar = condemned,
7065 condemned = Qnil,
7066 ! GC_NILP (bar));
7067 bar = XSCROLL_BAR (bar)->next)
7068 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7069 return XSCROLL_BAR (bar);
7070 }
7071
7072 return 0;
7073 }
7074
7075
7076 \f
7077 /************************************************************************
7078 Toolkit scroll bars
7079 ************************************************************************/
7080
7081 #if USE_TOOLKIT_SCROLL_BARS
7082
7083 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7084 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7085 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7086 struct scroll_bar *));
7087 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7088 int, int, int));
7089
7090
7091 /* Id of action hook installed for scroll bars. */
7092
7093 static XtActionHookId action_hook_id;
7094
7095 /* Lisp window being scrolled. Set when starting to interact with
7096 a toolkit scroll bar, reset to nil when ending the interaction. */
7097
7098 static Lisp_Object window_being_scrolled;
7099
7100 /* Last scroll bar part sent in xm_scroll_callback. */
7101
7102 static int last_scroll_bar_part;
7103
7104
7105 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7106 bars are used.. The hoos is responsible for detecting when
7107 the user ends an interaction with the scroll bar, and generates
7108 a `end-scroll' scroll_bar_click' event if so. */
7109
7110 static void
7111 xt_action_hook (widget, client_data, action_name, event, params,
7112 num_params)
7113 Widget widget;
7114 XtPointer client_data;
7115 String action_name;
7116 XEvent *event;
7117 String *params;
7118 Cardinal *num_params;
7119 {
7120 int scroll_bar_p;
7121 char *end_action;
7122
7123 #ifdef USE_MOTIF
7124 scroll_bar_p = XmIsScrollBar (widget);
7125 end_action = "Release";
7126 #elif defined HAVE_XAW3D
7127 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7128 end_action = "EndScroll";
7129 #else
7130 #error unknown scroll bar toolkit
7131 #endif /* HAVE_XAW3D */
7132
7133 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
7134 let Xt timeouts be processed doesn't work. */
7135 if (scroll_bar_p
7136 && strcmp (action_name, end_action) == 0
7137 && WINDOWP (window_being_scrolled))
7138 {
7139 struct window *w;
7140
7141 x_send_scroll_bar_event (window_being_scrolled,
7142 scroll_bar_end_scroll, 0, 0);
7143 w = XWINDOW (window_being_scrolled);
7144 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7145 window_being_scrolled = Qnil;
7146 last_scroll_bar_part = -1;
7147 }
7148 }
7149
7150
7151 /* Send a client message with message type Xatom_Scrollbar for a
7152 scroll action to the frame of WINDOW. PART is a value identifying
7153 the part of the scroll bar that was clicked on. PORTION is the
7154 amount to scroll of a whole of WHOLE. */
7155
7156 static void
7157 x_send_scroll_bar_event (window, part, portion, whole)
7158 Lisp_Object window;
7159 int part, portion, whole;
7160 {
7161 XEvent event;
7162 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7163 struct frame *f = XFRAME (XWINDOW (window)->frame);
7164
7165 /* Construct a ClientMessage event to send to the frame. */
7166 ev->type = ClientMessage;
7167 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7168 ev->display = FRAME_X_DISPLAY (f);
7169 ev->window = FRAME_X_WINDOW (f);
7170 ev->format = 32;
7171 ev->data.l[0] = (long) window;
7172 ev->data.l[1] = (long) part;
7173 ev->data.l[2] = (long) 0;
7174 ev->data.l[3] = (long) portion;
7175 ev->data.l[4] = (long) whole;
7176
7177 /* Setting the event mask to zero means that the message will
7178 be sent to the client that created the window, and if that
7179 window no longer exists, no event will be sent. */
7180 BLOCK_INPUT;
7181 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7182 UNBLOCK_INPUT;
7183 }
7184
7185
7186 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7187 in *IEVENT. */
7188
7189 static void
7190 x_scroll_bar_to_input_event (event, ievent)
7191 XEvent *event;
7192 struct input_event *ievent;
7193 {
7194 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7195 Lisp_Object window = (Lisp_Object) ev->data.l[0];
7196 struct frame *f = XFRAME (XWINDOW (window)->frame);
7197
7198 ievent->kind = scroll_bar_click;
7199 ievent->frame_or_window = window;
7200 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7201 ievent->part = ev->data.l[1];
7202 ievent->code = ev->data.l[2];
7203 ievent->x = make_number ((int) ev->data.l[3]);
7204 ievent->y = make_number ((int) ev->data.l[4]);
7205 ievent->modifiers = 0;
7206 }
7207
7208
7209 #ifdef USE_MOTIF
7210
7211 /* Minimum and maximum values used for Motif scroll bars. */
7212
7213 #define XM_SB_MIN 1
7214 #define XM_SB_MAX 10000000
7215 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7216
7217
7218 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7219 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7220 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7221
7222 static void
7223 xm_scroll_callback (widget, client_data, call_data)
7224 Widget widget;
7225 XtPointer client_data, call_data;
7226 {
7227 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7228 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7229 double percent;
7230 int part = -1, whole = 0, portion = 0;
7231
7232 switch (cs->reason)
7233 {
7234 case XmCR_DECREMENT:
7235 bar->dragging = Qnil;
7236 part = scroll_bar_up_arrow;
7237 break;
7238
7239 case XmCR_INCREMENT:
7240 bar->dragging = Qnil;
7241 part = scroll_bar_down_arrow;
7242 break;
7243
7244 case XmCR_PAGE_DECREMENT:
7245 bar->dragging = Qnil;
7246 part = scroll_bar_above_handle;
7247 break;
7248
7249 case XmCR_PAGE_INCREMENT:
7250 bar->dragging = Qnil;
7251 part = scroll_bar_below_handle;
7252 break;
7253
7254 case XmCR_TO_TOP:
7255 bar->dragging = Qnil;
7256 part = scroll_bar_to_top;
7257 break;
7258
7259 case XmCR_TO_BOTTOM:
7260 bar->dragging = Qnil;
7261 part = scroll_bar_to_bottom;
7262 break;
7263
7264 case XmCR_DRAG:
7265 {
7266 int slider_size;
7267 int dragging_down_p = (INTEGERP (bar->dragging)
7268 && XINT (bar->dragging) <= cs->value);
7269
7270 /* Get the slider size. */
7271 BLOCK_INPUT;
7272 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7273 UNBLOCK_INPUT;
7274
7275 /* At the max position of the scroll bar, do a line-wise
7276 movement. Without doing anything, the LessTif scroll bar
7277 calls us with the same cs->value again and again. If we
7278 want to make sure that we can reach the end of the buffer,
7279 we have to do something.
7280
7281 Implementation note: setting bar->dragging always to
7282 cs->value gives a smoother movement at the max position.
7283 Setting it to nil when doing line-wise movement gives
7284 a better slider behavior. */
7285
7286 if (cs->value + slider_size == XM_SB_MAX
7287 || (dragging_down_p
7288 && last_scroll_bar_part == scroll_bar_down_arrow))
7289 {
7290 part = scroll_bar_down_arrow;
7291 bar->dragging = Qnil;
7292 }
7293 else
7294 {
7295 whole = XM_SB_RANGE;
7296 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7297 part = scroll_bar_handle;
7298 bar->dragging = make_number (cs->value);
7299 }
7300 }
7301 break;
7302
7303 case XmCR_VALUE_CHANGED:
7304 break;
7305 };
7306
7307 if (part >= 0)
7308 {
7309 window_being_scrolled = bar->window;
7310 last_scroll_bar_part = part;
7311 x_send_scroll_bar_event (bar->window, part, portion, whole);
7312 }
7313 }
7314
7315
7316 #else /* not USE_MOTIF, i.e. XAW3D. */
7317
7318
7319 /* Xaw3d scroll bar callback. Invoked when the thumb is dragged.
7320 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7321 scroll bar struct. CALL_DATA is a pointer to a float saying where
7322 the thumb is. */
7323
7324 static void
7325 xaw3d_jump_callback (widget, client_data, call_data)
7326 Widget widget;
7327 XtPointer client_data, call_data;
7328 {
7329 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7330 float top = *(float *) call_data;
7331 float shown;
7332 int whole, portion;
7333 int dragging_down_p, part;
7334 double epsilon = 0.01;
7335
7336 /* Get the size of the thumb, a value between 0 and 1. */
7337 BLOCK_INPUT;
7338 XtVaGetValues (widget, XtNshown, &shown, NULL);
7339 UNBLOCK_INPUT;
7340
7341 whole = 10000000;
7342 portion = shown < 1 ? top * whole : 0;
7343 dragging_down_p = (INTEGERP (bar->dragging)
7344 && XINT (bar->dragging) < portion);
7345
7346 if (shown < 1
7347 && (abs (top + shown - 1) < epsilon
7348 || (dragging_down_p
7349 && last_scroll_bar_part == scroll_bar_down_arrow)))
7350 part = scroll_bar_down_arrow;
7351 else
7352 part = scroll_bar_handle;
7353
7354 window_being_scrolled = bar->window;
7355 bar->dragging = make_number (portion);
7356 last_scroll_bar_part = part;
7357 x_send_scroll_bar_event (bar->window, part, portion, whole);
7358 }
7359
7360
7361 /* Xaw3d scroll bar callback. Invoked for incremental scrolling.,
7362 i.e. line or page up or down. WIDGET is the Xaw3d scroll bar
7363 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7364 the scroll bar. CALL_DATA is an integer specifying the action that
7365 has taken place. It's magnitude is in the range 0..height of the
7366 scroll bar. Negative values mean scroll towards buffer start.
7367 Values < height of scroll bar mean line-wise movement. */
7368
7369 static void
7370 xaw3d_scroll_callback (widget, client_data, call_data)
7371 Widget widget;
7372 XtPointer client_data, call_data;
7373 {
7374 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7375 int position = (int) call_data;
7376 Dimension height;
7377 int part;
7378
7379 /* Get the height of the scroll bar. */
7380 BLOCK_INPUT;
7381 XtVaGetValues (widget, XtNheight, &height, NULL);
7382 UNBLOCK_INPUT;
7383
7384 if (position < 0)
7385 {
7386 if (abs (position) < height)
7387 part = scroll_bar_up_arrow;
7388 else
7389 part = scroll_bar_above_handle;
7390 }
7391 else
7392 {
7393 if (abs (position) < height)
7394 part = scroll_bar_down_arrow;
7395 else
7396 part = scroll_bar_below_handle;
7397 }
7398
7399 window_being_scrolled = bar->window;
7400 bar->dragging = Qnil;
7401 last_scroll_bar_part = part;
7402 x_send_scroll_bar_event (bar->window, part, 0, 0);
7403 }
7404
7405
7406 #endif /* not USE_MOTIF */
7407
7408
7409 /* Create the widget for scroll bar BAR on frame F. Record the widget
7410 and X window of the scroll bar in BAR. */
7411
7412 static void
7413 x_create_toolkit_scroll_bar (f, bar)
7414 struct frame *f;
7415 struct scroll_bar *bar;
7416 {
7417 Window xwindow;
7418 Widget widget;
7419 Arg av[20];
7420 int ac = 0;
7421 char *scroll_bar_name = "verticalScrollBar";
7422 unsigned long pixel;
7423
7424 BLOCK_INPUT;
7425
7426 #ifdef USE_MOTIF
7427 /* LessTif 0.85, problems:
7428
7429 1. When the mouse if over the scroll bar, the scroll bar will
7430 get keyboard events. I didn't find a way to turn this off.
7431
7432 2. Do we have to explicitly set the cursor to get an arrow
7433 cursor (see below)? */
7434
7435 /* Set resources. Create the widget. */
7436 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7437 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7438 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7439 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7440 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7441 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7442 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7443
7444 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7445 if (pixel != -1)
7446 {
7447 XtSetArg (av[ac], XmNforeground, pixel);
7448 ++ac;
7449 }
7450
7451 pixel = f->output_data.x->scroll_bar_background_pixel;
7452 if (pixel != -1)
7453 {
7454 XtSetArg (av[ac], XmNbackground, pixel);
7455 ++ac;
7456 }
7457
7458 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7459 scroll_bar_name, av, ac);
7460
7461 /* Add one callback for everything that can happen. */
7462 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7463 (XtPointer) bar);
7464 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7465 (XtPointer) bar);
7466 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7467 (XtPointer) bar);
7468 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7469 (XtPointer) bar);
7470 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7471 (XtPointer) bar);
7472 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7473 (XtPointer) bar);
7474 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7475 (XtPointer) bar);
7476
7477 /* Realize the widget. Only after that is the X window created. */
7478 XtRealizeWidget (widget);
7479
7480 /* Set the cursor to an arrow. I didn't find a resource to do that.
7481 And I'm wondering why it hasn't an arrow cursor by default. */
7482 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7483 f->output_data.x->nontext_cursor);
7484
7485 #elif defined HAVE_XAW3D
7486
7487 /* Set resources. Create the widget. The background of the
7488 Xaw3d scroll bar widget is a little bit light for my taste.
7489 We don't alter it here to let users change it according
7490 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7491 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7492 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7493 XtSetArg (av[ac], XtNcursorName, "left_ptr"); ++ac;
7494 XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac;
7495
7496 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7497 if (pixel != -1)
7498 {
7499 XtSetArg (av[ac], XtNforeground, pixel);
7500 ++ac;
7501 }
7502
7503 pixel = f->output_data.x->scroll_bar_background_pixel;
7504 if (pixel != -1)
7505 {
7506 XtSetArg (av[ac], XtNbackground, pixel);
7507 ++ac;
7508 }
7509
7510 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7511 f->output_data.x->edit_widget, av, ac);
7512
7513 /* Define callbacks. */
7514 XtAddCallback (widget, XtNjumpProc, xaw3d_jump_callback, (XtPointer) bar);
7515 XtAddCallback (widget, XtNscrollProc, xaw3d_scroll_callback,
7516 (XtPointer) bar);
7517
7518 /* Realize the widget. Only after that is the X window created. */
7519 XtRealizeWidget (widget);
7520
7521 #endif /* HAVE_XAW3D */
7522
7523 /* Install an action hook that let's us detect when the user
7524 finishes interacting with a scroll bar. */
7525 if (action_hook_id == 0)
7526 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7527
7528 /* Remember X window and widget in the scroll bar vector. */
7529 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7530 xwindow = XtWindow (widget);
7531 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7532
7533 UNBLOCK_INPUT;
7534 }
7535
7536
7537 /* Set the thumb size and position of scroll bar BAR. We are currently
7538 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7539
7540 static void
7541 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7542 struct scroll_bar *bar;
7543 int portion, position, whole;
7544 {
7545 float top, shown;
7546 Widget widget = SCROLL_BAR_X_WIDGET (bar);
7547
7548 if (whole == 0)
7549 top = 0, shown = 1;
7550 else
7551 {
7552 top = (float) position / whole;
7553 shown = (float) portion / whole;
7554 }
7555
7556 BLOCK_INPUT;
7557
7558 #ifdef USE_MOTIF
7559 {
7560 int size, value;
7561 Boolean arrow1_selected, arrow2_selected;
7562 unsigned char flags;
7563 XmScrollBarWidget sb;
7564
7565 /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX
7566 is the scroll bar's maximum and MIN is the scroll bar's minimum
7567 value. */
7568 size = shown * XM_SB_RANGE;
7569 size = min (size, XM_SB_RANGE);
7570 size = max (size, 1);
7571
7572 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7573 value = top * XM_SB_RANGE;
7574 value = min (value, XM_SB_MAX - size);
7575 value = max (value, XM_SB_MIN);
7576
7577 /* LessTif: Calling XmScrollBarSetValues after an increment or
7578 decrement turns off auto-repeat LessTif-internally. This can
7579 be seen in ScrollBar.c which resets Arrow1Selected and
7580 Arrow2Selected. It also sets internal flags so that LessTif
7581 believes the mouse is in the slider. We either have to change
7582 our code, or work around that by accessing private data. */
7583
7584 sb = (XmScrollBarWidget) widget;
7585 arrow1_selected = sb->scrollBar.arrow1_selected;
7586 arrow2_selected = sb->scrollBar.arrow2_selected;
7587 flags = sb->scrollBar.flags;
7588
7589 if (NILP (bar->dragging))
7590 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7591 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7592 /* This has the negative side effect that the slider value is
7593 not would it would be if we scrolled here using line-wise or
7594 page-wise movement. */
7595 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7596 else
7597 {
7598 /* If currently dragging, only update the slider size.
7599 This reduces flicker effects. */
7600 int old_value, old_size, increment, page_increment;
7601
7602 XmScrollBarGetValues (widget, &old_value, &old_size,
7603 &increment, &page_increment);
7604 XmScrollBarSetValues (widget, old_value,
7605 min (size, XM_SB_RANGE - old_value),
7606 0, 0, False);
7607 }
7608
7609 sb->scrollBar.arrow1_selected = arrow1_selected;
7610 sb->scrollBar.arrow2_selected = arrow2_selected;
7611 sb->scrollBar.flags = flags;
7612 }
7613 #elif defined HAVE_XAW3D
7614 {
7615 /* Restrict to [0 1]. */
7616 top = max (0, min (1, top));
7617 shown = max (0, min (1, shown));
7618
7619 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7620 check that your system's configuration file contains a define
7621 for `NARROWPROTO'. See s/freebsd.h for an example. */
7622 if (NILP (bar->dragging))
7623 {
7624 float old_top, old_shown;
7625 XtVaGetValues (widget, XtNtopOfThumb, &old_top, XtNshown, &old_shown,
7626 NULL);
7627 if (top != old_top || shown != old_shown)
7628 XawScrollbarSetThumb (widget, top, shown);
7629 }
7630 else
7631 {
7632 ScrollbarWidget sb = (ScrollbarWidget) widget;
7633 int scroll_mode = sb->scrollbar.scroll_mode;
7634
7635 sb->scrollbar.scroll_mode = 0;
7636
7637 if (last_scroll_bar_part == scroll_bar_down_arrow)
7638 XawScrollbarSetThumb (widget, top, 1 - top);
7639 else
7640 {
7641 float old_top;
7642 XtVaGetValues (widget, XtNtopOfThumb, &old_top, NULL);
7643 XawScrollbarSetThumb (widget, old_top, min (shown, 1 - old_top));
7644 }
7645
7646 sb->scrollbar.scroll_mode = scroll_mode;
7647 }
7648 }
7649 #endif /* HAVE_XAW3D */
7650
7651 UNBLOCK_INPUT;
7652 }
7653
7654 #endif /* USE_TOOLKIT_SCROLL_BARS */
7655
7656
7657 \f
7658 /************************************************************************
7659 Scroll bars, general
7660 ************************************************************************/
7661
7662 /* Create a scroll bar and return the scroll bar vector for it. W is
7663 the Emacs window on which to create the scroll bar. TOP, LEFT,
7664 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7665 scroll bar. */
7666
7667 static struct scroll_bar *
7668 x_scroll_bar_create (w, top, left, width, height)
7669 struct window *w;
7670 int top, left, width, height;
7671 {
7672 struct frame *f = XFRAME (w->frame);
7673 struct scroll_bar *bar
7674 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
7675
7676 BLOCK_INPUT;
7677
7678 #if USE_TOOLKIT_SCROLL_BARS
7679 x_create_toolkit_scroll_bar (f, bar);
7680 #else /* not USE_TOOLKIT_SCROLL_BARS */
7681 {
7682 XSetWindowAttributes a;
7683 unsigned long mask;
7684 Window window;
7685
7686 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7687 if (a.background_pixel == -1)
7688 a.background_pixel = f->output_data.x->background_pixel;
7689
7690 a.event_mask = (ButtonPressMask | ButtonReleaseMask
7691 | ButtonMotionMask | PointerMotionHintMask
7692 | ExposureMask);
7693 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
7694
7695 mask = (CWBackPixel | CWEventMask | CWCursor);
7696
7697 /* Clear the area of W that will serve as a scroll bar. This is
7698 for the case that a window has been split horizontally. In
7699 this case, no clear_frame is generated to reduce flickering. */
7700 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7701 left, top, width,
7702 window_box_height (w), False);
7703
7704 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7705 /* Position and size of scroll bar. */
7706 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7707 top,
7708 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7709 height,
7710 /* Border width, depth, class, and visual. */
7711 0,
7712 CopyFromParent,
7713 CopyFromParent,
7714 CopyFromParent,
7715 /* Attributes. */
7716 mask, &a);
7717 SET_SCROLL_BAR_X_WINDOW (bar, window);
7718 }
7719 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7720
7721 XSETWINDOW (bar->window, w);
7722 XSETINT (bar->top, top);
7723 XSETINT (bar->left, left);
7724 XSETINT (bar->width, width);
7725 XSETINT (bar->height, height);
7726 XSETINT (bar->start, 0);
7727 XSETINT (bar->end, 0);
7728 bar->dragging = Qnil;
7729
7730 /* Add bar to its frame's list of scroll bars. */
7731 bar->next = FRAME_SCROLL_BARS (f);
7732 bar->prev = Qnil;
7733 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7734 if (!NILP (bar->next))
7735 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7736
7737 /* Map the window/widget. */
7738 #if USE_TOOLKIT_SCROLL_BARS
7739 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
7740 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7741 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7742 top,
7743 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7744 height, 0);
7745 #else /* not USE_TOOLKIT_SCROLL_BARS */
7746 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
7747 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7748
7749 UNBLOCK_INPUT;
7750 return bar;
7751 }
7752
7753
7754 /* Draw BAR's handle in the proper position.
7755
7756 If the handle is already drawn from START to END, don't bother
7757 redrawing it, unless REBUILD is non-zero; in that case, always
7758 redraw it. (REBUILD is handy for drawing the handle after expose
7759 events.)
7760
7761 Normally, we want to constrain the start and end of the handle to
7762 fit inside its rectangle, but if the user is dragging the scroll
7763 bar handle, we want to let them drag it down all the way, so that
7764 the bar's top is as far down as it goes; otherwise, there's no way
7765 to move to the very end of the buffer. */
7766
7767 #ifndef USE_TOOLKIT_SCROLL_BARS
7768
7769 static void
7770 x_scroll_bar_set_handle (bar, start, end, rebuild)
7771 struct scroll_bar *bar;
7772 int start, end;
7773 int rebuild;
7774 {
7775 int dragging = ! NILP (bar->dragging);
7776 Window w = SCROLL_BAR_X_WINDOW (bar);
7777 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7778 GC gc = f->output_data.x->normal_gc;
7779
7780 /* If the display is already accurate, do nothing. */
7781 if (! rebuild
7782 && start == XINT (bar->start)
7783 && end == XINT (bar->end))
7784 return;
7785
7786 BLOCK_INPUT;
7787
7788 {
7789 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
7790 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
7791 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7792
7793 /* Make sure the values are reasonable, and try to preserve
7794 the distance between start and end. */
7795 {
7796 int length = end - start;
7797
7798 if (start < 0)
7799 start = 0;
7800 else if (start > top_range)
7801 start = top_range;
7802 end = start + length;
7803
7804 if (end < start)
7805 end = start;
7806 else if (end > top_range && ! dragging)
7807 end = top_range;
7808 }
7809
7810 /* Store the adjusted setting in the scroll bar. */
7811 XSETINT (bar->start, start);
7812 XSETINT (bar->end, end);
7813
7814 /* Clip the end position, just for display. */
7815 if (end > top_range)
7816 end = top_range;
7817
7818 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
7819 below top positions, to make sure the handle is always at least
7820 that many pixels tall. */
7821 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
7822
7823 /* Draw the empty space above the handle. Note that we can't clear
7824 zero-height areas; that means "clear to end of window." */
7825 if (0 < start)
7826 XClearArea (FRAME_X_DISPLAY (f), w,
7827
7828 /* x, y, width, height, and exposures. */
7829 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7830 VERTICAL_SCROLL_BAR_TOP_BORDER,
7831 inside_width, start,
7832 False);
7833
7834 /* Change to proper foreground color if one is specified. */
7835 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7836 XSetForeground (FRAME_X_DISPLAY (f), gc,
7837 f->output_data.x->scroll_bar_foreground_pixel);
7838
7839 /* Draw the handle itself. */
7840 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
7841
7842 /* x, y, width, height */
7843 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7844 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
7845 inside_width, end - start);
7846
7847 /* Restore the foreground color of the GC if we changed it above. */
7848 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7849 XSetForeground (FRAME_X_DISPLAY (f), gc,
7850 f->output_data.x->foreground_pixel);
7851
7852 /* Draw the empty space below the handle. Note that we can't
7853 clear zero-height areas; that means "clear to end of window." */
7854 if (end < inside_height)
7855 XClearArea (FRAME_X_DISPLAY (f), w,
7856
7857 /* x, y, width, height, and exposures. */
7858 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7859 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
7860 inside_width, inside_height - end,
7861 False);
7862
7863 }
7864
7865 UNBLOCK_INPUT;
7866 }
7867
7868 #endif /* !USE_TOOLKIT_SCROLL_BARS */
7869
7870 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7871 nil. */
7872
7873 static void
7874 x_scroll_bar_remove (bar)
7875 struct scroll_bar *bar;
7876 {
7877 BLOCK_INPUT;
7878
7879 #if USE_TOOLKIT_SCROLL_BARS
7880 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
7881 #else /* not USE_TOOLKIT_SCROLL_BARS */
7882 {
7883 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7884 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
7885 }
7886 #endif /* not USE_TOOLKIT_SCROLL_BARS */
7887
7888 /* Disassociate this scroll bar from its window. */
7889 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7890
7891 UNBLOCK_INPUT;
7892 }
7893
7894
7895 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7896 that we are displaying PORTION characters out of a total of WHOLE
7897 characters, starting at POSITION. If WINDOW has no scroll bar,
7898 create one. */
7899
7900 static void
7901 XTset_vertical_scroll_bar (w, portion, whole, position)
7902 struct window *w;
7903 int portion, whole, position;
7904 {
7905 struct frame *f = XFRAME (w->frame);
7906 struct scroll_bar *bar;
7907 int top, height, left, sb_left, width, sb_width;
7908 int window_x, window_y, window_width, window_height;
7909
7910 /* Get window dimensions. */
7911 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7912 top = window_y;
7913 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7914 height = window_height;
7915
7916 /* Compute the left edge of the scroll bar area. */
7917 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7918 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
7919 else
7920 left = XFASTINT (w->left);
7921 left *= CANON_X_UNIT (f);
7922 left += FRAME_INTERNAL_BORDER_WIDTH (f);
7923
7924 /* Compute the width of the scroll bar which might be less than
7925 the width of the area reserved for the scroll bar. */
7926 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
7927 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
7928 else
7929 sb_width = width;
7930
7931 /* Compute the left edge of the scroll bar. */
7932 #ifdef USE_TOOLKIT_SCROLL_BARS
7933 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7934 sb_left = left + width - sb_width - (width - sb_width) / 2;
7935 else
7936 sb_left = left + (width - sb_width) / 2;
7937 #else
7938 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7939 sb_left = left + width - sb_width;
7940 else
7941 sb_left = left;
7942 #endif
7943
7944 /* Does the scroll bar exist yet? */
7945 if (NILP (w->vertical_scroll_bar))
7946 {
7947 BLOCK_INPUT;
7948 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7949 left, top, width, height, False);
7950 UNBLOCK_INPUT;
7951 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
7952 }
7953 else
7954 {
7955 /* It may just need to be moved and resized. */
7956 unsigned int mask = 0;
7957
7958 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7959
7960 BLOCK_INPUT;
7961
7962 if (sb_left != XINT (bar->left))
7963 mask |= CWX;
7964 if (top != XINT (bar->top))
7965 mask |= CWY;
7966 if (sb_width != XINT (bar->width))
7967 mask |= CWWidth;
7968 if (height != XINT (bar->height))
7969 mask |= CWHeight;
7970
7971 #ifdef USE_TOOLKIT_SCROLL_BARS
7972
7973 /* Since toolkit scroll bars are smaller than the space reserved
7974 for them on the frame, we have to clear "under" them. */
7975 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7976 left, top, width, height, False);
7977
7978 /* Move/size the scroll bar widget. */
7979 if (mask)
7980 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7981 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7982 top,
7983 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7984 height, 0);
7985
7986 #else /* not USE_TOOLKIT_SCROLL_BARS */
7987
7988 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
7989 {
7990 /* Clear areas not covered by the scroll bar. This makes sure a
7991 previous mode line display is cleared after C-x 2 C-x 1, for
7992 example. Non-toolkit scroll bars are as wide as the area
7993 reserved for scroll bars - trim at both sides. */
7994 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7995 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7996 height, False);
7997 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7998 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7999 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8000 height, False);
8001 }
8002
8003 /* Move/size the scroll bar window. */
8004 if (mask)
8005 {
8006 XWindowChanges wc;
8007
8008 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8009 wc.y = top;
8010 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8011 wc.height = height;
8012 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8013 mask, &wc);
8014 }
8015
8016 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8017
8018 /* Remember new settings. */
8019 XSETINT (bar->left, sb_left);
8020 XSETINT (bar->top, top);
8021 XSETINT (bar->width, sb_width);
8022 XSETINT (bar->height, height);
8023
8024 UNBLOCK_INPUT;
8025 }
8026
8027 #if USE_TOOLKIT_SCROLL_BARS
8028 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8029 #else /* not USE_TOOLKIT_SCROLL_BARS */
8030 /* Set the scroll bar's current state, unless we're currently being
8031 dragged. */
8032 if (NILP (bar->dragging))
8033 {
8034 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8035
8036 if (whole == 0)
8037 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8038 else
8039 {
8040 int start = ((double) position * top_range) / whole;
8041 int end = ((double) (position + portion) * top_range) / whole;
8042 x_scroll_bar_set_handle (bar, start, end, 0);
8043 }
8044 }
8045 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8046
8047 XSETVECTOR (w->vertical_scroll_bar, bar);
8048 }
8049
8050
8051 /* The following three hooks are used when we're doing a thorough
8052 redisplay of the frame. We don't explicitly know which scroll bars
8053 are going to be deleted, because keeping track of when windows go
8054 away is a real pain - "Can you say set-window-configuration, boys
8055 and girls?" Instead, we just assert at the beginning of redisplay
8056 that *all* scroll bars are to be removed, and then save a scroll bar
8057 from the fiery pit when we actually redisplay its window. */
8058
8059 /* Arrange for all scroll bars on FRAME to be removed at the next call
8060 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8061 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8062
8063 static void
8064 XTcondemn_scroll_bars (frame)
8065 FRAME_PTR frame;
8066 {
8067 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8068 while (! NILP (FRAME_SCROLL_BARS (frame)))
8069 {
8070 Lisp_Object bar;
8071 bar = FRAME_SCROLL_BARS (frame);
8072 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8073 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8074 XSCROLL_BAR (bar)->prev = Qnil;
8075 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8076 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8077 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8078 }
8079 }
8080
8081 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8082 Note that WINDOW isn't necessarily condemned at all. */
8083 static void
8084 XTredeem_scroll_bar (window)
8085 struct window *window;
8086 {
8087 struct scroll_bar *bar;
8088
8089 /* We can't redeem this window's scroll bar if it doesn't have one. */
8090 if (NILP (window->vertical_scroll_bar))
8091 abort ();
8092
8093 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8094
8095 /* Unlink it from the condemned list. */
8096 {
8097 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8098
8099 if (NILP (bar->prev))
8100 {
8101 /* If the prev pointer is nil, it must be the first in one of
8102 the lists. */
8103 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8104 /* It's not condemned. Everything's fine. */
8105 return;
8106 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8107 window->vertical_scroll_bar))
8108 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8109 else
8110 /* If its prev pointer is nil, it must be at the front of
8111 one or the other! */
8112 abort ();
8113 }
8114 else
8115 XSCROLL_BAR (bar->prev)->next = bar->next;
8116
8117 if (! NILP (bar->next))
8118 XSCROLL_BAR (bar->next)->prev = bar->prev;
8119
8120 bar->next = FRAME_SCROLL_BARS (f);
8121 bar->prev = Qnil;
8122 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8123 if (! NILP (bar->next))
8124 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8125 }
8126 }
8127
8128 /* Remove all scroll bars on FRAME that haven't been saved since the
8129 last call to `*condemn_scroll_bars_hook'. */
8130
8131 static void
8132 XTjudge_scroll_bars (f)
8133 FRAME_PTR f;
8134 {
8135 Lisp_Object bar, next;
8136
8137 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8138
8139 /* Clear out the condemned list now so we won't try to process any
8140 more events on the hapless scroll bars. */
8141 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8142
8143 for (; ! NILP (bar); bar = next)
8144 {
8145 struct scroll_bar *b = XSCROLL_BAR (bar);
8146
8147 x_scroll_bar_remove (b);
8148
8149 next = b->next;
8150 b->next = b->prev = Qnil;
8151 }
8152
8153 /* Now there should be no references to the condemned scroll bars,
8154 and they should get garbage-collected. */
8155 }
8156
8157
8158 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8159 is a no-op when using toolkit scroll bars.
8160
8161 This may be called from a signal handler, so we have to ignore GC
8162 mark bits. */
8163
8164 static void
8165 x_scroll_bar_expose (bar, event)
8166 struct scroll_bar *bar;
8167 XEvent *event;
8168 {
8169 #ifndef USE_TOOLKIT_SCROLL_BARS
8170
8171 Window w = SCROLL_BAR_X_WINDOW (bar);
8172 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8173 GC gc = f->output_data.x->normal_gc;
8174 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8175
8176 BLOCK_INPUT;
8177
8178 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8179
8180 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8181 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8182
8183 /* x, y, width, height */
8184 0, 0,
8185 XINT (bar->width) - 1 - width_trim - width_trim,
8186 XINT (bar->height) - 1);
8187
8188 UNBLOCK_INPUT;
8189
8190 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8191 }
8192
8193 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8194 is set to something other than no_event, it is enqueued.
8195
8196 This may be called from a signal handler, so we have to ignore GC
8197 mark bits. */
8198
8199 #ifndef USE_TOOLKIT_SCROLL_BARS
8200
8201 static void
8202 x_scroll_bar_handle_click (bar, event, emacs_event)
8203 struct scroll_bar *bar;
8204 XEvent *event;
8205 struct input_event *emacs_event;
8206 {
8207 if (! GC_WINDOWP (bar->window))
8208 abort ();
8209
8210 emacs_event->kind = scroll_bar_click;
8211 emacs_event->code = event->xbutton.button - Button1;
8212 emacs_event->modifiers
8213 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8214 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8215 event->xbutton.state)
8216 | (event->type == ButtonRelease
8217 ? up_modifier
8218 : down_modifier));
8219 emacs_event->frame_or_window = bar->window;
8220 emacs_event->timestamp = event->xbutton.time;
8221 {
8222 #if 0
8223 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8224 int internal_height
8225 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8226 #endif
8227 int top_range
8228 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8229 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8230
8231 if (y < 0) y = 0;
8232 if (y > top_range) y = top_range;
8233
8234 if (y < XINT (bar->start))
8235 emacs_event->part = scroll_bar_above_handle;
8236 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8237 emacs_event->part = scroll_bar_handle;
8238 else
8239 emacs_event->part = scroll_bar_below_handle;
8240
8241 /* Just because the user has clicked on the handle doesn't mean
8242 they want to drag it. Lisp code needs to be able to decide
8243 whether or not we're dragging. */
8244 #if 0
8245 /* If the user has just clicked on the handle, record where they're
8246 holding it. */
8247 if (event->type == ButtonPress
8248 && emacs_event->part == scroll_bar_handle)
8249 XSETINT (bar->dragging, y - XINT (bar->start));
8250 #endif
8251
8252 /* If the user has released the handle, set it to its final position. */
8253 if (event->type == ButtonRelease
8254 && ! NILP (bar->dragging))
8255 {
8256 int new_start = y - XINT (bar->dragging);
8257 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8258
8259 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8260 bar->dragging = Qnil;
8261 }
8262
8263 /* Same deal here as the other #if 0. */
8264 #if 0
8265 /* Clicks on the handle are always reported as occurring at the top of
8266 the handle. */
8267 if (emacs_event->part == scroll_bar_handle)
8268 emacs_event->x = bar->start;
8269 else
8270 XSETINT (emacs_event->x, y);
8271 #else
8272 XSETINT (emacs_event->x, y);
8273 #endif
8274
8275 XSETINT (emacs_event->y, top_range);
8276 }
8277 }
8278
8279 /* Handle some mouse motion while someone is dragging the scroll bar.
8280
8281 This may be called from a signal handler, so we have to ignore GC
8282 mark bits. */
8283
8284 static void
8285 x_scroll_bar_note_movement (bar, event)
8286 struct scroll_bar *bar;
8287 XEvent *event;
8288 {
8289 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8290
8291 last_mouse_movement_time = event->xmotion.time;
8292
8293 f->mouse_moved = 1;
8294 XSETVECTOR (last_mouse_scroll_bar, bar);
8295
8296 /* If we're dragging the bar, display it. */
8297 if (! GC_NILP (bar->dragging))
8298 {
8299 /* Where should the handle be now? */
8300 int new_start = event->xmotion.y - XINT (bar->dragging);
8301
8302 if (new_start != XINT (bar->start))
8303 {
8304 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8305
8306 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8307 }
8308 }
8309 }
8310
8311 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8312
8313 /* Return information to the user about the current position of the mouse
8314 on the scroll bar. */
8315
8316 static void
8317 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8318 FRAME_PTR *fp;
8319 Lisp_Object *bar_window;
8320 enum scroll_bar_part *part;
8321 Lisp_Object *x, *y;
8322 unsigned long *time;
8323 {
8324 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8325 Window w = SCROLL_BAR_X_WINDOW (bar);
8326 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8327 int win_x, win_y;
8328 Window dummy_window;
8329 int dummy_coord;
8330 unsigned int dummy_mask;
8331
8332 BLOCK_INPUT;
8333
8334 /* Get the mouse's position relative to the scroll bar window, and
8335 report that. */
8336 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8337
8338 /* Root, child, root x and root y. */
8339 &dummy_window, &dummy_window,
8340 &dummy_coord, &dummy_coord,
8341
8342 /* Position relative to scroll bar. */
8343 &win_x, &win_y,
8344
8345 /* Mouse buttons and modifier keys. */
8346 &dummy_mask))
8347 ;
8348 else
8349 {
8350 #if 0
8351 int inside_height
8352 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8353 #endif
8354 int top_range
8355 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8356
8357 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8358
8359 if (! NILP (bar->dragging))
8360 win_y -= XINT (bar->dragging);
8361
8362 if (win_y < 0)
8363 win_y = 0;
8364 if (win_y > top_range)
8365 win_y = top_range;
8366
8367 *fp = f;
8368 *bar_window = bar->window;
8369
8370 if (! NILP (bar->dragging))
8371 *part = scroll_bar_handle;
8372 else if (win_y < XINT (bar->start))
8373 *part = scroll_bar_above_handle;
8374 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8375 *part = scroll_bar_handle;
8376 else
8377 *part = scroll_bar_below_handle;
8378
8379 XSETINT (*x, win_y);
8380 XSETINT (*y, top_range);
8381
8382 f->mouse_moved = 0;
8383 last_mouse_scroll_bar = Qnil;
8384 }
8385
8386 *time = last_mouse_movement_time;
8387
8388 UNBLOCK_INPUT;
8389 }
8390
8391
8392 /* The screen has been cleared so we may have changed foreground or
8393 background colors, and the scroll bars may need to be redrawn.
8394 Clear out the scroll bars, and ask for expose events, so we can
8395 redraw them. */
8396
8397 void
8398 x_scroll_bar_clear (f)
8399 FRAME_PTR f;
8400 {
8401 #ifndef USE_TOOLKIT_SCROLL_BARS
8402 Lisp_Object bar;
8403
8404 /* We can have scroll bars even if this is 0,
8405 if we just turned off scroll bar mode.
8406 But in that case we should not clear them. */
8407 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8408 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8409 bar = XSCROLL_BAR (bar)->next)
8410 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8411 0, 0, 0, 0, True);
8412 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8413 }
8414
8415 /* This processes Expose events from the menu-bar specific X event
8416 loop in xmenu.c. This allows to redisplay the frame if necessary
8417 when handling menu-bar or pop-up items. */
8418
8419 int
8420 process_expose_from_menu (event)
8421 XEvent event;
8422 {
8423 FRAME_PTR f;
8424 struct x_display_info *dpyinfo;
8425 int frame_exposed_p = 0;
8426
8427 BLOCK_INPUT;
8428
8429 dpyinfo = x_display_info_for_display (event.xexpose.display);
8430 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8431 if (f)
8432 {
8433 if (f->async_visible == 0)
8434 {
8435 f->async_visible = 1;
8436 f->async_iconified = 0;
8437 f->output_data.x->has_been_visible = 1;
8438 SET_FRAME_GARBAGED (f);
8439 }
8440 else
8441 {
8442 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8443 event.xexpose.x, event.xexpose.y,
8444 event.xexpose.width, event.xexpose.height);
8445 frame_exposed_p = 1;
8446 }
8447 }
8448 else
8449 {
8450 struct scroll_bar *bar
8451 = x_window_to_scroll_bar (event.xexpose.window);
8452
8453 if (bar)
8454 x_scroll_bar_expose (bar, &event);
8455 }
8456
8457 UNBLOCK_INPUT;
8458 return frame_exposed_p;
8459 }
8460 \f
8461 /* Define a queue to save up SelectionRequest events for later handling. */
8462
8463 struct selection_event_queue
8464 {
8465 XEvent event;
8466 struct selection_event_queue *next;
8467 };
8468
8469 static struct selection_event_queue *queue;
8470
8471 /* Nonzero means queue up certain events--don't process them yet. */
8472
8473 static int x_queue_selection_requests;
8474
8475 /* Queue up an X event *EVENT, to be processed later. */
8476
8477 static void
8478 x_queue_event (f, event)
8479 FRAME_PTR f;
8480 XEvent *event;
8481 {
8482 struct selection_event_queue *queue_tmp
8483 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
8484
8485 if (queue_tmp != NULL)
8486 {
8487 queue_tmp->event = *event;
8488 queue_tmp->next = queue;
8489 queue = queue_tmp;
8490 }
8491 }
8492
8493 /* Take all the queued events and put them back
8494 so that they get processed afresh. */
8495
8496 static void
8497 x_unqueue_events (display)
8498 Display *display;
8499 {
8500 while (queue != NULL)
8501 {
8502 struct selection_event_queue *queue_tmp = queue;
8503 XPutBackEvent (display, &queue_tmp->event);
8504 queue = queue_tmp->next;
8505 xfree ((char *)queue_tmp);
8506 }
8507 }
8508
8509 /* Start queuing SelectionRequest events. */
8510
8511 void
8512 x_start_queuing_selection_requests (display)
8513 Display *display;
8514 {
8515 x_queue_selection_requests++;
8516 }
8517
8518 /* Stop queuing SelectionRequest events. */
8519
8520 void
8521 x_stop_queuing_selection_requests (display)
8522 Display *display;
8523 {
8524 x_queue_selection_requests--;
8525 x_unqueue_events (display);
8526 }
8527 \f
8528 /* The main X event-reading loop - XTread_socket. */
8529
8530 /* Time stamp of enter window event. This is only used by XTread_socket,
8531 but we have to put it out here, since static variables within functions
8532 sometimes don't work. */
8533
8534 static Time enter_timestamp;
8535
8536 /* This holds the state XLookupString needs to implement dead keys
8537 and other tricks known as "compose processing". _X Window System_
8538 says that a portable program can't use this, but Stephen Gildea assures
8539 me that letting the compiler initialize it to zeros will work okay.
8540
8541 This must be defined outside of XTread_socket, for the same reasons
8542 given for enter_time stamp, above. */
8543
8544 static XComposeStatus compose_status;
8545
8546 /* Record the last 100 characters stored
8547 to help debug the loss-of-chars-during-GC problem. */
8548
8549 static int temp_index;
8550 static short temp_buffer[100];
8551
8552 /* Set this to nonzero to fake an "X I/O error"
8553 on a particular display. */
8554
8555 struct x_display_info *XTread_socket_fake_io_error;
8556
8557 /* When we find no input here, we occasionally do a no-op command
8558 to verify that the X server is still running and we can still talk with it.
8559 We try all the open displays, one by one.
8560 This variable is used for cycling thru the displays. */
8561
8562 static struct x_display_info *next_noop_dpyinfo;
8563
8564 #define SET_SAVED_MENU_EVENT(size) \
8565 do \
8566 { \
8567 if (f->output_data.x->saved_menu_event == 0) \
8568 f->output_data.x->saved_menu_event \
8569 = (XEvent *) xmalloc (sizeof (XEvent)); \
8570 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8571 if (numchars >= 1) \
8572 { \
8573 bufp->kind = menu_bar_activate_event; \
8574 XSETFRAME (bufp->frame_or_window, f); \
8575 bufp++; \
8576 count++; \
8577 numchars--; \
8578 } \
8579 } \
8580 while (0)
8581
8582 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8583 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8584
8585 /* Read events coming from the X server.
8586 This routine is called by the SIGIO handler.
8587 We return as soon as there are no more events to be read.
8588
8589 Events representing keys are stored in buffer BUFP,
8590 which can hold up to NUMCHARS characters.
8591 We return the number of characters stored into the buffer,
8592 thus pretending to be `read'.
8593
8594 EXPECTED is nonzero if the caller knows input is available. */
8595
8596 int
8597 XTread_socket (sd, bufp, numchars, expected)
8598 register int sd;
8599 /* register */ struct input_event *bufp;
8600 /* register */ int numchars;
8601 int expected;
8602 {
8603 int count = 0;
8604 int nbytes = 0;
8605 XEvent event;
8606 struct frame *f;
8607 int event_found = 0;
8608 struct x_display_info *dpyinfo;
8609 #ifdef HAVE_X_I18N
8610 Status status_return;
8611 #endif
8612
8613 if (interrupt_input_blocked)
8614 {
8615 interrupt_input_pending = 1;
8616 return -1;
8617 }
8618
8619 interrupt_input_pending = 0;
8620 BLOCK_INPUT;
8621
8622 /* So people can tell when we have read the available input. */
8623 input_signal_count++;
8624
8625 if (numchars <= 0)
8626 abort (); /* Don't think this happens. */
8627
8628 /* Find the display we are supposed to read input for.
8629 It's the one communicating on descriptor SD. */
8630 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8631 {
8632 #if 0 /* This ought to be unnecessary; let's verify it. */
8633 #ifdef FIOSNBIO
8634 /* If available, Xlib uses FIOSNBIO to make the socket
8635 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8636 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8637 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8638 fcntl (dpyinfo->connection, F_SETFL, 0);
8639 #endif /* ! defined (FIOSNBIO) */
8640 #endif
8641
8642 #if 0 /* This code can't be made to work, with multiple displays,
8643 and appears not to be used on any system any more.
8644 Also keyboard.c doesn't turn O_NDELAY on and off
8645 for X connections. */
8646 #ifndef SIGIO
8647 #ifndef HAVE_SELECT
8648 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8649 {
8650 extern int read_alarm_should_throw;
8651 read_alarm_should_throw = 1;
8652 XPeekEvent (dpyinfo->display, &event);
8653 read_alarm_should_throw = 0;
8654 }
8655 #endif /* HAVE_SELECT */
8656 #endif /* SIGIO */
8657 #endif
8658
8659 /* For debugging, this gives a way to fake an I/O error. */
8660 if (dpyinfo == XTread_socket_fake_io_error)
8661 {
8662 XTread_socket_fake_io_error = 0;
8663 x_io_error_quitter (dpyinfo->display);
8664 }
8665
8666 while (XPending (dpyinfo->display))
8667 {
8668 XNextEvent (dpyinfo->display, &event);
8669
8670 if (display_busy_cursor_p)
8671 {
8672 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8673 display until the next X event is read and we come
8674 here again. Setting it to 1 inhibits busy-cursor
8675 display for direct commands. */
8676 if (event.type == MotionNotify
8677 || event.type == EnterNotify
8678 || (dpyinfo->grabbed
8679 && event.type != ButtonRelease))
8680 inhibit_busy_cursor = 2;
8681 else
8682 inhibit_busy_cursor = 1;
8683 }
8684
8685 #ifdef HAVE_X_I18N
8686 {
8687 struct frame *f1 = x_any_window_to_frame (dpyinfo,
8688 event.xclient.window);
8689 /* The necessity of the following line took me
8690 a full work-day to decipher from the docs!! */
8691 if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
8692 break;
8693 }
8694 #endif
8695 event_found = 1;
8696
8697 switch (event.type)
8698 {
8699 case ClientMessage:
8700 {
8701 if (event.xclient.message_type
8702 == dpyinfo->Xatom_wm_protocols
8703 && event.xclient.format == 32)
8704 {
8705 if (event.xclient.data.l[0]
8706 == dpyinfo->Xatom_wm_take_focus)
8707 {
8708 /* Use x_any_window_to_frame because this
8709 could be the shell widget window
8710 if the frame has no title bar. */
8711 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
8712 #ifdef HAVE_X_I18N
8713 /* Not quite sure this is needed -pd */
8714 if (f && FRAME_XIC (f))
8715 XSetICFocus (FRAME_XIC (f));
8716 #endif
8717 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8718 instructs the WM to set the input focus automatically for
8719 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8720 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8721 it has set the focus. So, XSetInputFocus below is not
8722 needed.
8723
8724 The call to XSetInputFocus below has also caused trouble. In
8725 cases where the XSetInputFocus done by the WM and the one
8726 below are temporally close (on a fast machine), the call
8727 below can generate additional FocusIn events which confuse
8728 Emacs. */
8729
8730 /* Since we set WM_TAKE_FOCUS, we must call
8731 XSetInputFocus explicitly. But not if f is null,
8732 since that might be an event for a deleted frame. */
8733 if (f)
8734 {
8735 Display *d = event.xclient.display;
8736 /* Catch and ignore errors, in case window has been
8737 iconified by a window manager such as GWM. */
8738 int count = x_catch_errors (d);
8739 XSetInputFocus (d, event.xclient.window,
8740 /* The ICCCM says this is
8741 the only valid choice. */
8742 RevertToParent,
8743 event.xclient.data.l[1]);
8744 /* This is needed to detect the error
8745 if there is an error. */
8746 XSync (d, False);
8747 x_uncatch_errors (d, count);
8748 }
8749 /* Not certain about handling scroll bars here */
8750 #endif /* 0 */
8751 }
8752 else if (event.xclient.data.l[0]
8753 == dpyinfo->Xatom_wm_save_yourself)
8754 {
8755 /* Save state modify the WM_COMMAND property to
8756 something which can reinstate us. This notifies
8757 the session manager, who's looking for such a
8758 PropertyNotify. Can restart processing when
8759 a keyboard or mouse event arrives. */
8760 if (numchars > 0)
8761 {
8762 f = x_top_window_to_frame (dpyinfo,
8763 event.xclient.window);
8764
8765 /* This is just so we only give real data once
8766 for a single Emacs process. */
8767 if (f == SELECTED_FRAME ())
8768 XSetCommand (FRAME_X_DISPLAY (f),
8769 event.xclient.window,
8770 initial_argv, initial_argc);
8771 else if (f)
8772 XSetCommand (FRAME_X_DISPLAY (f),
8773 event.xclient.window,
8774 0, 0);
8775 }
8776 }
8777 else if (event.xclient.data.l[0]
8778 == dpyinfo->Xatom_wm_delete_window)
8779 {
8780 struct frame *f
8781 = x_any_window_to_frame (dpyinfo,
8782 event.xclient.window);
8783
8784 if (f)
8785 {
8786 if (numchars == 0)
8787 abort ();
8788
8789 bufp->kind = delete_window_event;
8790 XSETFRAME (bufp->frame_or_window, f);
8791 bufp++;
8792
8793 count += 1;
8794 numchars -= 1;
8795 }
8796 }
8797 }
8798 else if (event.xclient.message_type
8799 == dpyinfo->Xatom_wm_configure_denied)
8800 {
8801 }
8802 else if (event.xclient.message_type
8803 == dpyinfo->Xatom_wm_window_moved)
8804 {
8805 int new_x, new_y;
8806 struct frame *f
8807 = x_window_to_frame (dpyinfo, event.xclient.window);
8808
8809 new_x = event.xclient.data.s[0];
8810 new_y = event.xclient.data.s[1];
8811
8812 if (f)
8813 {
8814 f->output_data.x->left_pos = new_x;
8815 f->output_data.x->top_pos = new_y;
8816 }
8817 }
8818 #ifdef HACK_EDITRES
8819 else if (event.xclient.message_type
8820 == dpyinfo->Xatom_editres)
8821 {
8822 struct frame *f
8823 = x_any_window_to_frame (dpyinfo, event.xclient.window);
8824 _XEditResCheckMessages (f->output_data.x->widget, NULL,
8825 &event, NULL);
8826 }
8827 #endif /* HACK_EDITRES */
8828 else if ((event.xclient.message_type
8829 == dpyinfo->Xatom_DONE)
8830 || (event.xclient.message_type
8831 == dpyinfo->Xatom_PAGE))
8832 {
8833 /* Ghostview job completed. Kill it. We could
8834 reply with "Next" if we received "Page", but we
8835 currently never do because we are interested in
8836 images, only, which should have 1 page. */
8837 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
8838 struct frame *f
8839 = x_window_to_frame (dpyinfo, event.xclient.window);
8840 x_kill_gs_process (pixmap, f);
8841 expose_frame (f, 0, 0, 0, 0);
8842 }
8843 #ifdef USE_TOOLKIT_SCROLL_BARS
8844 /* Scroll bar callbacks send a ClientMessage from which
8845 we construct an input_event. */
8846 else if (event.xclient.message_type
8847 == dpyinfo->Xatom_Scrollbar)
8848 {
8849 if (display_busy_cursor_p)
8850 inhibit_busy_cursor = 2;
8851 x_scroll_bar_to_input_event (&event, bufp);
8852 ++bufp, ++count, --numchars;
8853 goto out;
8854 }
8855 #endif /* USE_TOOLKIT_SCROLL_BARS */
8856 else
8857 goto OTHER;
8858 }
8859 break;
8860
8861 case SelectionNotify:
8862 #ifdef USE_X_TOOLKIT
8863 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
8864 goto OTHER;
8865 #endif /* not USE_X_TOOLKIT */
8866 x_handle_selection_notify (&event.xselection);
8867 break;
8868
8869 case SelectionClear: /* Someone has grabbed ownership. */
8870 #ifdef USE_X_TOOLKIT
8871 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
8872 goto OTHER;
8873 #endif /* USE_X_TOOLKIT */
8874 {
8875 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
8876
8877 if (numchars == 0)
8878 abort ();
8879
8880 bufp->kind = selection_clear_event;
8881 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
8882 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
8883 SELECTION_EVENT_TIME (bufp) = eventp->time;
8884 bufp->frame_or_window = Qnil;
8885 bufp++;
8886
8887 count += 1;
8888 numchars -= 1;
8889 }
8890 break;
8891
8892 case SelectionRequest: /* Someone wants our selection. */
8893 #ifdef USE_X_TOOLKIT
8894 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
8895 goto OTHER;
8896 #endif /* USE_X_TOOLKIT */
8897 if (x_queue_selection_requests)
8898 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
8899 &event);
8900 else
8901 {
8902 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
8903
8904 if (numchars == 0)
8905 abort ();
8906
8907 bufp->kind = selection_request_event;
8908 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
8909 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
8910 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
8911 SELECTION_EVENT_TARGET (bufp) = eventp->target;
8912 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
8913 SELECTION_EVENT_TIME (bufp) = eventp->time;
8914 bufp->frame_or_window = Qnil;
8915 bufp++;
8916
8917 count += 1;
8918 numchars -= 1;
8919 }
8920 break;
8921
8922 case PropertyNotify:
8923 #ifdef USE_X_TOOLKIT
8924 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
8925 goto OTHER;
8926 #endif /* not USE_X_TOOLKIT */
8927 x_handle_property_notify (&event.xproperty);
8928 break;
8929
8930 case ReparentNotify:
8931 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
8932 if (f)
8933 {
8934 int x, y;
8935 f->output_data.x->parent_desc = event.xreparent.parent;
8936 x_real_positions (f, &x, &y);
8937 f->output_data.x->left_pos = x;
8938 f->output_data.x->top_pos = y;
8939 }
8940 break;
8941
8942 case Expose:
8943 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8944 if (f)
8945 {
8946 if (f->async_visible == 0)
8947 {
8948 f->async_visible = 1;
8949 f->async_iconified = 0;
8950 f->output_data.x->has_been_visible = 1;
8951 SET_FRAME_GARBAGED (f);
8952 }
8953 else
8954 expose_frame (x_window_to_frame (dpyinfo,
8955 event.xexpose.window),
8956 event.xexpose.x, event.xexpose.y,
8957 event.xexpose.width, event.xexpose.height);
8958 }
8959 else
8960 {
8961 #ifdef USE_TOOLKIT_SCROLL_BARS
8962 /* Dispatch event to the widget. */
8963 goto OTHER;
8964 #else /* not USE_TOOLKIT_SCROLL_BARS */
8965 struct scroll_bar *bar
8966 = x_window_to_scroll_bar (event.xexpose.window);
8967
8968 if (bar)
8969 x_scroll_bar_expose (bar, &event);
8970 #ifdef USE_X_TOOLKIT
8971 else
8972 goto OTHER;
8973 #endif /* USE_X_TOOLKIT */
8974 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8975 }
8976 break;
8977
8978 case GraphicsExpose: /* This occurs when an XCopyArea's
8979 source area was obscured or not
8980 available.*/
8981 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
8982 if (f)
8983 {
8984 expose_frame (f,
8985 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
8986 event.xgraphicsexpose.width,
8987 event.xgraphicsexpose.height);
8988 }
8989 #ifdef USE_X_TOOLKIT
8990 else
8991 goto OTHER;
8992 #endif /* USE_X_TOOLKIT */
8993 break;
8994
8995 case NoExpose: /* This occurs when an XCopyArea's
8996 source area was completely
8997 available */
8998 break;
8999
9000 case UnmapNotify:
9001 /* Redo the mouse-highlight after the tooltip has gone. */
9002 if (event.xmap.window == tip_window)
9003 {
9004 tip_window = 0;
9005 redo_mouse_highlight ();
9006 }
9007
9008 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9009 if (f) /* F may no longer exist if
9010 the frame was deleted. */
9011 {
9012 /* While a frame is unmapped, display generation is
9013 disabled; you don't want to spend time updating a
9014 display that won't ever be seen. */
9015 f->async_visible = 0;
9016 /* We can't distinguish, from the event, whether the window
9017 has become iconified or invisible. So assume, if it
9018 was previously visible, than now it is iconified.
9019 But x_make_frame_invisible clears both
9020 the visible flag and the iconified flag;
9021 and that way, we know the window is not iconified now. */
9022 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9023 {
9024 f->async_iconified = 1;
9025
9026 bufp->kind = iconify_event;
9027 XSETFRAME (bufp->frame_or_window, f);
9028 bufp++;
9029 count++;
9030 numchars--;
9031 }
9032 }
9033 goto OTHER;
9034
9035 case MapNotify:
9036 if (event.xmap.window == tip_window)
9037 /* The tooltip has been drawn already. Avoid
9038 the SET_FRAME_GARBAGED below. */
9039 goto OTHER;
9040
9041 /* We use x_top_window_to_frame because map events can
9042 come for sub-windows and they don't mean that the
9043 frame is visible. */
9044 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9045 if (f)
9046 {
9047 f->async_visible = 1;
9048 f->async_iconified = 0;
9049 f->output_data.x->has_been_visible = 1;
9050
9051 /* wait_reading_process_input will notice this and update
9052 the frame's display structures. */
9053 SET_FRAME_GARBAGED (f);
9054
9055 if (f->iconified)
9056 {
9057 bufp->kind = deiconify_event;
9058 XSETFRAME (bufp->frame_or_window, f);
9059 bufp++;
9060 count++;
9061 numchars--;
9062 }
9063 else if (! NILP (Vframe_list)
9064 && ! NILP (XCDR (Vframe_list)))
9065 /* Force a redisplay sooner or later
9066 to update the frame titles
9067 in case this is the second frame. */
9068 record_asynch_buffer_change ();
9069 }
9070 goto OTHER;
9071
9072 case KeyPress:
9073 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9074
9075 #ifdef USE_MOTIF
9076 /* I couldn't find a way to prevent LessTif scroll bars
9077 from consuming key events. */
9078 if (f == 0)
9079 {
9080 Widget widget = XtWindowToWidget (dpyinfo->display,
9081 event.xkey.window);
9082 if (widget && XmIsScrollBar (widget))
9083 {
9084 widget = XtParent (widget);
9085 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9086 }
9087 }
9088 #endif /* USE_MOTIF */
9089
9090 if (f != 0)
9091 {
9092 KeySym keysym, orig_keysym;
9093 /* al%imercury@uunet.uu.net says that making this 81 instead of
9094 80 fixed a bug whereby meta chars made his Emacs hang. */
9095 unsigned char copy_buffer[81];
9096 int modifiers;
9097
9098 event.xkey.state
9099 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9100 extra_keyboard_modifiers);
9101 modifiers = event.xkey.state;
9102
9103 /* This will have to go some day... */
9104
9105 /* make_lispy_event turns chars into control chars.
9106 Don't do it here because XLookupString is too eager. */
9107 event.xkey.state &= ~ControlMask;
9108 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9109 | dpyinfo->super_mod_mask
9110 | dpyinfo->hyper_mod_mask
9111 | dpyinfo->alt_mod_mask);
9112
9113 /* In case Meta is ComposeCharacter,
9114 clear its status. According to Markus Ehrnsperger
9115 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9116 this enables ComposeCharacter to work whether or
9117 not it is combined with Meta. */
9118 if (modifiers & dpyinfo->meta_mod_mask)
9119 bzero (&compose_status, sizeof (compose_status));
9120
9121 #ifdef HAVE_X_I18N
9122 if (FRAME_XIC (f))
9123 {
9124 /* The necessity of the following line took me
9125 a full work-day to decipher from the docs!! */
9126 if (XFilterEvent (&event, None))
9127 break;
9128 nbytes = XmbLookupString (FRAME_XIC (f),
9129 &event.xkey, copy_buffer,
9130 80, &keysym,
9131 &status_return);
9132 if (status_return == XLookupNone)
9133 break;
9134 else if (status_return == XLookupChars)
9135 keysym = NoSymbol;
9136 else if (status_return != XLookupKeySym
9137 && status_return != XLookupBoth)
9138 abort ();
9139 }
9140 else
9141 nbytes = XLookupString (&event.xkey, copy_buffer,
9142 80, &keysym, &compose_status);
9143 #else
9144 nbytes = XLookupString (&event.xkey, copy_buffer,
9145 80, &keysym, &compose_status);
9146 #endif
9147
9148 orig_keysym = keysym;
9149
9150 if (numchars > 1)
9151 {
9152 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9153 || keysym == XK_Delete
9154 #ifdef XK_ISO_Left_Tab
9155 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9156 #endif
9157 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9158 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9159 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9160 #ifdef HPUX
9161 /* This recognizes the "extended function keys".
9162 It seems there's no cleaner way.
9163 Test IsModifierKey to avoid handling mode_switch
9164 incorrectly. */
9165 || ((unsigned) (keysym) >= XK_Select
9166 && (unsigned)(keysym) < XK_KP_Space)
9167 #endif
9168 #ifdef XK_dead_circumflex
9169 || orig_keysym == XK_dead_circumflex
9170 #endif
9171 #ifdef XK_dead_grave
9172 || orig_keysym == XK_dead_grave
9173 #endif
9174 #ifdef XK_dead_tilde
9175 || orig_keysym == XK_dead_tilde
9176 #endif
9177 #ifdef XK_dead_diaeresis
9178 || orig_keysym == XK_dead_diaeresis
9179 #endif
9180 #ifdef XK_dead_macron
9181 || orig_keysym == XK_dead_macron
9182 #endif
9183 #ifdef XK_dead_degree
9184 || orig_keysym == XK_dead_degree
9185 #endif
9186 #ifdef XK_dead_acute
9187 || orig_keysym == XK_dead_acute
9188 #endif
9189 #ifdef XK_dead_cedilla
9190 || orig_keysym == XK_dead_cedilla
9191 #endif
9192 #ifdef XK_dead_breve
9193 || orig_keysym == XK_dead_breve
9194 #endif
9195 #ifdef XK_dead_ogonek
9196 || orig_keysym == XK_dead_ogonek
9197 #endif
9198 #ifdef XK_dead_caron
9199 || orig_keysym == XK_dead_caron
9200 #endif
9201 #ifdef XK_dead_doubleacute
9202 || orig_keysym == XK_dead_doubleacute
9203 #endif
9204 #ifdef XK_dead_abovedot
9205 || orig_keysym == XK_dead_abovedot
9206 #endif
9207 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9208 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9209 /* Any "vendor-specific" key is ok. */
9210 || (orig_keysym & (1 << 28)))
9211 && ! (IsModifierKey (orig_keysym)
9212 #ifndef HAVE_X11R5
9213 #ifdef XK_Mode_switch
9214 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9215 #endif
9216 #ifdef XK_Num_Lock
9217 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9218 #endif
9219 #endif /* not HAVE_X11R5 */
9220 ))
9221 {
9222 if (temp_index == sizeof temp_buffer / sizeof (short))
9223 temp_index = 0;
9224 temp_buffer[temp_index++] = keysym;
9225 bufp->kind = non_ascii_keystroke;
9226 bufp->code = keysym;
9227 XSETFRAME (bufp->frame_or_window, f);
9228 bufp->modifiers
9229 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9230 modifiers);
9231 bufp->timestamp = event.xkey.time;
9232 bufp++;
9233 count++;
9234 numchars--;
9235
9236 if (display_busy_cursor_p)
9237 if (keysym != XK_Return || minibuf_level == 0)
9238 inhibit_busy_cursor = 2;
9239 }
9240 else if (numchars > nbytes)
9241 {
9242 register int i;
9243
9244 for (i = 0; i < nbytes; i++)
9245 {
9246 if (temp_index == sizeof temp_buffer / sizeof (short))
9247 temp_index = 0;
9248 temp_buffer[temp_index++] = copy_buffer[i];
9249 bufp->kind = ascii_keystroke;
9250 bufp->code = copy_buffer[i];
9251 XSETFRAME (bufp->frame_or_window, f);
9252 bufp->modifiers
9253 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9254 modifiers);
9255 bufp->timestamp = event.xkey.time;
9256 bufp++;
9257 }
9258
9259 count += nbytes;
9260 numchars -= nbytes;
9261
9262 if (keysym == NoSymbol)
9263 break;
9264 }
9265 else
9266 abort ();
9267 }
9268 else
9269 abort ();
9270 }
9271 goto OTHER;
9272
9273 /* Here's a possible interpretation of the whole
9274 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9275 you get a FocusIn event, you have to get a FocusOut
9276 event before you relinquish the focus. If you
9277 haven't received a FocusIn event, then a mere
9278 LeaveNotify is enough to free you. */
9279
9280 case EnterNotify:
9281 {
9282 int from_menu_bar_p = 0;
9283
9284 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9285
9286 #ifdef LESSTIF_VERSION
9287 /* When clicking outside of a menu bar popup to close
9288 it, we get a FocusIn/ EnterNotify sequence of
9289 events. The flag event.xcrossing.focus is not set
9290 in the EnterNotify event of that sequence because
9291 the focus is in the menu bar,
9292 event.xcrossing.window is the frame's X window.
9293 Unconditionally setting the focus frame to null in
9294 this case is not the right thing, because no event
9295 follows that could set the focus frame to the right
9296 value.
9297
9298 This could be a LessTif bug, but I wasn't able to
9299 reproduce the behavior in a simple test program.
9300
9301 (gerd, LessTif 0.88.1). */
9302
9303 if (!event.xcrossing.focus
9304 && f
9305 && f->output_data.x->menubar_widget)
9306 {
9307 Window focus;
9308 int revert;
9309
9310 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9311 if (focus == XtWindow (f->output_data.x->menubar_widget))
9312 from_menu_bar_p = 1;
9313 }
9314 #endif /* LESSTIF_VERSION */
9315
9316 if (event.xcrossing.focus || from_menu_bar_p)
9317 {
9318 /* Avoid nasty pop/raise loops. */
9319 if (f && (!(f->auto_raise)
9320 || !(f->auto_lower)
9321 || (event.xcrossing.time - enter_timestamp) > 500))
9322 {
9323 x_new_focus_frame (dpyinfo, f);
9324 enter_timestamp = event.xcrossing.time;
9325 }
9326 }
9327 else if (f == dpyinfo->x_focus_frame)
9328 x_new_focus_frame (dpyinfo, 0);
9329
9330 /* EnterNotify counts as mouse movement,
9331 so update things that depend on mouse position. */
9332 if (f && !f->output_data.x->busy_p)
9333 note_mouse_movement (f, &event.xmotion);
9334 goto OTHER;
9335 }
9336
9337 case FocusIn:
9338 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9339 if (event.xfocus.detail != NotifyPointer)
9340 dpyinfo->x_focus_event_frame = f;
9341 if (f)
9342 x_new_focus_frame (dpyinfo, f);
9343
9344 #ifdef HAVE_X_I18N
9345 if (f && FRAME_XIC (f))
9346 XSetICFocus (FRAME_XIC (f));
9347 #endif
9348
9349 goto OTHER;
9350
9351 case LeaveNotify:
9352 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
9353 if (f)
9354 {
9355 Lisp_Object frame;
9356 int from_menu_bar_p = 0;
9357
9358 if (f == dpyinfo->mouse_face_mouse_frame)
9359 {
9360 /* If we move outside the frame, then we're
9361 certainly no longer on any text in the frame. */
9362 clear_mouse_face (dpyinfo);
9363 dpyinfo->mouse_face_mouse_frame = 0;
9364 }
9365
9366 /* Generate a nil HELP_EVENT to cancel a help-echo.
9367 Do it only if there's something to cancel.
9368 Otherwise, the startup message is cleared when
9369 the mouse leaves the frame. */
9370 if (any_help_event_p)
9371 {
9372 XSETFRAME (frame, f);
9373 bufp->kind = HELP_EVENT;
9374 bufp->frame_or_window = Fcons (frame, Qnil);
9375 ++bufp, ++count, --numchars;
9376 }
9377
9378 #ifdef LESSTIF_VERSION
9379 /* Please see the comment at the start of the
9380 EnterNotify case. */
9381 if (!event.xcrossing.focus
9382 && f->output_data.x->menubar_widget)
9383 {
9384 Window focus;
9385 int revert;
9386 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9387 if (focus == XtWindow (f->output_data.x->menubar_widget))
9388 from_menu_bar_p = 1;
9389 }
9390 #endif /* LESSTIF_VERSION */
9391
9392 if (event.xcrossing.focus || from_menu_bar_p)
9393 x_mouse_leave (dpyinfo);
9394 else
9395 {
9396 if (f == dpyinfo->x_focus_event_frame)
9397 dpyinfo->x_focus_event_frame = 0;
9398 if (f == dpyinfo->x_focus_frame)
9399 x_new_focus_frame (dpyinfo, 0);
9400 }
9401 }
9402 goto OTHER;
9403
9404 case FocusOut:
9405 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9406 if (event.xfocus.detail != NotifyPointer
9407 && f == dpyinfo->x_focus_event_frame)
9408 dpyinfo->x_focus_event_frame = 0;
9409 if (f && f == dpyinfo->x_focus_frame)
9410 x_new_focus_frame (dpyinfo, 0);
9411
9412 #ifdef HAVE_X_I18N
9413 if (f && FRAME_XIC (f))
9414 XUnsetICFocus (FRAME_XIC (f));
9415 #endif
9416
9417 goto OTHER;
9418
9419 case MotionNotify:
9420 {
9421 previous_help_echo = help_echo;
9422 help_echo = Qnil;
9423
9424 if (dpyinfo->grabbed && last_mouse_frame
9425 && FRAME_LIVE_P (last_mouse_frame))
9426 f = last_mouse_frame;
9427 else
9428 f = x_window_to_frame (dpyinfo, event.xmotion.window);
9429
9430 if (f)
9431 note_mouse_movement (f, &event.xmotion);
9432 else
9433 {
9434 #ifndef USE_TOOLKIT_SCROLL_BARS
9435 struct scroll_bar *bar
9436 = x_window_to_scroll_bar (event.xmotion.window);
9437
9438 if (bar)
9439 x_scroll_bar_note_movement (bar, &event);
9440 #endif /* USE_TOOLKIT_SCROLL_BARS */
9441
9442 /* If we move outside the frame, then we're
9443 certainly no longer on any text in the frame. */
9444 clear_mouse_face (dpyinfo);
9445 }
9446
9447 /* If the contents of the global variable help_echo
9448 has changed, generate a HELP_EVENT. */
9449 if (STRINGP (help_echo)
9450 || STRINGP (previous_help_echo))
9451 {
9452 Lisp_Object frame;
9453
9454 if (f)
9455 XSETFRAME (frame, f);
9456 else
9457 frame = Qnil;
9458
9459 any_help_event_p = 1;
9460 bufp->kind = HELP_EVENT;
9461 bufp->frame_or_window = Fcons (frame, help_echo);
9462 ++bufp, ++count, --numchars;
9463 }
9464
9465 goto OTHER;
9466 }
9467
9468 case ConfigureNotify:
9469 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9470 if (f)
9471 {
9472 #ifndef USE_X_TOOLKIT
9473 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9474 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
9475
9476 /* In the toolkit version, change_frame_size
9477 is called by the code that handles resizing
9478 of the EmacsFrame widget. */
9479
9480 /* Even if the number of character rows and columns has
9481 not changed, the font size may have changed, so we need
9482 to check the pixel dimensions as well. */
9483 if (columns != f->width
9484 || rows != f->height
9485 || event.xconfigure.width != f->output_data.x->pixel_width
9486 || event.xconfigure.height != f->output_data.x->pixel_height)
9487 {
9488 change_frame_size (f, rows, columns, 0, 1, 0);
9489 SET_FRAME_GARBAGED (f);
9490 cancel_mouse_face (f);
9491 }
9492 #endif
9493
9494 f->output_data.x->pixel_width = event.xconfigure.width;
9495 f->output_data.x->pixel_height = event.xconfigure.height;
9496
9497 /* What we have now is the position of Emacs's own window.
9498 Convert that to the position of the window manager window. */
9499 x_real_positions (f, &f->output_data.x->left_pos,
9500 &f->output_data.x->top_pos);
9501
9502 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9503 {
9504 /* Since the WM decorations come below top_pos now,
9505 we must put them below top_pos in the future. */
9506 f->output_data.x->win_gravity = NorthWestGravity;
9507 x_wm_set_size_hint (f, (long) 0, 0);
9508 }
9509 #ifdef USE_MOTIF
9510 /* Some window managers pass (0,0) as the location of
9511 the window, and the Motif event handler stores it
9512 in the emacs widget, which messes up Motif menus. */
9513 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9514 {
9515 event.xconfigure.x = f->output_data.x->widget->core.x;
9516 event.xconfigure.y = f->output_data.x->widget->core.y;
9517 }
9518 #endif /* USE_MOTIF */
9519 }
9520 goto OTHER;
9521
9522 case ButtonPress:
9523 case ButtonRelease:
9524 {
9525 /* If we decide we want to generate an event to be seen
9526 by the rest of Emacs, we put it here. */
9527 struct input_event emacs_event;
9528 int tool_bar_p = 0;
9529
9530 emacs_event.kind = no_event;
9531 bzero (&compose_status, sizeof (compose_status));
9532
9533 if (dpyinfo->grabbed
9534 && last_mouse_frame
9535 && FRAME_LIVE_P (last_mouse_frame))
9536 f = last_mouse_frame;
9537 else
9538 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9539
9540 if (f)
9541 {
9542 /* Is this in the tool-bar? */
9543 if (WINDOWP (f->tool_bar_window)
9544 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
9545 {
9546 Lisp_Object window;
9547 int p, x, y;
9548
9549 x = event.xbutton.x;
9550 y = event.xbutton.y;
9551
9552 /* Set x and y. */
9553 window = window_from_coordinates (f, x, y, &p, 1);
9554 if (EQ (window, f->tool_bar_window))
9555 {
9556 x_handle_tool_bar_click (f, &event.xbutton);
9557 tool_bar_p = 1;
9558 }
9559 }
9560
9561 if (!tool_bar_p)
9562 if (!dpyinfo->x_focus_frame
9563 || f == dpyinfo->x_focus_frame)
9564 construct_mouse_click (&emacs_event, &event, f);
9565 }
9566 else
9567 {
9568 #ifndef USE_TOOLKIT_SCROLL_BARS
9569 struct scroll_bar *bar
9570 = x_window_to_scroll_bar (event.xbutton.window);
9571
9572 if (bar)
9573 x_scroll_bar_handle_click (bar, &event, &emacs_event);
9574 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9575 }
9576
9577 if (event.type == ButtonPress)
9578 {
9579 dpyinfo->grabbed |= (1 << event.xbutton.button);
9580 last_mouse_frame = f;
9581 /* Ignore any mouse motion that happened
9582 before this event; any subsequent mouse-movement
9583 Emacs events should reflect only motion after
9584 the ButtonPress. */
9585 if (f != 0)
9586 f->mouse_moved = 0;
9587
9588 if (!tool_bar_p)
9589 last_tool_bar_item = -1;
9590 if (display_busy_cursor_p)
9591 inhibit_busy_cursor = 2;
9592 }
9593 else
9594 {
9595 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
9596 }
9597
9598 if (numchars >= 1 && emacs_event.kind != no_event)
9599 {
9600 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9601 bufp++;
9602 count++;
9603 numchars--;
9604 }
9605
9606 #ifdef USE_X_TOOLKIT
9607 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9608 /* For a down-event in the menu bar,
9609 don't pass it to Xt right now.
9610 Instead, save it away
9611 and we will pass it to Xt from kbd_buffer_get_event.
9612 That way, we can run some Lisp code first. */
9613 if (f && event.type == ButtonPress
9614 /* Verify the event is really within the menu bar
9615 and not just sent to it due to grabbing. */
9616 && event.xbutton.x >= 0
9617 && event.xbutton.x < f->output_data.x->pixel_width
9618 && event.xbutton.y >= 0
9619 && event.xbutton.y < f->output_data.x->menubar_height
9620 && event.xbutton.same_screen)
9621 {
9622 SET_SAVED_BUTTON_EVENT;
9623 XSETFRAME (last_mouse_press_frame, f);
9624 }
9625 else if (event.type == ButtonPress)
9626 {
9627 last_mouse_press_frame = Qnil;
9628 goto OTHER;
9629 }
9630
9631 #ifdef USE_MOTIF /* This should do not harm for Lucid,
9632 but I am trying to be cautious. */
9633 else if (event.type == ButtonRelease)
9634 {
9635 if (!NILP (last_mouse_press_frame))
9636 {
9637 f = XFRAME (last_mouse_press_frame);
9638 if (f->output_data.x)
9639 SET_SAVED_BUTTON_EVENT;
9640 }
9641 else
9642 goto OTHER;
9643 }
9644 #endif /* USE_MOTIF */
9645 else
9646 goto OTHER;
9647 #endif /* USE_X_TOOLKIT */
9648 }
9649 break;
9650
9651 case CirculateNotify:
9652 goto OTHER;
9653
9654 case CirculateRequest:
9655 goto OTHER;
9656
9657 case VisibilityNotify:
9658 goto OTHER;
9659
9660 case MappingNotify:
9661 /* Someone has changed the keyboard mapping - update the
9662 local cache. */
9663 switch (event.xmapping.request)
9664 {
9665 case MappingModifier:
9666 x_find_modifier_meanings (dpyinfo);
9667 /* This is meant to fall through. */
9668 case MappingKeyboard:
9669 XRefreshKeyboardMapping (&event.xmapping);
9670 }
9671 goto OTHER;
9672
9673 default:
9674 OTHER:
9675 #ifdef USE_X_TOOLKIT
9676 BLOCK_INPUT;
9677 XtDispatchEvent (&event);
9678 UNBLOCK_INPUT;
9679 #endif /* USE_X_TOOLKIT */
9680 break;
9681 }
9682 }
9683 }
9684
9685 out:;
9686
9687 /* On some systems, an X bug causes Emacs to get no more events
9688 when the window is destroyed. Detect that. (1994.) */
9689 if (! event_found)
9690 {
9691 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9692 One XNOOP in 100 loops will make Emacs terminate.
9693 B. Bretthauer, 1994 */
9694 x_noop_count++;
9695 if (x_noop_count >= 100)
9696 {
9697 x_noop_count=0;
9698
9699 if (next_noop_dpyinfo == 0)
9700 next_noop_dpyinfo = x_display_list;
9701
9702 XNoOp (next_noop_dpyinfo->display);
9703
9704 /* Each time we get here, cycle through the displays now open. */
9705 next_noop_dpyinfo = next_noop_dpyinfo->next;
9706 }
9707 }
9708
9709 /* If the focus was just given to an auto-raising frame,
9710 raise it now. */
9711 /* ??? This ought to be able to handle more than one such frame. */
9712 if (pending_autoraise_frame)
9713 {
9714 x_raise_frame (pending_autoraise_frame);
9715 pending_autoraise_frame = 0;
9716 }
9717
9718 UNBLOCK_INPUT;
9719 return count;
9720 }
9721
9722
9723
9724 \f
9725 /***********************************************************************
9726 Text Cursor
9727 ***********************************************************************/
9728
9729 /* Note if the text cursor of window W has been overwritten by a
9730 drawing operation that outputs N glyphs starting at HPOS in the
9731 line given by output_cursor.vpos. N < 0 means all the rest of the
9732 line after HPOS has been written. */
9733
9734 static void
9735 note_overwritten_text_cursor (w, hpos, n)
9736 struct window *w;
9737 int hpos, n;
9738 {
9739 if (updated_area == TEXT_AREA
9740 && output_cursor.vpos == w->phys_cursor.vpos
9741 && hpos <= w->phys_cursor.hpos
9742 && (n < 0
9743 || hpos + n > w->phys_cursor.hpos))
9744 w->phys_cursor_on_p = 0;
9745 }
9746
9747
9748 /* Set clipping for output in glyph row ROW. W is the window in which
9749 we operate. GC is the graphics context to set clipping in.
9750 WHOLE_LINE_P non-zero means include the areas used for truncation
9751 mark display and alike in the clipping rectangle.
9752
9753 ROW may be a text row or, e.g., a mode line. Text rows must be
9754 clipped to the interior of the window dedicated to text display,
9755 mode lines must be clipped to the whole window. */
9756
9757 static void
9758 x_clip_to_row (w, row, gc, whole_line_p)
9759 struct window *w;
9760 struct glyph_row *row;
9761 GC gc;
9762 int whole_line_p;
9763 {
9764 struct frame *f = XFRAME (WINDOW_FRAME (w));
9765 XRectangle clip_rect;
9766 int window_x, window_y, window_width, window_height;
9767
9768 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9769
9770 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9771 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9772 clip_rect.y = max (clip_rect.y, window_y);
9773 clip_rect.width = window_width;
9774 clip_rect.height = row->visible_height;
9775
9776 /* If clipping to the whole line, including trunc marks, extend
9777 the rectangle to the left and increase its width. */
9778 if (whole_line_p)
9779 {
9780 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
9781 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
9782 }
9783
9784 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
9785 }
9786
9787
9788 /* Draw a hollow box cursor on window W in glyph row ROW. */
9789
9790 static void
9791 x_draw_hollow_cursor (w, row)
9792 struct window *w;
9793 struct glyph_row *row;
9794 {
9795 struct frame *f = XFRAME (WINDOW_FRAME (w));
9796 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9797 Display *dpy = FRAME_X_DISPLAY (f);
9798 int x, y, wd, h;
9799 XGCValues xgcv;
9800 struct glyph *cursor_glyph;
9801 GC gc;
9802
9803 /* Compute frame-relative coordinates from window-relative
9804 coordinates. */
9805 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9806 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9807 + row->ascent - w->phys_cursor_ascent);
9808 h = row->height - 1;
9809
9810 /* Get the glyph the cursor is on. If we can't tell because
9811 the current matrix is invalid or such, give up. */
9812 cursor_glyph = get_phys_cursor_glyph (w);
9813 if (cursor_glyph == NULL)
9814 return;
9815
9816 /* Compute the width of the rectangle to draw. If on a stretch
9817 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9818 rectangle as wide as the glyph, but use a canonical character
9819 width instead. */
9820 wd = cursor_glyph->pixel_width - 1;
9821 if (cursor_glyph->type == STRETCH_GLYPH
9822 && !x_stretch_cursor_p)
9823 wd = min (CANON_X_UNIT (f), wd);
9824
9825 /* The foreground of cursor_gc is typically the same as the normal
9826 background color, which can cause the cursor box to be invisible. */
9827 xgcv.foreground = f->output_data.x->cursor_pixel;
9828 if (dpyinfo->scratch_cursor_gc)
9829 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9830 else
9831 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
9832 GCForeground, &xgcv);
9833 gc = dpyinfo->scratch_cursor_gc;
9834
9835 /* Set clipping, draw the rectangle, and reset clipping again. */
9836 x_clip_to_row (w, row, gc, 0);
9837 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
9838 XSetClipMask (dpy, gc, None);
9839 }
9840
9841
9842 /* Draw a bar cursor on window W in glyph row ROW.
9843
9844 Implementation note: One would like to draw a bar cursor with an
9845 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9846 Unfortunately, I didn't find a font yet that has this property set.
9847 --gerd. */
9848
9849 static void
9850 x_draw_bar_cursor (w, row)
9851 struct window *w;
9852 struct glyph_row *row;
9853 {
9854 /* If cursor hpos is out of bounds, don't draw garbage. This can
9855 happen in mini-buffer windows when switching between echo area
9856 glyphs and mini-buffer. */
9857 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9858 {
9859 struct frame *f = XFRAME (w->frame);
9860 struct glyph *cursor_glyph;
9861 GC gc;
9862 int x;
9863 unsigned long mask;
9864 XGCValues xgcv;
9865 Display *dpy;
9866 Window window;
9867
9868 cursor_glyph = get_phys_cursor_glyph (w);
9869 if (cursor_glyph == NULL)
9870 return;
9871
9872 xgcv.background = f->output_data.x->cursor_pixel;
9873 xgcv.foreground = f->output_data.x->cursor_pixel;
9874 xgcv.graphics_exposures = 0;
9875 mask = GCForeground | GCBackground | GCGraphicsExposures;
9876 dpy = FRAME_X_DISPLAY (f);
9877 window = FRAME_X_WINDOW (f);
9878 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9879
9880 if (gc)
9881 XChangeGC (dpy, gc, mask, &xgcv);
9882 else
9883 {
9884 gc = XCreateGC (dpy, window, mask, &xgcv);
9885 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9886 }
9887
9888 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9889 x_clip_to_row (w, row, gc, 0);
9890 XFillRectangle (dpy, window, gc,
9891 x,
9892 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9893 min (cursor_glyph->pixel_width,
9894 f->output_data.x->cursor_width),
9895 row->height);
9896 XSetClipMask (dpy, gc, None);
9897 }
9898 }
9899
9900
9901 /* Clear the cursor of window W to background color, and mark the
9902 cursor as not shown. This is used when the text where the cursor
9903 is is about to be rewritten. */
9904
9905 static void
9906 x_clear_cursor (w)
9907 struct window *w;
9908 {
9909 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9910 x_update_window_cursor (w, 0);
9911 }
9912
9913
9914 /* Draw the cursor glyph of window W in glyph row ROW. See the
9915 comment of x_draw_glyphs for the meaning of HL. */
9916
9917 static void
9918 x_draw_phys_cursor_glyph (w, row, hl)
9919 struct window *w;
9920 struct glyph_row *row;
9921 enum draw_glyphs_face hl;
9922 {
9923 /* If cursor hpos is out of bounds, don't draw garbage. This can
9924 happen in mini-buffer windows when switching between echo area
9925 glyphs and mini-buffer. */
9926 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9927 {
9928 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9929 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9930 hl, 0, 0, 0);
9931
9932 /* When we erase the cursor, and ROW is overlapped by other
9933 rows, make sure that these overlapping parts of other rows
9934 are redrawn. */
9935 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9936 {
9937 if (row > w->current_matrix->rows
9938 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9939 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9940
9941 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9942 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9943 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9944 }
9945 }
9946 }
9947
9948
9949 /* Erase the image of a cursor of window W from the screen. */
9950
9951 static void
9952 x_erase_phys_cursor (w)
9953 struct window *w;
9954 {
9955 struct frame *f = XFRAME (w->frame);
9956 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9957 int hpos = w->phys_cursor.hpos;
9958 int vpos = w->phys_cursor.vpos;
9959 int mouse_face_here_p = 0;
9960 struct glyph_matrix *active_glyphs = w->current_matrix;
9961 struct glyph_row *cursor_row;
9962 struct glyph *cursor_glyph;
9963 enum draw_glyphs_face hl;
9964
9965 /* No cursor displayed or row invalidated => nothing to do on the
9966 screen. */
9967 if (w->phys_cursor_type == NO_CURSOR)
9968 goto mark_cursor_off;
9969
9970 /* VPOS >= active_glyphs->nrows means that window has been resized.
9971 Don't bother to erase the cursor. */
9972 if (vpos >= active_glyphs->nrows)
9973 goto mark_cursor_off;
9974
9975 /* If row containing cursor is marked invalid, there is nothing we
9976 can do. */
9977 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9978 if (!cursor_row->enabled_p)
9979 goto mark_cursor_off;
9980
9981 /* This can happen when the new row is shorter than the old one.
9982 In this case, either x_draw_glyphs or clear_end_of_line
9983 should have cleared the cursor. Note that we wouldn't be
9984 able to erase the cursor in this case because we don't have a
9985 cursor glyph at hand. */
9986 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9987 goto mark_cursor_off;
9988
9989 /* If the cursor is in the mouse face area, redisplay that when
9990 we clear the cursor. */
9991 if (w == XWINDOW (dpyinfo->mouse_face_window)
9992 && (vpos > dpyinfo->mouse_face_beg_row
9993 || (vpos == dpyinfo->mouse_face_beg_row
9994 && hpos >= dpyinfo->mouse_face_beg_col))
9995 && (vpos < dpyinfo->mouse_face_end_row
9996 || (vpos == dpyinfo->mouse_face_end_row
9997 && hpos < dpyinfo->mouse_face_end_col))
9998 /* Don't redraw the cursor's spot in mouse face if it is at the
9999 end of a line (on a newline). The cursor appears there, but
10000 mouse highlighting does not. */
10001 && cursor_row->used[TEXT_AREA] > hpos)
10002 mouse_face_here_p = 1;
10003
10004 /* Maybe clear the display under the cursor. */
10005 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10006 {
10007 int x;
10008 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10009
10010 cursor_glyph = get_phys_cursor_glyph (w);
10011 if (cursor_glyph == NULL)
10012 goto mark_cursor_off;
10013
10014 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10015
10016 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10017 x,
10018 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10019 cursor_row->y)),
10020 cursor_glyph->pixel_width,
10021 cursor_row->visible_height,
10022 False);
10023 }
10024
10025 /* Erase the cursor by redrawing the character underneath it. */
10026 if (mouse_face_here_p)
10027 hl = DRAW_MOUSE_FACE;
10028 else if (cursor_row->inverse_p)
10029 hl = DRAW_INVERSE_VIDEO;
10030 else
10031 hl = DRAW_NORMAL_TEXT;
10032 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10033
10034 mark_cursor_off:
10035 w->phys_cursor_on_p = 0;
10036 w->phys_cursor_type = NO_CURSOR;
10037 }
10038
10039
10040 /* Display or clear cursor of window W. If ON is zero, clear the
10041 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10042 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10043
10044 void
10045 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10046 struct window *w;
10047 int on, hpos, vpos, x, y;
10048 {
10049 struct frame *f = XFRAME (w->frame);
10050 int new_cursor_type;
10051 struct glyph_matrix *current_glyphs;
10052 struct glyph_row *glyph_row;
10053 struct glyph *glyph;
10054
10055 /* This is pointless on invisible frames, and dangerous on garbaged
10056 windows and frames; in the latter case, the frame or window may
10057 be in the midst of changing its size, and x and y may be off the
10058 window. */
10059 if (! FRAME_VISIBLE_P (f)
10060 || FRAME_GARBAGED_P (f)
10061 || vpos >= w->current_matrix->nrows
10062 || hpos >= w->current_matrix->matrix_w)
10063 return;
10064
10065 /* If cursor is off and we want it off, return quickly. */
10066 if (!on && !w->phys_cursor_on_p)
10067 return;
10068
10069 current_glyphs = w->current_matrix;
10070 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10071 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10072
10073 /* If cursor row is not enabled, we don't really know where to
10074 display the cursor. */
10075 if (!glyph_row->enabled_p)
10076 {
10077 w->phys_cursor_on_p = 0;
10078 return;
10079 }
10080
10081 xassert (interrupt_input_blocked);
10082
10083 /* Set new_cursor_type to the cursor we want to be displayed. In a
10084 mini-buffer window, we want the cursor only to appear if we are
10085 reading input from this window. For the selected window, we want
10086 the cursor type given by the frame parameter. If explicitly
10087 marked off, draw no cursor. In all other cases, we want a hollow
10088 box cursor. */
10089 if (cursor_in_echo_area
10090 && FRAME_HAS_MINIBUF_P (f)
10091 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10092 {
10093 if (w == XWINDOW (echo_area_window))
10094 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10095 else
10096 new_cursor_type = HOLLOW_BOX_CURSOR;
10097 }
10098 else
10099 {
10100 if (w != XWINDOW (selected_window)
10101 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10102 {
10103 if (MINI_WINDOW_P (w))
10104 new_cursor_type = NO_CURSOR;
10105 else
10106 new_cursor_type = HOLLOW_BOX_CURSOR;
10107 }
10108 else if (w->cursor_off_p)
10109 new_cursor_type = NO_CURSOR;
10110 else
10111 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10112 }
10113
10114 /* If cursor is currently being shown and we don't want it to be or
10115 it is in the wrong place, or the cursor type is not what we want,
10116 erase it. */
10117 if (w->phys_cursor_on_p
10118 && (!on
10119 || w->phys_cursor.x != x
10120 || w->phys_cursor.y != y
10121 || new_cursor_type != w->phys_cursor_type))
10122 x_erase_phys_cursor (w);
10123
10124 /* If the cursor is now invisible and we want it to be visible,
10125 display it. */
10126 if (on && !w->phys_cursor_on_p)
10127 {
10128 w->phys_cursor_ascent = glyph_row->ascent;
10129 w->phys_cursor_height = glyph_row->height;
10130
10131 /* Set phys_cursor_.* before x_draw_.* is called because some
10132 of them may need the information. */
10133 w->phys_cursor.x = x;
10134 w->phys_cursor.y = glyph_row->y;
10135 w->phys_cursor.hpos = hpos;
10136 w->phys_cursor.vpos = vpos;
10137 w->phys_cursor_type = new_cursor_type;
10138 w->phys_cursor_on_p = 1;
10139
10140 switch (new_cursor_type)
10141 {
10142 case HOLLOW_BOX_CURSOR:
10143 x_draw_hollow_cursor (w, glyph_row);
10144 break;
10145
10146 case FILLED_BOX_CURSOR:
10147 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10148 break;
10149
10150 case BAR_CURSOR:
10151 x_draw_bar_cursor (w, glyph_row);
10152 break;
10153
10154 case NO_CURSOR:
10155 break;
10156
10157 default:
10158 abort ();
10159 }
10160 }
10161
10162 #ifndef XFlush
10163 if (updating_frame != f)
10164 XFlush (FRAME_X_DISPLAY (f));
10165 #endif
10166 }
10167
10168
10169 /* Display the cursor on window W, or clear it. X and Y are window
10170 relative pixel coordinates. HPOS and VPOS are glyph matrix
10171 positions. If W is not the selected window, display a hollow
10172 cursor. ON non-zero means display the cursor at X, Y which
10173 correspond to HPOS, VPOS, otherwise it is cleared. */
10174
10175 void
10176 x_display_cursor (w, on, hpos, vpos, x, y)
10177 struct window *w;
10178 int on, hpos, vpos, x, y;
10179 {
10180 BLOCK_INPUT;
10181 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10182 UNBLOCK_INPUT;
10183 }
10184
10185
10186 /* Display the cursor on window W, or clear it, according to ON_P.
10187 Don't change the cursor's position. */
10188
10189 void
10190 x_update_cursor (f, on_p)
10191 struct frame *f;
10192 {
10193 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10194 }
10195
10196
10197 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10198 in the window tree rooted at W. */
10199
10200 static void
10201 x_update_cursor_in_window_tree (w, on_p)
10202 struct window *w;
10203 int on_p;
10204 {
10205 while (w)
10206 {
10207 if (!NILP (w->hchild))
10208 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10209 else if (!NILP (w->vchild))
10210 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10211 else
10212 x_update_window_cursor (w, on_p);
10213
10214 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10215 }
10216 }
10217
10218
10219 /* Switch the display of W's cursor on or off, according to the value
10220 of ON. */
10221
10222 static void
10223 x_update_window_cursor (w, on)
10224 struct window *w;
10225 int on;
10226 {
10227 BLOCK_INPUT;
10228 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10229 w->phys_cursor.x, w->phys_cursor.y);
10230 UNBLOCK_INPUT;
10231 }
10232
10233
10234
10235 \f
10236 /* Icons. */
10237
10238 /* Refresh bitmap kitchen sink icon for frame F
10239 when we get an expose event for it. */
10240
10241 void
10242 refreshicon (f)
10243 struct frame *f;
10244 {
10245 /* Normally, the window manager handles this function. */
10246 }
10247
10248 /* Make the x-window of frame F use the gnu icon bitmap. */
10249
10250 int
10251 x_bitmap_icon (f, file)
10252 struct frame *f;
10253 Lisp_Object file;
10254 {
10255 int bitmap_id;
10256
10257 if (FRAME_X_WINDOW (f) == 0)
10258 return 1;
10259
10260 /* Free up our existing icon bitmap if any. */
10261 if (f->output_data.x->icon_bitmap > 0)
10262 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10263 f->output_data.x->icon_bitmap = 0;
10264
10265 if (STRINGP (file))
10266 bitmap_id = x_create_bitmap_from_file (f, file);
10267 else
10268 {
10269 /* Create the GNU bitmap if necessary. */
10270 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10271 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10272 = x_create_bitmap_from_data (f, gnu_bits,
10273 gnu_width, gnu_height);
10274
10275 /* The first time we create the GNU bitmap,
10276 this increments the ref-count one extra time.
10277 As a result, the GNU bitmap is never freed.
10278 That way, we don't have to worry about allocating it again. */
10279 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10280
10281 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10282 }
10283
10284 x_wm_set_icon_pixmap (f, bitmap_id);
10285 f->output_data.x->icon_bitmap = bitmap_id;
10286
10287 return 0;
10288 }
10289
10290
10291 /* Make the x-window of frame F use a rectangle with text.
10292 Use ICON_NAME as the text. */
10293
10294 int
10295 x_text_icon (f, icon_name)
10296 struct frame *f;
10297 char *icon_name;
10298 {
10299 if (FRAME_X_WINDOW (f) == 0)
10300 return 1;
10301
10302 #ifdef HAVE_X11R4
10303 {
10304 XTextProperty text;
10305 text.value = (unsigned char *) icon_name;
10306 text.encoding = XA_STRING;
10307 text.format = 8;
10308 text.nitems = strlen (icon_name);
10309 #ifdef USE_X_TOOLKIT
10310 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10311 &text);
10312 #else /* not USE_X_TOOLKIT */
10313 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10314 #endif /* not USE_X_TOOLKIT */
10315 }
10316 #else /* not HAVE_X11R4 */
10317 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10318 #endif /* not HAVE_X11R4 */
10319
10320 if (f->output_data.x->icon_bitmap > 0)
10321 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10322 f->output_data.x->icon_bitmap = 0;
10323 x_wm_set_icon_pixmap (f, 0);
10324
10325 return 0;
10326 }
10327 \f
10328 #define X_ERROR_MESSAGE_SIZE 200
10329
10330 /* If non-nil, this should be a string.
10331 It means catch X errors and store the error message in this string. */
10332
10333 static Lisp_Object x_error_message_string;
10334
10335 /* An X error handler which stores the error message in
10336 x_error_message_string. This is called from x_error_handler if
10337 x_catch_errors is in effect. */
10338
10339 static void
10340 x_error_catcher (display, error)
10341 Display *display;
10342 XErrorEvent *error;
10343 {
10344 XGetErrorText (display, error->error_code,
10345 XSTRING (x_error_message_string)->data,
10346 X_ERROR_MESSAGE_SIZE);
10347 }
10348
10349 /* Begin trapping X errors for display DPY. Actually we trap X errors
10350 for all displays, but DPY should be the display you are actually
10351 operating on.
10352
10353 After calling this function, X protocol errors no longer cause
10354 Emacs to exit; instead, they are recorded in the string
10355 stored in x_error_message_string.
10356
10357 Calling x_check_errors signals an Emacs error if an X error has
10358 occurred since the last call to x_catch_errors or x_check_errors.
10359
10360 Calling x_uncatch_errors resumes the normal error handling. */
10361
10362 void x_check_errors ();
10363 static Lisp_Object x_catch_errors_unwind ();
10364
10365 int
10366 x_catch_errors (dpy)
10367 Display *dpy;
10368 {
10369 int count = specpdl_ptr - specpdl;
10370
10371 /* Make sure any errors from previous requests have been dealt with. */
10372 XSync (dpy, False);
10373
10374 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10375
10376 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10377 XSTRING (x_error_message_string)->data[0] = 0;
10378
10379 return count;
10380 }
10381
10382 /* Unbind the binding that we made to check for X errors. */
10383
10384 static Lisp_Object
10385 x_catch_errors_unwind (old_val)
10386 Lisp_Object old_val;
10387 {
10388 x_error_message_string = old_val;
10389 return Qnil;
10390 }
10391
10392 /* If any X protocol errors have arrived since the last call to
10393 x_catch_errors or x_check_errors, signal an Emacs error using
10394 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10395
10396 void
10397 x_check_errors (dpy, format)
10398 Display *dpy;
10399 char *format;
10400 {
10401 /* Make sure to catch any errors incurred so far. */
10402 XSync (dpy, False);
10403
10404 if (XSTRING (x_error_message_string)->data[0])
10405 error (format, XSTRING (x_error_message_string)->data);
10406 }
10407
10408 /* Nonzero if we had any X protocol errors
10409 since we did x_catch_errors on DPY. */
10410
10411 int
10412 x_had_errors_p (dpy)
10413 Display *dpy;
10414 {
10415 /* Make sure to catch any errors incurred so far. */
10416 XSync (dpy, False);
10417
10418 return XSTRING (x_error_message_string)->data[0] != 0;
10419 }
10420
10421 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10422
10423 void
10424 x_clear_errors (dpy)
10425 Display *dpy;
10426 {
10427 XSTRING (x_error_message_string)->data[0] = 0;
10428 }
10429
10430 /* Stop catching X protocol errors and let them make Emacs die.
10431 DPY should be the display that was passed to x_catch_errors.
10432 COUNT should be the value that was returned by
10433 the corresponding call to x_catch_errors. */
10434
10435 void
10436 x_uncatch_errors (dpy, count)
10437 Display *dpy;
10438 int count;
10439 {
10440 unbind_to (count, Qnil);
10441 }
10442
10443 #if 0
10444 static unsigned int x_wire_count;
10445 x_trace_wire ()
10446 {
10447 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10448 }
10449 #endif /* ! 0 */
10450
10451 \f
10452 /* Handle SIGPIPE, which can happen when the connection to a server
10453 simply goes away. SIGPIPE is handled by x_connection_signal.
10454 Don't need to do anything, because the write which caused the
10455 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10456 which will do the appropriate cleanup for us. */
10457
10458 static SIGTYPE
10459 x_connection_signal (signalnum) /* If we don't have an argument, */
10460 int signalnum; /* some compilers complain in signal calls. */
10461 {
10462 #ifdef USG
10463 /* USG systems forget handlers when they are used;
10464 must reestablish each time */
10465 signal (signalnum, x_connection_signal);
10466 #endif /* USG */
10467 }
10468 \f
10469 /* Handling X errors. */
10470
10471 /* Handle the loss of connection to display DISPLAY. */
10472
10473 static SIGTYPE
10474 x_connection_closed (display, error_message)
10475 Display *display;
10476 char *error_message;
10477 {
10478 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10479 Lisp_Object frame, tail;
10480
10481 /* Indicate that this display is dead. */
10482
10483 #ifdef USE_X_TOOLKIT
10484 XtCloseDisplay (display);
10485 #endif
10486
10487 dpyinfo->display = 0;
10488
10489 /* First delete frames whose mini-buffers are on frames
10490 that are on the dead display. */
10491 FOR_EACH_FRAME (tail, frame)
10492 {
10493 Lisp_Object minibuf_frame;
10494 minibuf_frame
10495 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
10496 if (FRAME_X_P (XFRAME (frame))
10497 && FRAME_X_P (XFRAME (minibuf_frame))
10498 && ! EQ (frame, minibuf_frame)
10499 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
10500 Fdelete_frame (frame, Qt);
10501 }
10502
10503 /* Now delete all remaining frames on the dead display.
10504 We are now sure none of these is used as the mini-buffer
10505 for another frame that we need to delete. */
10506 FOR_EACH_FRAME (tail, frame)
10507 if (FRAME_X_P (XFRAME (frame))
10508 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
10509 {
10510 /* Set this to t so that Fdelete_frame won't get confused
10511 trying to find a replacement. */
10512 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10513 Fdelete_frame (frame, Qt);
10514 }
10515
10516 if (dpyinfo)
10517 x_delete_display (dpyinfo);
10518
10519 if (x_display_list == 0)
10520 {
10521 fprintf (stderr, "%s\n", error_message);
10522 shut_down_emacs (0, 0, Qnil);
10523 exit (70);
10524 }
10525
10526 /* Ordinary stack unwind doesn't deal with these. */
10527 #ifdef SIGIO
10528 sigunblock (sigmask (SIGIO));
10529 #endif
10530 sigunblock (sigmask (SIGALRM));
10531 TOTALLY_UNBLOCK_INPUT;
10532
10533 clear_waiting_for_input ();
10534 error ("%s", error_message);
10535 }
10536
10537 /* This is the usual handler for X protocol errors.
10538 It kills all frames on the display that we got the error for.
10539 If that was the only one, it prints an error message and kills Emacs. */
10540
10541 static void
10542 x_error_quitter (display, error)
10543 Display *display;
10544 XErrorEvent *error;
10545 {
10546 char buf[256], buf1[356];
10547
10548 /* Note that there is no real way portable across R3/R4 to get the
10549 original error handler. */
10550
10551 XGetErrorText (display, error->error_code, buf, sizeof (buf));
10552 sprintf (buf1, "X protocol error: %s on protocol request %d",
10553 buf, error->request_code);
10554 x_connection_closed (display, buf1);
10555 }
10556
10557 /* This is the first-level handler for X protocol errors.
10558 It calls x_error_quitter or x_error_catcher. */
10559
10560 static int
10561 x_error_handler (display, error)
10562 Display *display;
10563 XErrorEvent *error;
10564 {
10565 if (! NILP (x_error_message_string))
10566 x_error_catcher (display, error);
10567 else
10568 x_error_quitter (display, error);
10569 return 0;
10570 }
10571
10572 /* This is the handler for X IO errors, always.
10573 It kills all frames on the display that we lost touch with.
10574 If that was the only one, it prints an error message and kills Emacs. */
10575
10576 static int
10577 x_io_error_quitter (display)
10578 Display *display;
10579 {
10580 char buf[256];
10581
10582 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10583 x_connection_closed (display, buf);
10584 return 0;
10585 }
10586 \f
10587 /* Changing the font of the frame. */
10588
10589 /* Give frame F the font named FONTNAME as its default font, and
10590 return the full name of that font. FONTNAME may be a wildcard
10591 pattern; in that case, we choose some font that fits the pattern.
10592 The return value shows which font we chose. */
10593
10594 Lisp_Object
10595 x_new_font (f, fontname)
10596 struct frame *f;
10597 register char *fontname;
10598 {
10599 struct font_info *fontp
10600 = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
10601
10602 if (!fontp)
10603 return Qnil;
10604
10605 f->output_data.x->font = (XFontStruct *) (fontp->font);
10606 f->output_data.x->font_baseline
10607 = (f->output_data.x->font->ascent + fontp->baseline_offset);
10608 f->output_data.x->fontset = -1;
10609
10610 /* Compute the scroll bar width in character columns. */
10611 if (f->scroll_bar_pixel_width > 0)
10612 {
10613 int wid = FONT_WIDTH (f->output_data.x->font);
10614 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10615 }
10616 else
10617 {
10618 int wid = FONT_WIDTH (f->output_data.x->font);
10619 f->scroll_bar_cols = (14 + wid - 1) / wid;
10620 }
10621
10622 /* Now make the frame display the given font. */
10623 if (FRAME_X_WINDOW (f) != 0)
10624 {
10625 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10626 f->output_data.x->font->fid);
10627 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10628 f->output_data.x->font->fid);
10629 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10630 f->output_data.x->font->fid);
10631
10632 frame_update_line_height (f);
10633 x_set_window_size (f, 0, f->width, f->height);
10634 }
10635 else
10636 /* If we are setting a new frame's font for the first time,
10637 there are no faces yet, so this font's height is the line height. */
10638 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
10639
10640 return build_string (fontp->full_name);
10641 }
10642
10643 /* Give frame F the fontset named FONTSETNAME as its default font, and
10644 return the full name of that fontset. FONTSETNAME may be a wildcard
10645 pattern; in that case, we choose some fontset that fits the pattern.
10646 The return value shows which fontset we chose. */
10647
10648 Lisp_Object
10649 x_new_fontset (f, fontsetname)
10650 struct frame *f;
10651 char *fontsetname;
10652 {
10653 int fontset = fs_query_fontset (f, fontsetname);
10654 struct fontset_info *fontsetp;
10655 Lisp_Object result;
10656
10657 if (fontset < 0)
10658 return Qnil;
10659
10660 if (f->output_data.x->fontset == fontset)
10661 /* This fontset is already set in frame F. There's nothing more
10662 to do. */
10663 return build_string (fontsetname);
10664
10665 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
10666
10667 if (!fontsetp->fontname[CHARSET_ASCII])
10668 /* This fontset doesn't contain ASCII font. */
10669 return Qnil;
10670
10671 result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
10672
10673 if (!STRINGP (result))
10674 /* Can't load ASCII font. */
10675 return Qnil;
10676
10677 /* Since x_new_font doesn't update any fontset information, do it now. */
10678 f->output_data.x->fontset = fontset;
10679 FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
10680 CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
10681
10682 return build_string (fontsetname);
10683 }
10684 \f
10685 /* Calculate the absolute position in frame F
10686 from its current recorded position values and gravity. */
10687
10688 void
10689 x_calc_absolute_position (f)
10690 struct frame *f;
10691 {
10692 Window child;
10693 int win_x = 0, win_y = 0;
10694 int flags = f->output_data.x->size_hint_flags;
10695 int this_window;
10696
10697 /* We have nothing to do if the current position
10698 is already for the top-left corner. */
10699 if (! ((flags & XNegative) || (flags & YNegative)))
10700 return;
10701
10702 #ifdef USE_X_TOOLKIT
10703 this_window = XtWindow (f->output_data.x->widget);
10704 #else
10705 this_window = FRAME_X_WINDOW (f);
10706 #endif
10707
10708 /* Find the position of the outside upper-left corner of
10709 the inner window, with respect to the outer window.
10710 But do this only if we will need the results. */
10711 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10712 {
10713 int count;
10714
10715 BLOCK_INPUT;
10716 count = x_catch_errors (FRAME_X_DISPLAY (f));
10717 while (1)
10718 {
10719 x_clear_errors (FRAME_X_DISPLAY (f));
10720 XTranslateCoordinates (FRAME_X_DISPLAY (f),
10721
10722 /* From-window, to-window. */
10723 this_window,
10724 f->output_data.x->parent_desc,
10725
10726 /* From-position, to-position. */
10727 0, 0, &win_x, &win_y,
10728
10729 /* Child of win. */
10730 &child);
10731 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
10732 {
10733 Window newroot, newparent = 0xdeadbeef;
10734 Window *newchildren;
10735 int nchildren;
10736
10737 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
10738 &newparent, &newchildren, &nchildren))
10739 break;
10740
10741 XFree ((char *) newchildren);
10742
10743 f->output_data.x->parent_desc = newparent;
10744 }
10745 else
10746 break;
10747 }
10748
10749 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
10750 UNBLOCK_INPUT;
10751 }
10752
10753 /* Treat negative positions as relative to the leftmost bottommost
10754 position that fits on the screen. */
10755 if (flags & XNegative)
10756 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
10757 - 2 * f->output_data.x->border_width - win_x
10758 - PIXEL_WIDTH (f)
10759 + f->output_data.x->left_pos);
10760
10761 if (flags & YNegative)
10762 {
10763 int menubar_height = 0;
10764
10765 #ifdef USE_X_TOOLKIT
10766 if (f->output_data.x->menubar_widget)
10767 menubar_height
10768 = (f->output_data.x->menubar_widget->core.height
10769 + f->output_data.x->menubar_widget->core.border_width);
10770 #endif
10771
10772 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
10773 - 2 * f->output_data.x->border_width
10774 - win_y
10775 - PIXEL_HEIGHT (f)
10776 - menubar_height
10777 + f->output_data.x->top_pos);
10778 }
10779
10780 /* The left_pos and top_pos
10781 are now relative to the top and left screen edges,
10782 so the flags should correspond. */
10783 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
10784 }
10785
10786 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10787 to really change the position, and 0 when calling from
10788 x_make_frame_visible (in that case, XOFF and YOFF are the current
10789 position values). It is -1 when calling from x_set_frame_parameters,
10790 which means, do adjust for borders but don't change the gravity. */
10791
10792 void
10793 x_set_offset (f, xoff, yoff, change_gravity)
10794 struct frame *f;
10795 register int xoff, yoff;
10796 int change_gravity;
10797 {
10798 int modified_top, modified_left;
10799
10800 if (change_gravity > 0)
10801 {
10802 f->output_data.x->top_pos = yoff;
10803 f->output_data.x->left_pos = xoff;
10804 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
10805 if (xoff < 0)
10806 f->output_data.x->size_hint_flags |= XNegative;
10807 if (yoff < 0)
10808 f->output_data.x->size_hint_flags |= YNegative;
10809 f->output_data.x->win_gravity = NorthWestGravity;
10810 }
10811 x_calc_absolute_position (f);
10812
10813 BLOCK_INPUT;
10814 x_wm_set_size_hint (f, (long) 0, 0);
10815
10816 modified_left = f->output_data.x->left_pos;
10817 modified_top = f->output_data.x->top_pos;
10818 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
10819 this seems to be unnecessary and incorrect. rms, 4/17/97. */
10820 /* It is a mystery why we need to add the border_width here
10821 when the frame is already visible, but experiment says we do. */
10822 if (change_gravity != 0)
10823 {
10824 modified_left += f->output_data.x->border_width;
10825 modified_top += f->output_data.x->border_width;
10826 }
10827 #endif
10828
10829 #ifdef USE_X_TOOLKIT
10830 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10831 modified_left, modified_top);
10832 #else /* not USE_X_TOOLKIT */
10833 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10834 modified_left, modified_top);
10835 #endif /* not USE_X_TOOLKIT */
10836 UNBLOCK_INPUT;
10837 }
10838
10839 /* Call this to change the size of frame F's x-window.
10840 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10841 for this size change and subsequent size changes.
10842 Otherwise we leave the window gravity unchanged. */
10843
10844 void
10845 x_set_window_size (f, change_gravity, cols, rows)
10846 struct frame *f;
10847 int change_gravity;
10848 int cols, rows;
10849 {
10850 #ifndef USE_X_TOOLKIT
10851 int pixelwidth, pixelheight;
10852 #endif
10853
10854 BLOCK_INPUT;
10855
10856 #ifdef USE_X_TOOLKIT
10857 {
10858 /* The x and y position of the widget is clobbered by the
10859 call to XtSetValues within EmacsFrameSetCharSize.
10860 This is a real kludge, but I don't understand Xt so I can't
10861 figure out a correct fix. Can anyone else tell me? -- rms. */
10862 int xpos = f->output_data.x->widget->core.x;
10863 int ypos = f->output_data.x->widget->core.y;
10864 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
10865 f->output_data.x->widget->core.x = xpos;
10866 f->output_data.x->widget->core.y = ypos;
10867 }
10868
10869 #else /* not USE_X_TOOLKIT */
10870
10871 check_frame_size (f, &rows, &cols);
10872 f->output_data.x->vertical_scroll_bar_extra
10873 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
10874 ? 0
10875 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
10876 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
10877 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
10878 f->output_data.x->flags_areas_extra
10879 = FRAME_FLAGS_AREA_WIDTH (f);
10880 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
10881 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
10882
10883 f->output_data.x->win_gravity = NorthWestGravity;
10884 x_wm_set_size_hint (f, (long) 0, 0);
10885
10886 XSync (FRAME_X_DISPLAY (f), False);
10887 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10888 pixelwidth, pixelheight);
10889
10890 /* Now, strictly speaking, we can't be sure that this is accurate,
10891 but the window manager will get around to dealing with the size
10892 change request eventually, and we'll hear how it went when the
10893 ConfigureNotify event gets here.
10894
10895 We could just not bother storing any of this information here,
10896 and let the ConfigureNotify event set everything up, but that
10897 might be kind of confusing to the Lisp code, since size changes
10898 wouldn't be reported in the frame parameters until some random
10899 point in the future when the ConfigureNotify event arrives.
10900
10901 We pass 1 for DELAY since we can't run Lisp code inside of
10902 a BLOCK_INPUT. */
10903 change_frame_size (f, rows, cols, 0, 1, 0);
10904 PIXEL_WIDTH (f) = pixelwidth;
10905 PIXEL_HEIGHT (f) = pixelheight;
10906
10907 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10908 receive in the ConfigureNotify event; if we get what we asked
10909 for, then the event won't cause the screen to become garbaged, so
10910 we have to make sure to do it here. */
10911 SET_FRAME_GARBAGED (f);
10912
10913 XFlush (FRAME_X_DISPLAY (f));
10914
10915 #endif /* not USE_X_TOOLKIT */
10916
10917 /* If cursor was outside the new size, mark it as off. */
10918 mark_window_cursors_off (XWINDOW (f->root_window));
10919
10920 /* Clear out any recollection of where the mouse highlighting was,
10921 since it might be in a place that's outside the new frame size.
10922 Actually checking whether it is outside is a pain in the neck,
10923 so don't try--just let the highlighting be done afresh with new size. */
10924 cancel_mouse_face (f);
10925
10926 UNBLOCK_INPUT;
10927 }
10928 \f
10929 /* Mouse warping. */
10930
10931 void
10932 x_set_mouse_position (f, x, y)
10933 struct frame *f;
10934 int x, y;
10935 {
10936 int pix_x, pix_y;
10937
10938 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
10939 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
10940
10941 if (pix_x < 0) pix_x = 0;
10942 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
10943
10944 if (pix_y < 0) pix_y = 0;
10945 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
10946
10947 BLOCK_INPUT;
10948
10949 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
10950 0, 0, 0, 0, pix_x, pix_y);
10951 UNBLOCK_INPUT;
10952 }
10953
10954 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
10955
10956 void
10957 x_set_mouse_pixel_position (f, pix_x, pix_y)
10958 struct frame *f;
10959 int pix_x, pix_y;
10960 {
10961 BLOCK_INPUT;
10962
10963 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
10964 0, 0, 0, 0, pix_x, pix_y);
10965 UNBLOCK_INPUT;
10966 }
10967 \f
10968 /* focus shifting, raising and lowering. */
10969
10970 void
10971 x_focus_on_frame (f)
10972 struct frame *f;
10973 {
10974 #if 0 /* This proves to be unpleasant. */
10975 x_raise_frame (f);
10976 #endif
10977 #if 0
10978 /* I don't think that the ICCCM allows programs to do things like this
10979 without the interaction of the window manager. Whatever you end up
10980 doing with this code, do it to x_unfocus_frame too. */
10981 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10982 RevertToPointerRoot, CurrentTime);
10983 #endif /* ! 0 */
10984 }
10985
10986 void
10987 x_unfocus_frame (f)
10988 struct frame *f;
10989 {
10990 #if 0
10991 /* Look at the remarks in x_focus_on_frame. */
10992 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
10993 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
10994 RevertToPointerRoot, CurrentTime);
10995 #endif /* ! 0 */
10996 }
10997
10998 /* Raise frame F. */
10999
11000 void
11001 x_raise_frame (f)
11002 struct frame *f;
11003 {
11004 if (f->async_visible)
11005 {
11006 BLOCK_INPUT;
11007 #ifdef USE_X_TOOLKIT
11008 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11009 #else /* not USE_X_TOOLKIT */
11010 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11011 #endif /* not USE_X_TOOLKIT */
11012 XFlush (FRAME_X_DISPLAY (f));
11013 UNBLOCK_INPUT;
11014 }
11015 }
11016
11017 /* Lower frame F. */
11018
11019 void
11020 x_lower_frame (f)
11021 struct frame *f;
11022 {
11023 if (f->async_visible)
11024 {
11025 BLOCK_INPUT;
11026 #ifdef USE_X_TOOLKIT
11027 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11028 #else /* not USE_X_TOOLKIT */
11029 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11030 #endif /* not USE_X_TOOLKIT */
11031 XFlush (FRAME_X_DISPLAY (f));
11032 UNBLOCK_INPUT;
11033 }
11034 }
11035
11036 static void
11037 XTframe_raise_lower (f, raise_flag)
11038 FRAME_PTR f;
11039 int raise_flag;
11040 {
11041 if (raise_flag)
11042 x_raise_frame (f);
11043 else
11044 x_lower_frame (f);
11045 }
11046 \f
11047 /* Change of visibility. */
11048
11049 /* This tries to wait until the frame is really visible.
11050 However, if the window manager asks the user where to position
11051 the frame, this will return before the user finishes doing that.
11052 The frame will not actually be visible at that time,
11053 but it will become visible later when the window manager
11054 finishes with it. */
11055
11056 void
11057 x_make_frame_visible (f)
11058 struct frame *f;
11059 {
11060 Lisp_Object type;
11061 int original_top, original_left;
11062
11063 BLOCK_INPUT;
11064
11065 type = x_icon_type (f);
11066 if (!NILP (type))
11067 x_bitmap_icon (f, type);
11068
11069 if (! FRAME_VISIBLE_P (f))
11070 {
11071 /* We test FRAME_GARBAGED_P here to make sure we don't
11072 call x_set_offset a second time
11073 if we get to x_make_frame_visible a second time
11074 before the window gets really visible. */
11075 if (! FRAME_ICONIFIED_P (f)
11076 && ! f->output_data.x->asked_for_visible)
11077 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11078
11079 f->output_data.x->asked_for_visible = 1;
11080
11081 if (! EQ (Vx_no_window_manager, Qt))
11082 x_wm_set_window_state (f, NormalState);
11083 #ifdef USE_X_TOOLKIT
11084 /* This was XtPopup, but that did nothing for an iconified frame. */
11085 XtMapWidget (f->output_data.x->widget);
11086 #else /* not USE_X_TOOLKIT */
11087 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11088 #endif /* not USE_X_TOOLKIT */
11089 #if 0 /* This seems to bring back scroll bars in the wrong places
11090 if the window configuration has changed. They seem
11091 to come back ok without this. */
11092 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
11093 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11094 #endif
11095 }
11096
11097 XFlush (FRAME_X_DISPLAY (f));
11098
11099 /* Synchronize to ensure Emacs knows the frame is visible
11100 before we do anything else. We do this loop with input not blocked
11101 so that incoming events are handled. */
11102 {
11103 Lisp_Object frame;
11104 int count = input_signal_count;
11105 /* This must be before UNBLOCK_INPUT
11106 since events that arrive in response to the actions above
11107 will set it when they are handled. */
11108 int previously_visible = f->output_data.x->has_been_visible;
11109
11110 original_left = f->output_data.x->left_pos;
11111 original_top = f->output_data.x->top_pos;
11112
11113 /* This must come after we set COUNT. */
11114 UNBLOCK_INPUT;
11115
11116 /* We unblock here so that arriving X events are processed. */
11117
11118 /* Now move the window back to where it was "supposed to be".
11119 But don't do it if the gravity is negative.
11120 When the gravity is negative, this uses a position
11121 that is 3 pixels too low. Perhaps that's really the border width.
11122
11123 Don't do this if the window has never been visible before,
11124 because the window manager may choose the position
11125 and we don't want to override it. */
11126
11127 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
11128 && f->output_data.x->win_gravity == NorthWestGravity
11129 && previously_visible)
11130 {
11131 Drawable rootw;
11132 int x, y;
11133 unsigned int width, height, border, depth;
11134
11135 BLOCK_INPUT;
11136
11137 /* On some window managers (such as FVWM) moving an existing
11138 window, even to the same place, causes the window manager
11139 to introduce an offset. This can cause the window to move
11140 to an unexpected location. Check the geometry (a little
11141 slow here) and then verify that the window is in the right
11142 place. If the window is not in the right place, move it
11143 there, and take the potential window manager hit. */
11144 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11145 &rootw, &x, &y, &width, &height, &border, &depth);
11146
11147 if (original_left != x || original_top != y)
11148 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11149 original_left, original_top);
11150
11151 UNBLOCK_INPUT;
11152 }
11153
11154 XSETFRAME (frame, f);
11155
11156 while (1)
11157 {
11158 x_sync (f);
11159 /* Once we have handled input events,
11160 we should have received the MapNotify if one is coming.
11161 So if we have not got it yet, stop looping.
11162 Some window managers make their own decisions
11163 about visibility. */
11164 if (input_signal_count != count)
11165 break;
11166 /* Machines that do polling rather than SIGIO have been observed
11167 to go into a busy-wait here. So we'll fake an alarm signal
11168 to let the handler know that there's something to be read.
11169 We used to raise a real alarm, but it seems that the handler
11170 isn't always enabled here. This is probably a bug. */
11171 if (input_polling_used ())
11172 {
11173 /* It could be confusing if a real alarm arrives while processing
11174 the fake one. Turn it off and let the handler reset it. */
11175 alarm (0);
11176 input_poll_signal (0);
11177 }
11178 /* Once we have handled input events,
11179 we should have received the MapNotify if one is coming.
11180 So if we have not got it yet, stop looping.
11181 Some window managers make their own decisions
11182 about visibility. */
11183 if (input_signal_count != count)
11184 break;
11185 }
11186 FRAME_SAMPLE_VISIBILITY (f);
11187 }
11188 }
11189
11190 /* Change from mapped state to withdrawn state. */
11191
11192 /* Make the frame visible (mapped and not iconified). */
11193
11194 void
11195 x_make_frame_invisible (f)
11196 struct frame *f;
11197 {
11198 Window window;
11199
11200 #ifdef USE_X_TOOLKIT
11201 /* Use the frame's outermost window, not the one we normally draw on. */
11202 window = XtWindow (f->output_data.x->widget);
11203 #else /* not USE_X_TOOLKIT */
11204 window = FRAME_X_WINDOW (f);
11205 #endif /* not USE_X_TOOLKIT */
11206
11207 /* Don't keep the highlight on an invisible frame. */
11208 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11209 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11210
11211 #if 0/* This might add unreliability; I don't trust it -- rms. */
11212 if (! f->async_visible && ! f->async_iconified)
11213 return;
11214 #endif
11215
11216 BLOCK_INPUT;
11217
11218 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11219 that the current position of the window is user-specified, rather than
11220 program-specified, so that when the window is mapped again, it will be
11221 placed at the same location, without forcing the user to position it
11222 by hand again (they have already done that once for this window.) */
11223 x_wm_set_size_hint (f, (long) 0, 1);
11224
11225 #ifdef HAVE_X11R4
11226
11227 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11228 DefaultScreen (FRAME_X_DISPLAY (f))))
11229 {
11230 UNBLOCK_INPUT_RESIGNAL;
11231 error ("Can't notify window manager of window withdrawal");
11232 }
11233 #else /* ! defined (HAVE_X11R4) */
11234
11235 /* Tell the window manager what we're going to do. */
11236 if (! EQ (Vx_no_window_manager, Qt))
11237 {
11238 XEvent unmap;
11239
11240 unmap.xunmap.type = UnmapNotify;
11241 unmap.xunmap.window = window;
11242 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
11243 unmap.xunmap.from_configure = False;
11244 if (! XSendEvent (FRAME_X_DISPLAY (f),
11245 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11246 False,
11247 SubstructureRedirectMaskSubstructureNotifyMask,
11248 &unmap))
11249 {
11250 UNBLOCK_INPUT_RESIGNAL;
11251 error ("Can't notify window manager of withdrawal");
11252 }
11253 }
11254
11255 /* Unmap the window ourselves. Cheeky! */
11256 XUnmapWindow (FRAME_X_DISPLAY (f), window);
11257 #endif /* ! defined (HAVE_X11R4) */
11258
11259 /* We can't distinguish this from iconification
11260 just by the event that we get from the server.
11261 So we can't win using the usual strategy of letting
11262 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11263 and synchronize with the server to make sure we agree. */
11264 f->visible = 0;
11265 FRAME_ICONIFIED_P (f) = 0;
11266 f->async_visible = 0;
11267 f->async_iconified = 0;
11268
11269 x_sync (f);
11270
11271 UNBLOCK_INPUT;
11272 }
11273
11274 /* Change window state from mapped to iconified. */
11275
11276 void
11277 x_iconify_frame (f)
11278 struct frame *f;
11279 {
11280 int result;
11281 Lisp_Object type;
11282
11283 /* Don't keep the highlight on an invisible frame. */
11284 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11285 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11286
11287 if (f->async_iconified)
11288 return;
11289
11290 BLOCK_INPUT;
11291
11292 FRAME_SAMPLE_VISIBILITY (f);
11293
11294 type = x_icon_type (f);
11295 if (!NILP (type))
11296 x_bitmap_icon (f, type);
11297
11298 #ifdef USE_X_TOOLKIT
11299
11300 if (! FRAME_VISIBLE_P (f))
11301 {
11302 if (! EQ (Vx_no_window_manager, Qt))
11303 x_wm_set_window_state (f, IconicState);
11304 /* This was XtPopup, but that did nothing for an iconified frame. */
11305 XtMapWidget (f->output_data.x->widget);
11306 /* The server won't give us any event to indicate
11307 that an invisible frame was changed to an icon,
11308 so we have to record it here. */
11309 f->iconified = 1;
11310 f->visible = 1;
11311 f->async_iconified = 1;
11312 f->async_visible = 0;
11313 UNBLOCK_INPUT;
11314 return;
11315 }
11316
11317 result = XIconifyWindow (FRAME_X_DISPLAY (f),
11318 XtWindow (f->output_data.x->widget),
11319 DefaultScreen (FRAME_X_DISPLAY (f)));
11320 UNBLOCK_INPUT;
11321
11322 if (!result)
11323 error ("Can't notify window manager of iconification");
11324
11325 f->async_iconified = 1;
11326 f->async_visible = 0;
11327
11328
11329 BLOCK_INPUT;
11330 XFlush (FRAME_X_DISPLAY (f));
11331 UNBLOCK_INPUT;
11332 #else /* not USE_X_TOOLKIT */
11333
11334 /* Make sure the X server knows where the window should be positioned,
11335 in case the user deiconifies with the window manager. */
11336 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
11337 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11338
11339 /* Since we don't know which revision of X we're running, we'll use both
11340 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11341
11342 /* X11R4: send a ClientMessage to the window manager using the
11343 WM_CHANGE_STATE type. */
11344 {
11345 XEvent message;
11346
11347 message.xclient.window = FRAME_X_WINDOW (f);
11348 message.xclient.type = ClientMessage;
11349 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
11350 message.xclient.format = 32;
11351 message.xclient.data.l[0] = IconicState;
11352
11353 if (! XSendEvent (FRAME_X_DISPLAY (f),
11354 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11355 False,
11356 SubstructureRedirectMask | SubstructureNotifyMask,
11357 &message))
11358 {
11359 UNBLOCK_INPUT_RESIGNAL;
11360 error ("Can't notify window manager of iconification");
11361 }
11362 }
11363
11364 /* X11R3: set the initial_state field of the window manager hints to
11365 IconicState. */
11366 x_wm_set_window_state (f, IconicState);
11367
11368 if (!FRAME_VISIBLE_P (f))
11369 {
11370 /* If the frame was withdrawn, before, we must map it. */
11371 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11372 }
11373
11374 f->async_iconified = 1;
11375 f->async_visible = 0;
11376
11377 XFlush (FRAME_X_DISPLAY (f));
11378 UNBLOCK_INPUT;
11379 #endif /* not USE_X_TOOLKIT */
11380 }
11381 \f
11382 /* Destroy the X window of frame F. */
11383
11384 void
11385 x_destroy_window (f)
11386 struct frame *f;
11387 {
11388 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11389
11390 BLOCK_INPUT;
11391
11392 /* If a display connection is dead, don't try sending more
11393 commands to the X server. */
11394 if (dpyinfo->display != 0)
11395 {
11396 if (f->output_data.x->icon_desc != 0)
11397 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
11398 #ifdef HAVE_X_I18N
11399 if (FRAME_XIM (f))
11400 {
11401 XDestroyIC (FRAME_XIC (f));
11402 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11403 /* This line causes crashes on Solaris with Openwin,
11404 due to an apparent bug in XCloseIM.
11405 X11R6 seems not to have the bug. */
11406 XCloseIM (FRAME_XIM (f));
11407 #endif
11408 }
11409 #endif
11410 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
11411 #ifdef USE_X_TOOLKIT
11412 if (f->output_data.x->widget)
11413 XtDestroyWidget (f->output_data.x->widget);
11414 free_frame_menubar (f);
11415 #endif /* USE_X_TOOLKIT */
11416
11417 free_frame_faces (f);
11418 XFlush (FRAME_X_DISPLAY (f));
11419 }
11420
11421 if (f->output_data.x->saved_menu_event)
11422 xfree (f->output_data.x->saved_menu_event);
11423
11424 xfree (f->output_data.x);
11425 f->output_data.x = 0;
11426 if (f == dpyinfo->x_focus_frame)
11427 dpyinfo->x_focus_frame = 0;
11428 if (f == dpyinfo->x_focus_event_frame)
11429 dpyinfo->x_focus_event_frame = 0;
11430 if (f == dpyinfo->x_highlight_frame)
11431 dpyinfo->x_highlight_frame = 0;
11432
11433 dpyinfo->reference_count--;
11434
11435 if (f == dpyinfo->mouse_face_mouse_frame)
11436 {
11437 dpyinfo->mouse_face_beg_row
11438 = dpyinfo->mouse_face_beg_col = -1;
11439 dpyinfo->mouse_face_end_row
11440 = dpyinfo->mouse_face_end_col = -1;
11441 dpyinfo->mouse_face_window = Qnil;
11442 dpyinfo->mouse_face_deferred_gc = 0;
11443 dpyinfo->mouse_face_mouse_frame = 0;
11444 }
11445
11446 UNBLOCK_INPUT;
11447 }
11448 \f
11449 /* Setting window manager hints. */
11450
11451 /* Set the normal size hints for the window manager, for frame F.
11452 FLAGS is the flags word to use--or 0 meaning preserve the flags
11453 that the window now has.
11454 If USER_POSITION is nonzero, we set the USPosition
11455 flag (this is useful when FLAGS is 0). */
11456
11457 void
11458 x_wm_set_size_hint (f, flags, user_position)
11459 struct frame *f;
11460 long flags;
11461 int user_position;
11462 {
11463 XSizeHints size_hints;
11464
11465 #ifdef USE_X_TOOLKIT
11466 Arg al[2];
11467 int ac = 0;
11468 Dimension widget_width, widget_height;
11469 Window window = XtWindow (f->output_data.x->widget);
11470 #else /* not USE_X_TOOLKIT */
11471 Window window = FRAME_X_WINDOW (f);
11472 #endif /* not USE_X_TOOLKIT */
11473
11474 /* Setting PMaxSize caused various problems. */
11475 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
11476
11477 size_hints.x = f->output_data.x->left_pos;
11478 size_hints.y = f->output_data.x->top_pos;
11479
11480 #ifdef USE_X_TOOLKIT
11481 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
11482 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
11483 XtGetValues (f->output_data.x->widget, al, ac);
11484 size_hints.height = widget_height;
11485 size_hints.width = widget_width;
11486 #else /* not USE_X_TOOLKIT */
11487 size_hints.height = PIXEL_HEIGHT (f);
11488 size_hints.width = PIXEL_WIDTH (f);
11489 #endif /* not USE_X_TOOLKIT */
11490
11491 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
11492 size_hints.height_inc = f->output_data.x->line_height;
11493 size_hints.max_width
11494 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
11495 size_hints.max_height
11496 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
11497
11498 /* Calculate the base and minimum sizes.
11499
11500 (When we use the X toolkit, we don't do it here.
11501 Instead we copy the values that the widgets are using, below.) */
11502 #ifndef USE_X_TOOLKIT
11503 {
11504 int base_width, base_height;
11505 int min_rows = 0, min_cols = 0;
11506
11507 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
11508 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
11509
11510 check_frame_size (f, &min_rows, &min_cols);
11511
11512 /* The window manager uses the base width hints to calculate the
11513 current number of rows and columns in the frame while
11514 resizing; min_width and min_height aren't useful for this
11515 purpose, since they might not give the dimensions for a
11516 zero-row, zero-column frame.
11517
11518 We use the base_width and base_height members if we have
11519 them; otherwise, we set the min_width and min_height members
11520 to the size for a zero x zero frame. */
11521
11522 #ifdef HAVE_X11R4
11523 size_hints.flags |= PBaseSize;
11524 size_hints.base_width = base_width;
11525 size_hints.base_height = base_height;
11526 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
11527 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
11528 #else
11529 size_hints.min_width = base_width;
11530 size_hints.min_height = base_height;
11531 #endif
11532 }
11533
11534 /* If we don't need the old flags, we don't need the old hint at all. */
11535 if (flags)
11536 {
11537 size_hints.flags |= flags;
11538 goto no_read;
11539 }
11540 #endif /* not USE_X_TOOLKIT */
11541
11542 {
11543 XSizeHints hints; /* Sometimes I hate X Windows... */
11544 long supplied_return;
11545 int value;
11546
11547 #ifdef HAVE_X11R4
11548 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
11549 &supplied_return);
11550 #else
11551 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
11552 #endif
11553
11554 #ifdef USE_X_TOOLKIT
11555 size_hints.base_height = hints.base_height;
11556 size_hints.base_width = hints.base_width;
11557 size_hints.min_height = hints.min_height;
11558 size_hints.min_width = hints.min_width;
11559 #endif
11560
11561 if (flags)
11562 size_hints.flags |= flags;
11563 else
11564 {
11565 if (value == 0)
11566 hints.flags = 0;
11567 if (hints.flags & PSize)
11568 size_hints.flags |= PSize;
11569 if (hints.flags & PPosition)
11570 size_hints.flags |= PPosition;
11571 if (hints.flags & USPosition)
11572 size_hints.flags |= USPosition;
11573 if (hints.flags & USSize)
11574 size_hints.flags |= USSize;
11575 }
11576 }
11577
11578 #ifndef USE_X_TOOLKIT
11579 no_read:
11580 #endif
11581
11582 #ifdef PWinGravity
11583 size_hints.win_gravity = f->output_data.x->win_gravity;
11584 size_hints.flags |= PWinGravity;
11585
11586 if (user_position)
11587 {
11588 size_hints.flags &= ~ PPosition;
11589 size_hints.flags |= USPosition;
11590 }
11591 #endif /* PWinGravity */
11592
11593 #ifdef HAVE_X11R4
11594 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
11595 #else
11596 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
11597 #endif
11598 }
11599
11600 /* Used for IconicState or NormalState */
11601
11602 void
11603 x_wm_set_window_state (f, state)
11604 struct frame *f;
11605 int state;
11606 {
11607 #ifdef USE_X_TOOLKIT
11608 Arg al[1];
11609
11610 XtSetArg (al[0], XtNinitialState, state);
11611 XtSetValues (f->output_data.x->widget, al, 1);
11612 #else /* not USE_X_TOOLKIT */
11613 Window window = FRAME_X_WINDOW (f);
11614
11615 f->output_data.x->wm_hints.flags |= StateHint;
11616 f->output_data.x->wm_hints.initial_state = state;
11617
11618 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11619 #endif /* not USE_X_TOOLKIT */
11620 }
11621
11622 void
11623 x_wm_set_icon_pixmap (f, pixmap_id)
11624 struct frame *f;
11625 int pixmap_id;
11626 {
11627 Pixmap icon_pixmap;
11628
11629 #ifndef USE_X_TOOLKIT
11630 Window window = FRAME_X_WINDOW (f);
11631 #endif
11632
11633 if (pixmap_id > 0)
11634 {
11635 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
11636 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
11637 }
11638 else
11639 {
11640 /* It seems there is no way to turn off use of an icon pixmap.
11641 The following line does it, only if no icon has yet been created,
11642 for some window managers. But with mwm it crashes.
11643 Some people say it should clear the IconPixmapHint bit in this case,
11644 but that doesn't work, and the X consortium said it isn't the
11645 right thing at all. Since there is no way to win,
11646 best to explicitly give up. */
11647 #if 0
11648 f->output_data.x->wm_hints.icon_pixmap = None;
11649 #else
11650 return;
11651 #endif
11652 }
11653
11654 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11655
11656 {
11657 Arg al[1];
11658 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
11659 XtSetValues (f->output_data.x->widget, al, 1);
11660 }
11661
11662 #else /* not USE_X_TOOLKIT */
11663
11664 f->output_data.x->wm_hints.flags |= IconPixmapHint;
11665 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11666
11667 #endif /* not USE_X_TOOLKIT */
11668 }
11669
11670 void
11671 x_wm_set_icon_position (f, icon_x, icon_y)
11672 struct frame *f;
11673 int icon_x, icon_y;
11674 {
11675 #ifdef USE_X_TOOLKIT
11676 Window window = XtWindow (f->output_data.x->widget);
11677 #else
11678 Window window = FRAME_X_WINDOW (f);
11679 #endif
11680
11681 f->output_data.x->wm_hints.flags |= IconPositionHint;
11682 f->output_data.x->wm_hints.icon_x = icon_x;
11683 f->output_data.x->wm_hints.icon_y = icon_y;
11684
11685 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
11686 }
11687
11688 \f
11689 /***********************************************************************
11690 Fonts
11691 ***********************************************************************/
11692
11693 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
11694
11695 struct font_info *
11696 x_get_font_info (f, font_idx)
11697 FRAME_PTR f;
11698 int font_idx;
11699 {
11700 return (FRAME_X_FONT_TABLE (f) + font_idx);
11701 }
11702
11703
11704 /* Return a list of names of available fonts matching PATTERN on frame
11705 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11706 to be listed. Frame F NULL means we have not yet created any
11707 frame on X, and consult the first display in x_display_list.
11708 MAXNAMES sets a limit on how many fonts to match. */
11709
11710 Lisp_Object
11711 x_list_fonts (f, pattern, size, maxnames)
11712 FRAME_PTR f;
11713 Lisp_Object pattern;
11714 int size;
11715 int maxnames;
11716 {
11717 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
11718 Lisp_Object tem, second_best;
11719 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
11720 int try_XLoadQueryFont = 0;
11721 int count;
11722
11723 patterns = Fassoc (pattern, Valternate_fontname_alist);
11724 if (NILP (patterns))
11725 patterns = Fcons (pattern, Qnil);
11726
11727 if (maxnames == 1 && !size)
11728 /* We can return any single font matching PATTERN. */
11729 try_XLoadQueryFont = 1;
11730
11731 for (; CONSP (patterns); patterns = XCDR (patterns))
11732 {
11733 int num_fonts;
11734 char **names;
11735
11736 pattern = XCAR (patterns);
11737 /* See if we cached the result for this particular query.
11738 The cache is an alist of the form:
11739 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11740 */
11741 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
11742 key = Fcons (pattern, make_number (maxnames)),
11743 !NILP (list = Fassoc (key, tem))))
11744 {
11745 list = Fcdr_safe (list);
11746 /* We have a cashed list. Don't have to get the list again. */
11747 goto label_cached;
11748 }
11749
11750 /* At first, put PATTERN in the cache. */
11751
11752 BLOCK_INPUT;
11753 count = x_catch_errors (dpy);
11754
11755 if (try_XLoadQueryFont)
11756 {
11757 XFontStruct *font;
11758 unsigned long value;
11759
11760 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
11761 if (x_had_errors_p (dpy))
11762 {
11763 /* This error is perhaps due to insufficient memory on X
11764 server. Let's just ignore it. */
11765 font = NULL;
11766 x_clear_errors (dpy);
11767 }
11768
11769 if (font
11770 && XGetFontProperty (font, XA_FONT, &value))
11771 {
11772 char *name = (char *) XGetAtomName (dpy, (Atom) value);
11773 int len = strlen (name);
11774 char *tmp;
11775
11776 /* If DXPC (a Differential X Protocol Compressor)
11777 Ver.3.7 is running, XGetAtomName will return null
11778 string. We must avoid such a name. */
11779 if (len == 0)
11780 try_XLoadQueryFont = 0;
11781 else
11782 {
11783 num_fonts = 1;
11784 names = (char **) alloca (sizeof (char *));
11785 /* Some systems only allow alloca assigned to a
11786 simple var. */
11787 tmp = (char *) alloca (len + 1); names[0] = tmp;
11788 bcopy (name, names[0], len + 1);
11789 XFree (name);
11790 }
11791 }
11792 else
11793 try_XLoadQueryFont = 0;
11794
11795 if (font)
11796 XFreeFont (dpy, font);
11797 }
11798
11799 if (!try_XLoadQueryFont)
11800 {
11801 /* We try at least 10 fonts because XListFonts will return
11802 auto-scaled fonts at the head. */
11803 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
11804 &num_fonts);
11805 if (x_had_errors_p (dpy))
11806 {
11807 /* This error is perhaps due to insufficient memory on X
11808 server. Let's just ignore it. */
11809 names = NULL;
11810 x_clear_errors (dpy);
11811 }
11812 }
11813
11814 x_uncatch_errors (dpy, count);
11815 UNBLOCK_INPUT;
11816
11817 if (names)
11818 {
11819 int i;
11820
11821 /* Make a list of all the fonts we got back.
11822 Store that in the font cache for the display. */
11823 for (i = 0; i < num_fonts; i++)
11824 {
11825 int width = 0;
11826 char *p = names[i];
11827 int average_width = -1, dashes = 0;
11828
11829 /* Count the number of dashes in NAMES[I]. If there are
11830 14 dashes, and the field value following 12th dash
11831 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
11832 is usually too ugly to be used for editing. Let's
11833 ignore it. */
11834 while (*p)
11835 if (*p++ == '-')
11836 {
11837 dashes++;
11838 if (dashes == 7) /* PIXEL_SIZE field */
11839 width = atoi (p);
11840 else if (dashes == 12) /* AVERAGE_WIDTH field */
11841 average_width = atoi (p);
11842 }
11843 if (dashes < 14 || average_width != 0)
11844 {
11845 tem = build_string (names[i]);
11846 if (NILP (Fassoc (tem, list)))
11847 {
11848 if (STRINGP (Vx_pixel_size_width_font_regexp)
11849 && ((fast_c_string_match_ignore_case
11850 (Vx_pixel_size_width_font_regexp, names[i]))
11851 >= 0))
11852 /* We can set the value of PIXEL_SIZE to the
11853 width of this font. */
11854 list = Fcons (Fcons (tem, make_number (width)), list);
11855 else
11856 /* For the moment, width is not known. */
11857 list = Fcons (Fcons (tem, Qnil), list);
11858 }
11859 }
11860 }
11861 if (!try_XLoadQueryFont)
11862 XFreeFontNames (names);
11863 }
11864
11865 /* Now store the result in the cache. */
11866 if (f != NULL)
11867 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
11868 = Fcons (Fcons (key, list),
11869 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
11870
11871 label_cached:
11872 if (NILP (list)) continue; /* Try the remaining alternatives. */
11873
11874 newlist = second_best = Qnil;
11875 /* Make a list of the fonts that have the right width. */
11876 for (; CONSP (list); list = XCDR (list))
11877 {
11878 int found_size;
11879
11880 tem = XCAR (list);
11881
11882 if (!CONSP (tem) || NILP (XCAR (tem)))
11883 continue;
11884 if (!size)
11885 {
11886 newlist = Fcons (XCAR (tem), newlist);
11887 continue;
11888 }
11889
11890 if (!INTEGERP (XCDR (tem)))
11891 {
11892 /* Since we have not yet known the size of this font, we
11893 must try slow function call XLoadQueryFont. */
11894 XFontStruct *thisinfo;
11895
11896 BLOCK_INPUT;
11897 count = x_catch_errors (dpy);
11898 thisinfo = XLoadQueryFont (dpy,
11899 XSTRING (XCAR (tem))->data);
11900 if (x_had_errors_p (dpy))
11901 {
11902 /* This error is perhaps due to insufficient memory on X
11903 server. Let's just ignore it. */
11904 thisinfo = NULL;
11905 x_clear_errors (dpy);
11906 }
11907 x_uncatch_errors (dpy, count);
11908 UNBLOCK_INPUT;
11909
11910 if (thisinfo)
11911 {
11912 XCDR (tem)
11913 = (thisinfo->min_bounds.width == 0
11914 ? make_number (0)
11915 : make_number (thisinfo->max_bounds.width));
11916 XFreeFont (dpy, thisinfo);
11917 }
11918 else
11919 /* For unknown reason, the previous call of XListFont had
11920 returned a font which can't be opened. Record the size
11921 as 0 not to try to open it again. */
11922 XCDR (tem) = make_number (0);
11923 }
11924
11925 found_size = XINT (XCDR (tem));
11926 if (found_size == size)
11927 newlist = Fcons (XCAR (tem), newlist);
11928 else if (found_size > 0)
11929 {
11930 if (NILP (second_best))
11931 second_best = tem;
11932 else if (found_size < size)
11933 {
11934 if (XINT (XCDR (second_best)) > size
11935 || XINT (XCDR (second_best)) < found_size)
11936 second_best = tem;
11937 }
11938 else
11939 {
11940 if (XINT (XCDR (second_best)) > size
11941 && XINT (XCDR (second_best)) > found_size)
11942 second_best = tem;
11943 }
11944 }
11945 }
11946 if (!NILP (newlist))
11947 break;
11948 else if (!NILP (second_best))
11949 {
11950 newlist = Fcons (XCAR (second_best), Qnil);
11951 break;
11952 }
11953 }
11954
11955 return newlist;
11956 }
11957
11958
11959 #if GLYPH_DEBUG
11960
11961 /* Check that FONT is valid on frame F. It is if it can be found in F's
11962 font table. */
11963
11964 static void
11965 x_check_font (f, font)
11966 struct frame *f;
11967 XFontStruct *font;
11968 {
11969 int i;
11970 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11971
11972 xassert (font != NULL);
11973
11974 for (i = 0; i < dpyinfo->n_fonts; i++)
11975 if (dpyinfo->font_table[i].name
11976 && font == dpyinfo->font_table[i].font)
11977 break;
11978
11979 xassert (i < dpyinfo->n_fonts);
11980 }
11981
11982 #endif /* GLYPH_DEBUG != 0 */
11983
11984 /* Set *W to the minimum width, *H to the minimum font height of FONT.
11985 Note: There are (broken) X fonts out there with invalid XFontStruct
11986 min_bounds contents. For example, handa@etl.go.jp reports that
11987 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
11988 have font->min_bounds.width == 0. */
11989
11990 static INLINE void
11991 x_font_min_bounds (font, w, h)
11992 XFontStruct *font;
11993 int *w, *h;
11994 {
11995 *h = FONT_HEIGHT (font);
11996 *w = font->min_bounds.width;
11997
11998 /* Try to handle the case where FONT->min_bounds has invalid
11999 contents. Since the only font known to have invalid min_bounds
12000 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12001 if (*w <= 0)
12002 *w = font->max_bounds.width;
12003 }
12004
12005
12006 /* Compute the smallest character width and smallest font height over
12007 all fonts available on frame F. Set the members smallest_char_width
12008 and smallest_font_height in F's x_display_info structure to
12009 the values computed. Value is non-zero if smallest_font_height or
12010 smallest_char_width become smaller than they were before. */
12011
12012 static int
12013 x_compute_min_glyph_bounds (f)
12014 struct frame *f;
12015 {
12016 int i;
12017 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12018 XFontStruct *font;
12019 int old_width = dpyinfo->smallest_char_width;
12020 int old_height = dpyinfo->smallest_font_height;
12021
12022 dpyinfo->smallest_font_height = 100000;
12023 dpyinfo->smallest_char_width = 100000;
12024
12025 for (i = 0; i < dpyinfo->n_fonts; ++i)
12026 if (dpyinfo->font_table[i].name)
12027 {
12028 struct font_info *fontp = dpyinfo->font_table + i;
12029 int w, h;
12030
12031 font = (XFontStruct *) fontp->font;
12032 xassert (font != (XFontStruct *) ~0);
12033 x_font_min_bounds (font, &w, &h);
12034
12035 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12036 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12037 }
12038
12039 xassert (dpyinfo->smallest_char_width > 0
12040 && dpyinfo->smallest_font_height > 0);
12041
12042 return (dpyinfo->n_fonts == 1
12043 || dpyinfo->smallest_char_width < old_width
12044 || dpyinfo->smallest_font_height < old_height);
12045 }
12046
12047
12048 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12049 pointer to the structure font_info while allocating it dynamically.
12050 If SIZE is 0, load any size of font.
12051 If loading is failed, return NULL. */
12052
12053 struct font_info *
12054 x_load_font (f, fontname, size)
12055 struct frame *f;
12056 register char *fontname;
12057 int size;
12058 {
12059 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12060 Lisp_Object font_names;
12061 int count;
12062
12063 /* Get a list of all the fonts that match this name. Once we
12064 have a list of matching fonts, we compare them against the fonts
12065 we already have by comparing names. */
12066 font_names = x_list_fonts (f, build_string (fontname), size, 1);
12067
12068 if (!NILP (font_names))
12069 {
12070 Lisp_Object tail;
12071 int i;
12072
12073 for (i = 0; i < dpyinfo->n_fonts; i++)
12074 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
12075 if (dpyinfo->font_table[i].name
12076 && (!strcmp (dpyinfo->font_table[i].name,
12077 XSTRING (XCAR (tail))->data)
12078 || !strcmp (dpyinfo->font_table[i].full_name,
12079 XSTRING (XCAR (tail))->data)))
12080 return (dpyinfo->font_table + i);
12081 }
12082
12083 /* Load the font and add it to the table. */
12084 {
12085 char *full_name;
12086 XFontStruct *font;
12087 struct font_info *fontp;
12088 unsigned long value;
12089 int i;
12090
12091 /* If we have found fonts by x_list_font, load one of them. If
12092 not, we still try to load a font by the name given as FONTNAME
12093 because XListFonts (called in x_list_font) of some X server has
12094 a bug of not finding a font even if the font surely exists and
12095 is loadable by XLoadQueryFont. */
12096 if (size > 0 && !NILP (font_names))
12097 fontname = (char *) XSTRING (XCAR (font_names))->data;
12098
12099 BLOCK_INPUT;
12100 count = x_catch_errors (FRAME_X_DISPLAY (f));
12101 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
12102 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12103 {
12104 /* This error is perhaps due to insufficient memory on X
12105 server. Let's just ignore it. */
12106 font = NULL;
12107 x_clear_errors (FRAME_X_DISPLAY (f));
12108 }
12109 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12110 UNBLOCK_INPUT;
12111 if (!font)
12112 return NULL;
12113
12114 /* Find a free slot in the font table. */
12115 for (i = 0; i < dpyinfo->n_fonts; ++i)
12116 if (dpyinfo->font_table[i].name == NULL)
12117 break;
12118
12119 /* If no free slot found, maybe enlarge the font table. */
12120 if (i == dpyinfo->n_fonts
12121 && dpyinfo->n_fonts == dpyinfo->font_table_size)
12122 {
12123 int sz;
12124 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12125 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
12126 dpyinfo->font_table
12127 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
12128 }
12129
12130 fontp = dpyinfo->font_table + i;
12131 if (i == dpyinfo->n_fonts)
12132 ++dpyinfo->n_fonts;
12133
12134 /* Now fill in the slots of *FONTP. */
12135 BLOCK_INPUT;
12136 fontp->font = font;
12137 fontp->font_idx = i;
12138 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12139 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12140
12141 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12142 full_name = 0;
12143 if (XGetFontProperty (font, XA_FONT, &value))
12144 {
12145 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12146 char *p = name;
12147 int dashes = 0;
12148
12149 /* Count the number of dashes in the "full name".
12150 If it is too few, this isn't really the font's full name,
12151 so don't use it.
12152 In X11R4, the fonts did not come with their canonical names
12153 stored in them. */
12154 while (*p)
12155 {
12156 if (*p == '-')
12157 dashes++;
12158 p++;
12159 }
12160
12161 if (dashes >= 13)
12162 {
12163 full_name = (char *) xmalloc (p - name + 1);
12164 bcopy (name, full_name, p - name + 1);
12165 }
12166
12167 XFree (name);
12168 }
12169
12170 if (full_name != 0)
12171 fontp->full_name = full_name;
12172 else
12173 fontp->full_name = fontp->name;
12174
12175 fontp->size = font->max_bounds.width;
12176 fontp->height = FONT_HEIGHT (font);
12177 {
12178 /* For some font, ascent and descent in max_bounds field is
12179 larger than the above value. */
12180 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12181 if (max_height > fontp->height)
12182 fontp->height = max_height;
12183 }
12184
12185 if (NILP (font_names))
12186 {
12187 /* We come here because of a bug of XListFonts mentioned at
12188 the head of this block. Let's store this information in
12189 the cache for x_list_fonts. */
12190 Lisp_Object lispy_name = build_string (fontname);
12191 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12192
12193 XCDR (dpyinfo->name_list_element)
12194 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12195 Fcons (Fcons (lispy_full_name,
12196 make_number (fontp->size)),
12197 Qnil)),
12198 XCDR (dpyinfo->name_list_element));
12199 if (full_name)
12200 XCDR (dpyinfo->name_list_element)
12201 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12202 Fcons (Fcons (lispy_full_name,
12203 make_number (fontp->size)),
12204 Qnil)),
12205 XCDR (dpyinfo->name_list_element));
12206 }
12207
12208 /* The slot `encoding' specifies how to map a character
12209 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12210 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
12211 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12212 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12213 2:0xA020..0xFF7F). For the moment, we don't know which charset
12214 uses this font. So, we set information in fontp->encoding[1]
12215 which is never used by any charset. If mapping can't be
12216 decided, set FONT_ENCODING_NOT_DECIDED. */
12217 fontp->encoding[1]
12218 = (font->max_byte1 == 0
12219 /* 1-byte font */
12220 ? (font->min_char_or_byte2 < 0x80
12221 ? (font->max_char_or_byte2 < 0x80
12222 ? 0 /* 0x20..0x7F */
12223 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
12224 : 1) /* 0xA0..0xFF */
12225 /* 2-byte font */
12226 : (font->min_byte1 < 0x80
12227 ? (font->max_byte1 < 0x80
12228 ? (font->min_char_or_byte2 < 0x80
12229 ? (font->max_char_or_byte2 < 0x80
12230 ? 0 /* 0x2020..0x7F7F */
12231 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
12232 : 3) /* 0x20A0..0x7FFF */
12233 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
12234 : (font->min_char_or_byte2 < 0x80
12235 ? (font->max_char_or_byte2 < 0x80
12236 ? 2 /* 0xA020..0xFF7F */
12237 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
12238 : 1))); /* 0xA0A0..0xFFFF */
12239
12240 fontp->baseline_offset
12241 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12242 ? (long) value : 0);
12243 fontp->relative_compose
12244 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12245 ? (long) value : 0);
12246 fontp->default_ascent
12247 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12248 ? (long) value : 0);
12249
12250 /* Set global flag fonts_changed_p to non-zero if the font loaded
12251 has a character with a smaller width than any other character
12252 before, or if the font loaded has a smalle>r height than any
12253 other font loaded before. If this happens, it will make a
12254 glyph matrix reallocation necessary. */
12255 fonts_changed_p = x_compute_min_glyph_bounds (f);
12256 UNBLOCK_INPUT;
12257 return fontp;
12258 }
12259 }
12260
12261
12262 /* Return a pointer to struct font_info of a font named FONTNAME for
12263 frame F. If no such font is loaded, return NULL. */
12264
12265 struct font_info *
12266 x_query_font (f, fontname)
12267 struct frame *f;
12268 register char *fontname;
12269 {
12270 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12271 int i;
12272
12273 for (i = 0; i < dpyinfo->n_fonts; i++)
12274 if (dpyinfo->font_table[i].name
12275 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12276 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
12277 return (dpyinfo->font_table + i);
12278 return NULL;
12279 }
12280
12281
12282 /* Find a CCL program for a font specified by FONTP, and set the member
12283 `encoder' of the structure. */
12284
12285 void
12286 x_find_ccl_program (fontp)
12287 struct font_info *fontp;
12288 {
12289 Lisp_Object list, elt;
12290
12291 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
12292 {
12293 elt = XCAR (list);
12294 if (CONSP (elt)
12295 && STRINGP (XCAR (elt))
12296 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
12297 >= 0))
12298 break;
12299 }
12300 if (! NILP (list))
12301 {
12302 struct ccl_program *ccl
12303 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
12304
12305 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
12306 xfree (ccl);
12307 else
12308 fontp->font_encoder = ccl;
12309 }
12310 }
12311
12312
12313 \f
12314 /***********************************************************************
12315 Initialization
12316 ***********************************************************************/
12317
12318 #ifdef USE_X_TOOLKIT
12319 static XrmOptionDescRec emacs_options[] = {
12320 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12321 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12322
12323 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12324 XrmoptionSepArg, NULL},
12325 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12326
12327 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12328 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12329 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12330 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12331 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12332 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12333 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12334 };
12335 #endif /* USE_X_TOOLKIT */
12336
12337 static int x_initialized;
12338
12339 #ifdef MULTI_KBOARD
12340 /* Test whether two display-name strings agree up to the dot that separates
12341 the screen number from the server number. */
12342 static int
12343 same_x_server (name1, name2)
12344 char *name1, *name2;
12345 {
12346 int seen_colon = 0;
12347 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12348 int system_name_length = strlen (system_name);
12349 int length_until_period = 0;
12350
12351 while (system_name[length_until_period] != 0
12352 && system_name[length_until_period] != '.')
12353 length_until_period++;
12354
12355 /* Treat `unix' like an empty host name. */
12356 if (! strncmp (name1, "unix:", 5))
12357 name1 += 4;
12358 if (! strncmp (name2, "unix:", 5))
12359 name2 += 4;
12360 /* Treat this host's name like an empty host name. */
12361 if (! strncmp (name1, system_name, system_name_length)
12362 && name1[system_name_length] == ':')
12363 name1 += system_name_length;
12364 if (! strncmp (name2, system_name, system_name_length)
12365 && name2[system_name_length] == ':')
12366 name2 += system_name_length;
12367 /* Treat this host's domainless name like an empty host name. */
12368 if (! strncmp (name1, system_name, length_until_period)
12369 && name1[length_until_period] == ':')
12370 name1 += length_until_period;
12371 if (! strncmp (name2, system_name, length_until_period)
12372 && name2[length_until_period] == ':')
12373 name2 += length_until_period;
12374
12375 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12376 {
12377 if (*name1 == ':')
12378 seen_colon++;
12379 if (seen_colon && *name1 == '.')
12380 return 1;
12381 }
12382 return (seen_colon
12383 && (*name1 == '.' || *name1 == '\0')
12384 && (*name2 == '.' || *name2 == '\0'));
12385 }
12386 #endif
12387
12388 struct x_display_info *
12389 x_term_init (display_name, xrm_option, resource_name)
12390 Lisp_Object display_name;
12391 char *xrm_option;
12392 char *resource_name;
12393 {
12394 int connection;
12395 Display *dpy;
12396 struct x_display_info *dpyinfo;
12397 XrmDatabase xrdb;
12398
12399 BLOCK_INPUT;
12400
12401 if (!x_initialized)
12402 {
12403 x_initialize ();
12404 x_initialized = 1;
12405 }
12406
12407 #ifdef USE_X_TOOLKIT
12408 /* weiner@footloose.sps.mot.com reports that this causes
12409 errors with X11R5:
12410 X protocol error: BadAtom (invalid Atom parameter)
12411 on protocol request 18skiloaf.
12412 So let's not use it until R6. */
12413 #ifdef HAVE_X11XTR6
12414 XtSetLanguageProc (NULL, NULL, NULL);
12415 #endif
12416
12417 {
12418 int argc = 0;
12419 char *argv[3];
12420
12421 argv[0] = "";
12422 argc = 1;
12423 if (xrm_option)
12424 {
12425 argv[argc++] = "-xrm";
12426 argv[argc++] = xrm_option;
12427 }
12428 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12429 resource_name, EMACS_CLASS,
12430 emacs_options, XtNumber (emacs_options),
12431 &argc, argv);
12432
12433 #ifdef HAVE_X11XTR6
12434 /* I think this is to compensate for XtSetLanguageProc. */
12435 fixup_locale ();
12436 #endif
12437 }
12438
12439 #else /* not USE_X_TOOLKIT */
12440 #ifdef HAVE_X11R5
12441 XSetLocaleModifiers ("");
12442 #endif
12443 dpy = XOpenDisplay (XSTRING (display_name)->data);
12444 #endif /* not USE_X_TOOLKIT */
12445
12446 /* Detect failure. */
12447 if (dpy == 0)
12448 {
12449 UNBLOCK_INPUT;
12450 return 0;
12451 }
12452
12453 /* We have definitely succeeded. Record the new connection. */
12454
12455 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
12456
12457 #ifdef MULTI_KBOARD
12458 {
12459 struct x_display_info *share;
12460 Lisp_Object tail;
12461
12462 for (share = x_display_list, tail = x_display_name_list; share;
12463 share = share->next, tail = XCDR (tail))
12464 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
12465 XSTRING (display_name)->data))
12466 break;
12467 if (share)
12468 dpyinfo->kboard = share->kboard;
12469 else
12470 {
12471 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12472 init_kboard (dpyinfo->kboard);
12473 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12474 {
12475 char *vendor = ServerVendor (dpy);
12476 dpyinfo->kboard->Vsystem_key_alist
12477 = call1 (Qvendor_specific_keysyms,
12478 build_string (vendor ? vendor : ""));
12479 }
12480
12481 dpyinfo->kboard->next_kboard = all_kboards;
12482 all_kboards = dpyinfo->kboard;
12483 /* Don't let the initial kboard remain current longer than necessary.
12484 That would cause problems if a file loaded on startup tries to
12485 prompt in the mini-buffer. */
12486 if (current_kboard == initial_kboard)
12487 current_kboard = dpyinfo->kboard;
12488 }
12489 dpyinfo->kboard->reference_count++;
12490 }
12491 #endif
12492
12493 /* Put this display on the chain. */
12494 dpyinfo->next = x_display_list;
12495 x_display_list = dpyinfo;
12496
12497 /* Put it on x_display_name_list as well, to keep them parallel. */
12498 x_display_name_list = Fcons (Fcons (display_name, Qnil),
12499 x_display_name_list);
12500 dpyinfo->name_list_element = XCAR (x_display_name_list);
12501
12502 dpyinfo->display = dpy;
12503
12504 #if 0
12505 XSetAfterFunction (x_current_display, x_trace_wire);
12506 #endif /* ! 0 */
12507
12508 dpyinfo->x_id_name
12509 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
12510 + STRING_BYTES (XSTRING (Vsystem_name))
12511 + 2);
12512 sprintf (dpyinfo->x_id_name, "%s@%s",
12513 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
12514
12515 /* Figure out which modifier bits mean what. */
12516 x_find_modifier_meanings (dpyinfo);
12517
12518 /* Get the scroll bar cursor. */
12519 dpyinfo->vertical_scroll_bar_cursor
12520 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
12521
12522 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12523 resource_name, EMACS_CLASS);
12524 #ifdef HAVE_XRMSETDATABASE
12525 XrmSetDatabase (dpyinfo->display, xrdb);
12526 #else
12527 dpyinfo->display->db = xrdb;
12528 #endif
12529 /* Put the rdb where we can find it in a way that works on
12530 all versions. */
12531 dpyinfo->xrdb = xrdb;
12532
12533 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12534 DefaultScreen (dpyinfo->display));
12535 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
12536 &dpyinfo->n_planes);
12537 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
12538 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
12539 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12540 dpyinfo->grabbed = 0;
12541 dpyinfo->reference_count = 0;
12542 dpyinfo->icon_bitmap_id = -1;
12543 dpyinfo->font_table = NULL;
12544 dpyinfo->n_fonts = 0;
12545 dpyinfo->font_table_size = 0;
12546 dpyinfo->bitmaps = 0;
12547 dpyinfo->bitmaps_size = 0;
12548 dpyinfo->bitmaps_last = 0;
12549 dpyinfo->scratch_cursor_gc = 0;
12550 dpyinfo->mouse_face_mouse_frame = 0;
12551 dpyinfo->mouse_face_deferred_gc = 0;
12552 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12553 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
12554 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
12555 dpyinfo->mouse_face_window = Qnil;
12556 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
12557 dpyinfo->mouse_face_defer = 0;
12558 dpyinfo->x_focus_frame = 0;
12559 dpyinfo->x_focus_event_frame = 0;
12560 dpyinfo->x_highlight_frame = 0;
12561 dpyinfo->image_cache = make_image_cache ();
12562
12563 {
12564 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
12565 double pixels = DisplayHeight (dpyinfo->display, screen_number);
12566 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
12567 dpyinfo->resy = pixels * 25.4 / mm;
12568 pixels = DisplayWidth (dpyinfo->display, screen_number);
12569 mm = DisplayWidthMM (dpyinfo->display, screen_number);
12570 dpyinfo->resx = pixels * 25.4 / mm;
12571 }
12572
12573 dpyinfo->Xatom_wm_protocols
12574 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
12575 dpyinfo->Xatom_wm_take_focus
12576 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
12577 dpyinfo->Xatom_wm_save_yourself
12578 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
12579 dpyinfo->Xatom_wm_delete_window
12580 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
12581 dpyinfo->Xatom_wm_change_state
12582 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
12583 dpyinfo->Xatom_wm_configure_denied
12584 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
12585 dpyinfo->Xatom_wm_window_moved
12586 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
12587 dpyinfo->Xatom_editres
12588 = XInternAtom (dpyinfo->display, "Editres", False);
12589 dpyinfo->Xatom_CLIPBOARD
12590 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
12591 dpyinfo->Xatom_TIMESTAMP
12592 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
12593 dpyinfo->Xatom_TEXT
12594 = XInternAtom (dpyinfo->display, "TEXT", False);
12595 dpyinfo->Xatom_COMPOUND_TEXT
12596 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
12597 dpyinfo->Xatom_DELETE
12598 = XInternAtom (dpyinfo->display, "DELETE", False);
12599 dpyinfo->Xatom_MULTIPLE
12600 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
12601 dpyinfo->Xatom_INCR
12602 = XInternAtom (dpyinfo->display, "INCR", False);
12603 dpyinfo->Xatom_EMACS_TMP
12604 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
12605 dpyinfo->Xatom_TARGETS
12606 = XInternAtom (dpyinfo->display, "TARGETS", False);
12607 dpyinfo->Xatom_NULL
12608 = XInternAtom (dpyinfo->display, "NULL", False);
12609 dpyinfo->Xatom_ATOM_PAIR
12610 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
12611 /* For properties of font. */
12612 dpyinfo->Xatom_PIXEL_SIZE
12613 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
12614 dpyinfo->Xatom_MULE_BASELINE_OFFSET
12615 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
12616 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
12617 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
12618 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
12619 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
12620
12621 /* Ghostscript support. */
12622 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
12623 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
12624
12625 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
12626 False);
12627
12628 dpyinfo->cut_buffers_initialized = 0;
12629
12630 connection = ConnectionNumber (dpyinfo->display);
12631 dpyinfo->connection = connection;
12632
12633 {
12634 char null_bits[1];
12635
12636 null_bits[0] = 0x00;
12637
12638 dpyinfo->null_pixel
12639 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12640 null_bits, 1, 1, (long) 0, (long) 0,
12641 1);
12642 }
12643
12644 {
12645 extern int gray_bitmap_width, gray_bitmap_height;
12646 extern unsigned char *gray_bitmap_bits;
12647 dpyinfo->gray
12648 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12649 gray_bitmap_bits,
12650 gray_bitmap_width, gray_bitmap_height,
12651 (unsigned long) 1, (unsigned long) 0, 1);
12652 }
12653
12654 #ifdef subprocesses
12655 /* This is only needed for distinguishing keyboard and process input. */
12656 if (connection != 0)
12657 add_keyboard_wait_descriptor (connection);
12658 #endif
12659
12660 #ifndef F_SETOWN_BUG
12661 #ifdef F_SETOWN
12662 #ifdef F_SETOWN_SOCK_NEG
12663 /* stdin is a socket here */
12664 fcntl (connection, F_SETOWN, -getpid ());
12665 #else /* ! defined (F_SETOWN_SOCK_NEG) */
12666 fcntl (connection, F_SETOWN, getpid ());
12667 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
12668 #endif /* ! defined (F_SETOWN) */
12669 #endif /* F_SETOWN_BUG */
12670
12671 #ifdef SIGIO
12672 if (interrupt_input)
12673 init_sigio (connection);
12674 #endif /* ! defined (SIGIO) */
12675
12676 #ifdef USE_LUCID
12677 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
12678 /* Make sure that we have a valid font for dialog boxes
12679 so that Xt does not crash. */
12680 {
12681 Display *dpy = dpyinfo->display;
12682 XrmValue d, fr, to;
12683 Font font;
12684 int count;
12685
12686 d.addr = (XPointer)&dpy;
12687 d.size = sizeof (Display *);
12688 fr.addr = XtDefaultFont;
12689 fr.size = sizeof (XtDefaultFont);
12690 to.size = sizeof (Font *);
12691 to.addr = (XPointer)&font;
12692 count = x_catch_errors (dpy);
12693 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
12694 abort ();
12695 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
12696 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
12697 x_uncatch_errors (dpy, count);
12698 }
12699 #endif
12700 #endif
12701
12702 UNBLOCK_INPUT;
12703
12704 return dpyinfo;
12705 }
12706 \f
12707 /* Get rid of display DPYINFO, assuming all frames are already gone,
12708 and without sending any more commands to the X server. */
12709
12710 void
12711 x_delete_display (dpyinfo)
12712 struct x_display_info *dpyinfo;
12713 {
12714 delete_keyboard_wait_descriptor (dpyinfo->connection);
12715
12716 /* Discard this display from x_display_name_list and x_display_list.
12717 We can't use Fdelq because that can quit. */
12718 if (! NILP (x_display_name_list)
12719 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
12720 x_display_name_list = XCDR (x_display_name_list);
12721 else
12722 {
12723 Lisp_Object tail;
12724
12725 tail = x_display_name_list;
12726 while (CONSP (tail) && CONSP (XCDR (tail)))
12727 {
12728 if (EQ (XCAR (XCDR (tail)),
12729 dpyinfo->name_list_element))
12730 {
12731 XCDR (tail) = XCDR (XCDR (tail));
12732 break;
12733 }
12734 tail = XCDR (tail);
12735 }
12736 }
12737
12738 if (x_display_list == dpyinfo)
12739 x_display_list = dpyinfo->next;
12740 else
12741 {
12742 struct x_display_info *tail;
12743
12744 for (tail = x_display_list; tail; tail = tail->next)
12745 if (tail->next == dpyinfo)
12746 tail->next = tail->next->next;
12747 }
12748
12749 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12750 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
12751 XrmDestroyDatabase (dpyinfo->xrdb);
12752 #endif
12753 #endif
12754 #ifdef MULTI_KBOARD
12755 if (--dpyinfo->kboard->reference_count == 0)
12756 delete_kboard (dpyinfo->kboard);
12757 #endif
12758 xfree (dpyinfo->font_table);
12759 xfree (dpyinfo->x_id_name);
12760 xfree (dpyinfo);
12761 }
12762 \f
12763 /* Set up use of X before we make the first connection. */
12764
12765 static struct redisplay_interface x_redisplay_interface =
12766 {
12767 x_produce_glyphs,
12768 x_write_glyphs,
12769 x_insert_glyphs,
12770 x_clear_end_of_line,
12771 x_scroll_run,
12772 x_after_update_window_line,
12773 x_update_window_begin,
12774 x_update_window_end,
12775 XTcursor_to,
12776 x_flush,
12777 x_get_glyph_overhangs,
12778 x_fix_overlapping_area
12779 };
12780
12781 void
12782 x_initialize ()
12783 {
12784 rif = &x_redisplay_interface;
12785
12786 clear_frame_hook = x_clear_frame;
12787 ins_del_lines_hook = x_ins_del_lines;
12788 change_line_highlight_hook = x_change_line_highlight;
12789 delete_glyphs_hook = x_delete_glyphs;
12790 ring_bell_hook = XTring_bell;
12791 reset_terminal_modes_hook = XTreset_terminal_modes;
12792 set_terminal_modes_hook = XTset_terminal_modes;
12793 update_begin_hook = x_update_begin;
12794 update_end_hook = x_update_end;
12795 set_terminal_window_hook = XTset_terminal_window;
12796 read_socket_hook = XTread_socket;
12797 frame_up_to_date_hook = XTframe_up_to_date;
12798 reassert_line_highlight_hook = XTreassert_line_highlight;
12799 mouse_position_hook = XTmouse_position;
12800 frame_rehighlight_hook = XTframe_rehighlight;
12801 frame_raise_lower_hook = XTframe_raise_lower;
12802 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12803 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12804 redeem_scroll_bar_hook = XTredeem_scroll_bar;
12805 judge_scroll_bars_hook = XTjudge_scroll_bars;
12806 estimate_mode_line_height_hook = x_estimate_mode_line_height;
12807
12808 scroll_region_ok = 1; /* we'll scroll partial frames */
12809 char_ins_del_ok = 0; /* just as fast to write the line */
12810 line_ins_del_ok = 1; /* we'll just blt 'em */
12811 fast_clear_end_of_line = 1; /* X does this well */
12812 memory_below_frame = 0; /* we don't remember what scrolls
12813 off the bottom */
12814 baud_rate = 19200;
12815
12816 x_noop_count = 0;
12817 last_tool_bar_item = -1;
12818 any_help_event_p = 0;
12819
12820 /* Try to use interrupt input; if we can't, then start polling. */
12821 Fset_input_mode (Qt, Qnil, Qt, Qnil);
12822
12823 #ifdef USE_X_TOOLKIT
12824 XtToolkitInitialize ();
12825 Xt_app_con = XtCreateApplicationContext ();
12826 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
12827 #endif
12828
12829 /* Note that there is no real way portable across R3/R4 to get the
12830 original error handler. */
12831 XSetErrorHandler (x_error_handler);
12832 XSetIOErrorHandler (x_io_error_quitter);
12833
12834 /* Disable Window Change signals; they are handled by X events. */
12835 #ifdef SIGWINCH
12836 signal (SIGWINCH, SIG_DFL);
12837 #endif /* ! defined (SIGWINCH) */
12838
12839 signal (SIGPIPE, x_connection_signal);
12840 }
12841
12842
12843 void
12844 syms_of_xterm ()
12845 {
12846 staticpro (&x_error_message_string);
12847 x_error_message_string = Qnil;
12848
12849 staticpro (&x_display_name_list);
12850 x_display_name_list = Qnil;
12851
12852 staticpro (&last_mouse_scroll_bar);
12853 last_mouse_scroll_bar = Qnil;
12854
12855 staticpro (&Qvendor_specific_keysyms);
12856 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
12857
12858 staticpro (&last_mouse_press_frame);
12859 last_mouse_press_frame = Qnil;
12860
12861 staticpro (&help_echo);
12862 help_echo = Qnil;
12863 staticpro (&previous_help_echo);
12864 previous_help_echo = Qnil;
12865
12866 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
12867 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
12868 For example, if a block cursor is over a tab, it will be drawn as\n\
12869 wide as that tab on the display.");
12870 x_stretch_cursor_p = 0;
12871
12872 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
12873 "If not nil, Emacs uses toolkit scroll bars.");
12874 #if USE_TOOLKIT_SCROLL_BARS
12875 x_toolkit_scroll_bars_p = 1;
12876 #else
12877 x_toolkit_scroll_bars_p = 0;
12878 #endif
12879
12880 defsubr (&Sxt_process_timeouts);
12881 staticpro (&last_mouse_motion_frame);
12882 last_mouse_motion_frame = Qnil;
12883 }
12884
12885 #endif /* not HAVE_X_WINDOWS */
12886