(x_update_window_begin): No need to turn off the mouse
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* New display code by Gerd Moellmann <gerd@gnu.org>. */
23 /* Xt features made by Fred Pierresteguy. */
24
25 #include <config.h>
26
27 /* On 4.3 these lose if they come after xterm.h. */
28 /* Putting these at the beginning seems to be standard for other .c files. */
29 #include <signal.h>
30
31 #include <stdio.h>
32
33 #ifdef HAVE_X_WINDOWS
34
35 #include "lisp.h"
36 #include "blockinput.h"
37
38 /* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40 #include "syssignal.h"
41
42 /* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44 #include "xterm.h"
45 #include <X11/cursorfont.h>
46
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52
53 #ifdef BSD_SYSTEM
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD_SYSTEM) */
56
57 #include "systty.h"
58 #include "systime.h"
59
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
69
70 #include "charset.h"
71 #include "ccl.h"
72 #include "frame.h"
73 #include "dispextern.h"
74 #include "fontset.h"
75 #include "termhooks.h"
76 #include "termopts.h"
77 #include "termchar.h"
78 #if 0
79 #include "sink.h"
80 #include "sinkmask.h"
81 #endif /* ! 0 */
82 #include "gnu.h"
83 #include "disptab.h"
84 #include "buffer.h"
85 #include "window.h"
86 #include "keyboard.h"
87 #include "intervals.h"
88 #include "process.h"
89 #include "atimer.h"
90
91 #ifdef USE_X_TOOLKIT
92 #include <X11/Shell.h>
93 #endif
94
95 #ifdef HAVE_SYS_TIME_H
96 #include <sys/time.h>
97 #endif
98 #ifdef HAVE_UNISTD_H
99 #include <unistd.h>
100 #endif
101
102 #ifdef USE_X_TOOLKIT
103
104 extern void free_frame_menubar ();
105 extern FRAME_PTR x_menubar_window_to_frame ();
106
107 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
108 #define HACK_EDITRES
109 extern void _XEditResCheckMessages ();
110 #endif /* not NO_EDITRES */
111
112 /* Include toolkit specific headers for the scroll bar widget. */
113
114 #ifdef USE_TOOLKIT_SCROLL_BARS
115 #if defined USE_MOTIF
116 #include <Xm/Xm.h> /* for LESSTIF_VERSION */
117 #include <Xm/ScrollBar.h>
118 #include <Xm/ScrollBarP.h>
119 #else /* !USE_MOTIF i.e. use Xaw */
120
121 #ifdef HAVE_XAW3D
122 #include <X11/Xaw3d/Simple.h>
123 #include <X11/Xaw3d/Scrollbar.h>
124 #define ARROW_SCROLLBAR
125 #include <X11/Xaw3d/ScrollbarP.h>
126 #else /* !HAVE_XAW3D */
127 #include <X11/Xaw/Simple.h>
128 #include <X11/Xaw/Scrollbar.h>
129 #endif /* !HAVE_XAW3D */
130 #ifndef XtNpickTop
131 #define XtNpickTop "pickTop"
132 #endif /* !XtNpickTop */
133 #endif /* !USE_MOTIF */
134 #endif /* USE_TOOLKIT_SCROLL_BARS */
135
136 #endif /* USE_X_TOOLKIT */
137
138 #ifndef USE_X_TOOLKIT
139 #define x_any_window_to_frame x_window_to_frame
140 #define x_top_window_to_frame x_window_to_frame
141 #endif
142
143 #ifdef USE_X_TOOLKIT
144 #include "widget.h"
145 #ifndef XtNinitialState
146 #define XtNinitialState "initialState"
147 #endif
148 #endif
149
150 #ifdef SOLARIS2
151 /* memmove will be defined as a macro in Xfuncs.h unless
152 <string.h> is included beforehand. The declaration for memmove in
153 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
154 #include <string.h>
155 #endif
156
157 #ifndef min
158 #define min(a,b) ((a) < (b) ? (a) : (b))
159 #endif
160 #ifndef max
161 #define max(a,b) ((a) > (b) ? (a) : (b))
162 #endif
163
164 #define abs(x) ((x) < 0 ? -(x) : (x))
165
166 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
167
168 \f
169 /* Bitmaps for truncated lines. */
170
171 enum bitmap_type
172 {
173 NO_BITMAP,
174 LEFT_TRUNCATION_BITMAP,
175 RIGHT_TRUNCATION_BITMAP,
176 OVERLAY_ARROW_BITMAP,
177 CONTINUED_LINE_BITMAP,
178 CONTINUATION_LINE_BITMAP,
179 ZV_LINE_BITMAP
180 };
181
182 /* Bitmap drawn to indicate lines not displaying text if
183 `indicate-empty-lines' is non-nil. */
184
185 #define zv_width 8
186 #define zv_height 8
187 static unsigned char zv_bits[] = {
188 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
189
190 /* An arrow like this: `<-'. */
191
192 #define left_width 8
193 #define left_height 8
194 static unsigned char left_bits[] = {
195 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
196
197 /* Right truncation arrow bitmap `->'. */
198
199 #define right_width 8
200 #define right_height 8
201 static unsigned char right_bits[] = {
202 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
203
204 /* Marker for continued lines. */
205
206 #define continued_width 8
207 #define continued_height 8
208 static unsigned char continued_bits[] = {
209 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
210
211 /* Marker for continuation lines. */
212
213 #define continuation_width 8
214 #define continuation_height 8
215 static unsigned char continuation_bits[] = {
216 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
217
218 /* Overlay arrow bitmap. */
219
220 #if 0
221 /* A bomb. */
222 #define ov_width 8
223 #define ov_height 8
224 static unsigned char ov_bits[] = {
225 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
226 #else
227 /* A triangular arrow. */
228 #define ov_width 8
229 #define ov_height 8
230 static unsigned char ov_bits[] = {
231 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
232
233 #endif
234
235 extern Lisp_Object Qhelp_echo;
236
237 \f
238 /* Non-zero means Emacs uses toolkit scroll bars. */
239
240 int x_toolkit_scroll_bars_p;
241
242 /* If a string, XTread_socket generates an event to display that string.
243 (The display is done in read_char.) */
244
245 static Lisp_Object help_echo;
246
247 /* Temporary variable for XTread_socket. */
248
249 static Lisp_Object previous_help_echo;
250
251 /* Non-zero means that a HELP_EVENT has been generated since Emacs
252 start. */
253
254 static int any_help_event_p;
255
256 /* Non-zero means draw block and hollow cursor as wide as the glyph
257 under it. For example, if a block cursor is over a tab, it will be
258 drawn as wide as that tab on the display. */
259
260 int x_stretch_cursor_p;
261
262 /* This is a chain of structures for all the X displays currently in
263 use. */
264
265 struct x_display_info *x_display_list;
266
267 /* This is a list of cons cells, each of the form (NAME
268 . FONT-LIST-CACHE), one for each element of x_display_list and in
269 the same order. NAME is the name of the frame. FONT-LIST-CACHE
270 records previous values returned by x-list-fonts. */
271
272 Lisp_Object x_display_name_list;
273
274 /* Frame being updated by update_frame. This is declared in term.c.
275 This is set by update_begin and looked at by all the XT functions.
276 It is zero while not inside an update. In that case, the XT
277 functions assume that `selected_frame' is the frame to apply to. */
278
279 extern struct frame *updating_frame;
280
281 extern int waiting_for_input;
282
283 /* This is a frame waiting to be auto-raised, within XTread_socket. */
284
285 struct frame *pending_autoraise_frame;
286
287 #ifdef USE_X_TOOLKIT
288 /* The application context for Xt use. */
289 XtAppContext Xt_app_con;
290 static String Xt_default_resources[] = {0};
291 #endif /* USE_X_TOOLKIT */
292
293 /* Nominal cursor position -- where to draw output.
294 HPOS and VPOS are window relative glyph matrix coordinates.
295 X and Y are window relative pixel coordinates. */
296
297 struct cursor_pos output_cursor;
298
299 /* Non-zero means user is interacting with a toolkit scroll bar. */
300
301 static int toolkit_scroll_bar_interaction;
302
303 /* Mouse movement.
304
305 Formerly, we used PointerMotionHintMask (in standard_event_mask)
306 so that we would have to call XQueryPointer after each MotionNotify
307 event to ask for another such event. However, this made mouse tracking
308 slow, and there was a bug that made it eventually stop.
309
310 Simply asking for MotionNotify all the time seems to work better.
311
312 In order to avoid asking for motion events and then throwing most
313 of them away or busy-polling the server for mouse positions, we ask
314 the server for pointer motion hints. This means that we get only
315 one event per group of mouse movements. "Groups" are delimited by
316 other kinds of events (focus changes and button clicks, for
317 example), or by XQueryPointer calls; when one of these happens, we
318 get another MotionNotify event the next time the mouse moves. This
319 is at least as efficient as getting motion events when mouse
320 tracking is on, and I suspect only negligibly worse when tracking
321 is off. */
322
323 /* Where the mouse was last time we reported a mouse event. */
324
325 FRAME_PTR last_mouse_frame;
326 static XRectangle last_mouse_glyph;
327 static Lisp_Object last_mouse_press_frame;
328
329 /* The scroll bar in which the last X motion event occurred.
330
331 If the last X motion event occurred in a scroll bar, we set this so
332 XTmouse_position can know whether to report a scroll bar motion or
333 an ordinary motion.
334
335 If the last X motion event didn't occur in a scroll bar, we set
336 this to Qnil, to tell XTmouse_position to return an ordinary motion
337 event. */
338
339 static Lisp_Object last_mouse_scroll_bar;
340
341 /* This is a hack. We would really prefer that XTmouse_position would
342 return the time associated with the position it returns, but there
343 doesn't seem to be any way to wrest the time-stamp from the server
344 along with the position query. So, we just keep track of the time
345 of the last movement we received, and return that in hopes that
346 it's somewhat accurate. */
347
348 static Time last_mouse_movement_time;
349
350 /* Incremented by XTread_socket whenever it really tries to read
351 events. */
352
353 #ifdef __STDC__
354 static int volatile input_signal_count;
355 #else
356 static int input_signal_count;
357 #endif
358
359 /* Used locally within XTread_socket. */
360
361 static int x_noop_count;
362
363 /* Initial values of argv and argc. */
364
365 extern char **initial_argv;
366 extern int initial_argc;
367
368 extern Lisp_Object Vcommand_line_args, Vsystem_name;
369
370 /* Tells if a window manager is present or not. */
371
372 extern Lisp_Object Vx_no_window_manager;
373
374 extern Lisp_Object Qface, Qmouse_face;
375
376 extern int errno;
377
378 /* A mask of extra modifier bits to put into every keyboard char. */
379
380 extern int extra_keyboard_modifiers;
381
382 static Lisp_Object Qvendor_specific_keysyms;
383
384 extern XrmDatabase x_load_resources ();
385 extern Lisp_Object x_icon_type ();
386
387
388 /* Enumeration for overriding/changing the face to use for drawing
389 glyphs in x_draw_glyphs. */
390
391 enum draw_glyphs_face
392 {
393 DRAW_NORMAL_TEXT,
394 DRAW_INVERSE_VIDEO,
395 DRAW_CURSOR,
396 DRAW_MOUSE_FACE,
397 DRAW_IMAGE_RAISED,
398 DRAW_IMAGE_SUNKEN
399 };
400
401 static void x_update_window_end P_ ((struct window *, int));
402 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
403 void x_delete_display P_ ((struct x_display_info *));
404 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
405 unsigned));
406 static int fast_find_position P_ ((struct window *, int, int *, int *,
407 int *, int *));
408 static void set_output_cursor P_ ((struct cursor_pos *));
409 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
410 int *, int *, int *));
411 static void note_mode_line_highlight P_ ((struct window *, int, int));
412 static void note_mouse_highlight P_ ((struct frame *, int, int));
413 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
414 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
415 static void show_mouse_face P_ ((struct x_display_info *,
416 enum draw_glyphs_face));
417 static int x_io_error_quitter P_ ((Display *));
418 int x_catch_errors P_ ((Display *));
419 void x_uncatch_errors P_ ((Display *, int));
420 void x_lower_frame P_ ((struct frame *));
421 void x_scroll_bar_clear P_ ((struct frame *));
422 int x_had_errors_p P_ ((Display *));
423 void x_wm_set_size_hint P_ ((struct frame *, long, int));
424 void x_raise_frame P_ ((struct frame *));
425 void x_set_window_size P_ ((struct frame *, int, int, int));
426 void x_wm_set_window_state P_ ((struct frame *, int));
427 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
428 void x_initialize P_ ((void));
429 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
430 static int x_compute_min_glyph_bounds P_ ((struct frame *));
431 static void x_draw_phys_cursor_glyph P_ ((struct window *,
432 struct glyph_row *,
433 enum draw_glyphs_face));
434 static void x_update_end P_ ((struct frame *));
435 static void XTframe_up_to_date P_ ((struct frame *));
436 static void XTreassert_line_highlight P_ ((int, int));
437 static void x_change_line_highlight P_ ((int, int, int, int));
438 static void XTset_terminal_modes P_ ((void));
439 static void XTreset_terminal_modes P_ ((void));
440 static void XTcursor_to P_ ((int, int, int, int));
441 static void x_write_glyphs P_ ((struct glyph *, int));
442 static void x_clear_end_of_line P_ ((int));
443 static void x_clear_frame P_ ((void));
444 static void x_clear_cursor P_ ((struct window *));
445 static void frame_highlight P_ ((struct frame *));
446 static void frame_unhighlight P_ ((struct frame *));
447 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
448 static void XTframe_rehighlight P_ ((struct frame *));
449 static void x_frame_rehighlight P_ ((struct x_display_info *));
450 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
451 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
452 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
453 XRectangle *));
454 static void expose_frame P_ ((struct frame *, int, int, int, int));
455 static void expose_window_tree P_ ((struct window *, XRectangle *));
456 static void expose_window P_ ((struct window *, XRectangle *));
457 static void expose_area P_ ((struct window *, struct glyph_row *,
458 XRectangle *, enum glyph_row_area));
459 static void expose_line P_ ((struct window *, struct glyph_row *,
460 XRectangle *));
461 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
462 static void x_update_window_cursor P_ ((struct window *, int));
463 static void x_erase_phys_cursor P_ ((struct window *));
464 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
465 static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
466 enum bitmap_type));
467
468 static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
469 GC, int));
470 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
471 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
472 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
473 static void x_flush P_ ((struct frame *f));
474
475
476 /* Flush display of frame F, or of all frames if F is null. */
477
478 static void
479 x_flush (f)
480 struct frame *f;
481 {
482 BLOCK_INPUT;
483 if (f == NULL)
484 {
485 Lisp_Object rest, frame;
486 FOR_EACH_FRAME (rest, frame)
487 x_flush (XFRAME (frame));
488 }
489 else if (FRAME_X_P (f))
490 XFlush (FRAME_X_DISPLAY (f));
491 UNBLOCK_INPUT;
492 }
493
494
495 /* Remove calls to XFlush by defining XFlush to an empty replacement.
496 Calls to XFlush should be unnecessary because the X output buffer
497 is flushed automatically as needed by calls to XPending,
498 XNextEvent, or XWindowEvent according to the XFlush man page.
499 XTread_socket calls XPending. Removing XFlush improves
500 performance. */
501
502 #define XFlush(DISPLAY) (void) 0
503
504 \f
505 /***********************************************************************
506 Debugging
507 ***********************************************************************/
508
509 #if 0
510
511 /* This is a function useful for recording debugging information about
512 the sequence of occurrences in this file. */
513
514 struct record
515 {
516 char *locus;
517 int type;
518 };
519
520 struct record event_record[100];
521
522 int event_record_index;
523
524 record_event (locus, type)
525 char *locus;
526 int type;
527 {
528 if (event_record_index == sizeof (event_record) / sizeof (struct record))
529 event_record_index = 0;
530
531 event_record[event_record_index].locus = locus;
532 event_record[event_record_index].type = type;
533 event_record_index++;
534 }
535
536 #endif /* 0 */
537
538
539 \f
540 /* Return the struct x_display_info corresponding to DPY. */
541
542 struct x_display_info *
543 x_display_info_for_display (dpy)
544 Display *dpy;
545 {
546 struct x_display_info *dpyinfo;
547
548 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
549 if (dpyinfo->display == dpy)
550 return dpyinfo;
551
552 return 0;
553 }
554
555
556 \f
557 /***********************************************************************
558 Starting and ending an update
559 ***********************************************************************/
560
561 /* Start an update of frame F. This function is installed as a hook
562 for update_begin, i.e. it is called when update_begin is called.
563 This function is called prior to calls to x_update_window_begin for
564 each window being updated. Currently, there is nothing to do here
565 because all interesting stuff is done on a window basis. */
566
567 static void
568 x_update_begin (f)
569 struct frame *f;
570 {
571 /* Nothing to do. */
572 }
573
574
575 /* Start update of window W. Set the global variable updated_window
576 to the window being updated and set output_cursor to the cursor
577 position of W. */
578
579 static void
580 x_update_window_begin (w)
581 struct window *w;
582 {
583 struct frame *f = XFRAME (WINDOW_FRAME (w));
584 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
585
586 updated_window = w;
587 set_output_cursor (&w->cursor);
588
589 BLOCK_INPUT;
590
591 if (f == display_info->mouse_face_mouse_frame)
592 {
593 /* Don't do highlighting for mouse motion during the update. */
594 display_info->mouse_face_defer = 1;
595
596 /* If F needs to be redrawn, simply forget about any prior mouse
597 highlighting. */
598 if (FRAME_GARBAGED_P (f))
599 display_info->mouse_face_window = Qnil;
600
601 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
602 their mouse_face_p flag set, which means that they are always
603 unequal to rows in a desired matrix which never have that
604 flag set. So, rows containing mouse-face glyphs are never
605 scrolled, and we don't have to switch the mouse highlight off
606 here to prevent it from being scrolled. */
607
608 /* Can we tell that this update does not affect the window
609 where the mouse highlight is? If so, no need to turn off.
610 Likewise, don't do anything if the frame is garbaged;
611 in that case, the frame's current matrix that we would use
612 is all wrong, and we will redisplay that line anyway. */
613 if (!NILP (display_info->mouse_face_window)
614 && w == XWINDOW (display_info->mouse_face_window))
615 {
616 int i;
617
618 for (i = 0; i < w->desired_matrix->nrows; ++i)
619 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
620 break;
621
622 if (i < w->desired_matrix->nrows)
623 clear_mouse_face (display_info);
624 }
625 #endif /* 0 */
626 }
627
628 UNBLOCK_INPUT;
629 }
630
631
632 /* Draw a vertical window border to the right of window W if W doesn't
633 have vertical scroll bars. */
634
635 static void
636 x_draw_vertical_border (w)
637 struct window *w;
638 {
639 struct frame *f = XFRAME (WINDOW_FRAME (w));
640
641 /* Redraw borders between horizontally adjacent windows. Don't
642 do it for frames with vertical scroll bars because either the
643 right scroll bar of a window, or the left scroll bar of its
644 neighbor will suffice as a border. */
645 if (!WINDOW_RIGHTMOST_P (w)
646 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
647 {
648 int x0, x1, y0, y1;
649
650 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
651 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
652 y1 -= 1;
653
654 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
655 f->output_data.x->normal_gc, x1, y0, x1, y1);
656 }
657 }
658
659
660 /* End update of window W (which is equal to updated_window). Draw
661 vertical borders between horizontally adjacent windows, and display
662 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
663 pseudo-window in case we don't have X toolkit support. Such
664 windows don't have a cursor, so don't display it here. */
665
666 static void
667 x_update_window_end (w, cursor_on_p)
668 struct window *w;
669 int cursor_on_p;
670 {
671 if (!w->pseudo_window_p)
672 {
673 BLOCK_INPUT;
674 if (cursor_on_p)
675 x_display_and_set_cursor (w, 1, output_cursor.hpos,
676 output_cursor.vpos,
677 output_cursor.x, output_cursor.y);
678 x_draw_vertical_border (w);
679 UNBLOCK_INPUT;
680 }
681
682 updated_window = NULL;
683 }
684
685
686 /* End update of frame F. This function is installed as a hook in
687 update_end. */
688
689 static void
690 x_update_end (f)
691 struct frame *f;
692 {
693 /* Mouse highlight may be displayed again. */
694 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
695
696 BLOCK_INPUT;
697 XFlush (FRAME_X_DISPLAY (f));
698 UNBLOCK_INPUT;
699 }
700
701
702 /* This function is called from various places in xdisp.c whenever a
703 complete update has been performed. The global variable
704 updated_window is not available here. */
705
706 static void
707 XTframe_up_to_date (f)
708 struct frame *f;
709 {
710 if (FRAME_X_P (f))
711 {
712 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
713 if (dpyinfo->mouse_face_deferred_gc
714 || f == dpyinfo->mouse_face_mouse_frame)
715 {
716 BLOCK_INPUT;
717 if (dpyinfo->mouse_face_mouse_frame)
718 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
719 dpyinfo->mouse_face_mouse_x,
720 dpyinfo->mouse_face_mouse_y);
721 dpyinfo->mouse_face_deferred_gc = 0;
722 UNBLOCK_INPUT;
723 }
724 }
725 }
726
727
728 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
729 arrow bitmaps, or clear the areas where they would be displayed
730 before DESIRED_ROW is made current. The window being updated is
731 found in updated_window. This function It is called from
732 update_window_line only if it is known that there are differences
733 between bitmaps to be drawn between current row and DESIRED_ROW. */
734
735 static void
736 x_after_update_window_line (desired_row)
737 struct glyph_row *desired_row;
738 {
739 struct window *w = updated_window;
740
741 xassert (w);
742
743 if (!desired_row->mode_line_p && !w->pseudo_window_p)
744 {
745 BLOCK_INPUT;
746 x_draw_row_bitmaps (w, desired_row);
747
748 /* When a window has disappeared, make sure that no rest of
749 full-width rows stays visible in the internal border. */
750 if (windows_or_buffers_changed)
751 {
752 struct frame *f = XFRAME (w->frame);
753 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
754 int height = desired_row->visible_height;
755 int x = (window_box_right (w, -1)
756 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
757 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
758
759 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
760 x, y, width, height, False);
761 }
762
763 UNBLOCK_INPUT;
764 }
765 }
766
767
768 /* Draw the bitmap WHICH in one of the areas to the left or right of
769 window W. ROW is the glyph row for which to display the bitmap; it
770 determines the vertical position at which the bitmap has to be
771 drawn. */
772
773 static void
774 x_draw_bitmap (w, row, which)
775 struct window *w;
776 struct glyph_row *row;
777 enum bitmap_type which;
778 {
779 struct frame *f = XFRAME (WINDOW_FRAME (w));
780 Display *display = FRAME_X_DISPLAY (f);
781 Window window = FRAME_X_WINDOW (f);
782 int x, y, wd, h, dy;
783 unsigned char *bits;
784 Pixmap pixmap;
785 GC gc = f->output_data.x->normal_gc;
786 struct face *face;
787 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
788
789 /* Must clip because of partially visible lines. */
790 x_clip_to_row (w, row, gc, 1);
791
792 switch (which)
793 {
794 case LEFT_TRUNCATION_BITMAP:
795 wd = left_width;
796 h = left_height;
797 bits = left_bits;
798 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
799 - wd
800 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
801 break;
802
803 case OVERLAY_ARROW_BITMAP:
804 wd = left_width;
805 h = left_height;
806 bits = ov_bits;
807 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
808 - wd
809 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
810 break;
811
812 case RIGHT_TRUNCATION_BITMAP:
813 wd = right_width;
814 h = right_height;
815 bits = right_bits;
816 x = window_box_right (w, -1);
817 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
818 break;
819
820 case CONTINUED_LINE_BITMAP:
821 wd = right_width;
822 h = right_height;
823 bits = continued_bits;
824 x = window_box_right (w, -1);
825 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
826 break;
827
828 case CONTINUATION_LINE_BITMAP:
829 wd = continuation_width;
830 h = continuation_height;
831 bits = continuation_bits;
832 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
833 - wd
834 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
835 break;
836
837 case ZV_LINE_BITMAP:
838 wd = zv_width;
839 h = zv_height;
840 bits = zv_bits;
841 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
842 - wd
843 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
844 break;
845
846 default:
847 abort ();
848 }
849
850 /* Convert to frame coordinates. Set dy to the offset in the row to
851 start drawing the bitmap. */
852 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
853 dy = (row->height - h) / 2;
854
855 /* Draw the bitmap. I believe these small pixmaps can be cached
856 by the server. */
857 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
858 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
859 face->foreground,
860 face->background, depth);
861 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
862 XFreePixmap (display, pixmap);
863 XSetClipMask (display, gc, None);
864 }
865
866
867 /* Draw flags bitmaps for glyph row ROW on window W. Call this
868 function with input blocked. */
869
870 static void
871 x_draw_row_bitmaps (w, row)
872 struct window *w;
873 struct glyph_row *row;
874 {
875 struct frame *f = XFRAME (w->frame);
876 enum bitmap_type bitmap;
877 struct face *face;
878 int header_line_height = -1;
879
880 xassert (interrupt_input_blocked);
881
882 /* If row is completely invisible, because of vscrolling, we
883 don't have to draw anything. */
884 if (row->visible_height <= 0)
885 return;
886
887 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
888 PREPARE_FACE_FOR_DISPLAY (f, face);
889
890 /* Decide which bitmap to draw at the left side. */
891 if (row->overlay_arrow_p)
892 bitmap = OVERLAY_ARROW_BITMAP;
893 else if (row->truncated_on_left_p)
894 bitmap = LEFT_TRUNCATION_BITMAP;
895 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
896 bitmap = CONTINUATION_LINE_BITMAP;
897 else if (row->indicate_empty_line_p)
898 bitmap = ZV_LINE_BITMAP;
899 else
900 bitmap = NO_BITMAP;
901
902 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
903 the flags area. */
904 if (bitmap == NO_BITMAP
905 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
906 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
907 {
908 /* If W has a vertical border to its left, don't draw over it. */
909 int border = ((XFASTINT (w->left) > 0
910 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
911 ? 1 : 0);
912 int left = window_box_left (w, -1);
913
914 if (header_line_height < 0)
915 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
916
917 /* In case the same realized face is used for bitmap areas and
918 for something displayed in the text (e.g. face `region' on
919 mono-displays, the fill style may have been changed to
920 FillSolid in x_draw_glyph_string_background. */
921 if (face->stipple)
922 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
923 else
924 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
925
926 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
927 face->gc,
928 (left
929 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
930 + border),
931 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
932 row->y)),
933 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
934 row->visible_height);
935 if (!face->stipple)
936 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
937 }
938
939 /* Draw the left bitmap. */
940 if (bitmap != NO_BITMAP)
941 x_draw_bitmap (w, row, bitmap);
942
943 /* Decide which bitmap to draw at the right side. */
944 if (row->truncated_on_right_p)
945 bitmap = RIGHT_TRUNCATION_BITMAP;
946 else if (row->continued_p)
947 bitmap = CONTINUED_LINE_BITMAP;
948 else
949 bitmap = NO_BITMAP;
950
951 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
952 the flags area. */
953 if (bitmap == NO_BITMAP
954 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
955 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
956 {
957 int right = window_box_right (w, -1);
958
959 if (header_line_height < 0)
960 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
961
962 /* In case the same realized face is used for bitmap areas and
963 for something displayed in the text (e.g. face `region' on
964 mono-displays, the fill style may have been changed to
965 FillSolid in x_draw_glyph_string_background. */
966 if (face->stipple)
967 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
968 else
969 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
970 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
971 face->gc,
972 right,
973 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
974 row->y)),
975 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
976 row->visible_height);
977 if (!face->stipple)
978 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
979 }
980
981 /* Draw the right bitmap. */
982 if (bitmap != NO_BITMAP)
983 x_draw_bitmap (w, row, bitmap);
984 }
985
986 \f
987 /***********************************************************************
988 Line Highlighting
989 ***********************************************************************/
990
991 /* External interface to control of standout mode. Not used for X
992 frames. Aborts when called. */
993
994 static void
995 XTreassert_line_highlight (new, vpos)
996 int new, vpos;
997 {
998 abort ();
999 }
1000
1001
1002 /* Call this when about to modify line at position VPOS and change
1003 whether it is highlighted. Not used for X frames. Aborts when
1004 called. */
1005
1006 static void
1007 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1008 int new_highlight, vpos, y, first_unused_hpos;
1009 {
1010 abort ();
1011 }
1012
1013
1014 /* This is called when starting Emacs and when restarting after
1015 suspend. When starting Emacs, no X window is mapped. And nothing
1016 must be done to Emacs's own window if it is suspended (though that
1017 rarely happens). */
1018
1019 static void
1020 XTset_terminal_modes ()
1021 {
1022 }
1023
1024 /* This is called when exiting or suspending Emacs. Exiting will make
1025 the X-windows go away, and suspending requires no action. */
1026
1027 static void
1028 XTreset_terminal_modes ()
1029 {
1030 }
1031
1032
1033 \f
1034 /***********************************************************************
1035 Output Cursor
1036 ***********************************************************************/
1037
1038 /* Set the global variable output_cursor to CURSOR. All cursor
1039 positions are relative to updated_window. */
1040
1041 static void
1042 set_output_cursor (cursor)
1043 struct cursor_pos *cursor;
1044 {
1045 output_cursor.hpos = cursor->hpos;
1046 output_cursor.vpos = cursor->vpos;
1047 output_cursor.x = cursor->x;
1048 output_cursor.y = cursor->y;
1049 }
1050
1051
1052 /* Set a nominal cursor position.
1053
1054 HPOS and VPOS are column/row positions in a window glyph matrix. X
1055 and Y are window text area relative pixel positions.
1056
1057 If this is done during an update, updated_window will contain the
1058 window that is being updated and the position is the future output
1059 cursor position for that window. If updated_window is null, use
1060 selected_window and display the cursor at the given position. */
1061
1062 static void
1063 XTcursor_to (vpos, hpos, y, x)
1064 int vpos, hpos, y, x;
1065 {
1066 struct window *w;
1067
1068 /* If updated_window is not set, work on selected_window. */
1069 if (updated_window)
1070 w = updated_window;
1071 else
1072 w = XWINDOW (selected_window);
1073
1074 /* Set the output cursor. */
1075 output_cursor.hpos = hpos;
1076 output_cursor.vpos = vpos;
1077 output_cursor.x = x;
1078 output_cursor.y = y;
1079
1080 /* If not called as part of an update, really display the cursor.
1081 This will also set the cursor position of W. */
1082 if (updated_window == NULL)
1083 {
1084 BLOCK_INPUT;
1085 x_display_cursor (w, 1, hpos, vpos, x, y);
1086 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
1087 UNBLOCK_INPUT;
1088 }
1089 }
1090
1091
1092 \f
1093 /***********************************************************************
1094 Display Iterator
1095 ***********************************************************************/
1096
1097 /* Function prototypes of this page. */
1098
1099 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1100 struct glyph *,
1101 XChar2b *,
1102 int *));
1103 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1104 int, XChar2b *, int));
1105 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1106 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1107 static void x_append_glyph P_ ((struct it *));
1108 static void x_append_composite_glyph P_ ((struct it *));
1109 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1110 int, int, double));
1111 static void x_produce_glyphs P_ ((struct it *));
1112 static void x_produce_image_glyph P_ ((struct it *it));
1113
1114
1115 /* Return a pointer to per-char metric information in FONT of a
1116 character pointed by B which is a pointer to an XChar2b. */
1117
1118 #define PER_CHAR_METRIC(font, b) \
1119 ((font)->per_char \
1120 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1121 + (((font)->min_byte1 || (font)->max_byte1) \
1122 ? (((b)->byte1 - (font)->min_byte1) \
1123 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1124 : 0)) \
1125 : &((font)->max_bounds))
1126
1127
1128 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1129 is not contained in the font. */
1130
1131 static INLINE XCharStruct *
1132 x_per_char_metric (font, char2b)
1133 XFontStruct *font;
1134 XChar2b *char2b;
1135 {
1136 /* The result metric information. */
1137 XCharStruct *pcm = NULL;
1138
1139 xassert (font && char2b);
1140
1141 if (font->per_char != NULL)
1142 {
1143 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1144 {
1145 /* min_char_or_byte2 specifies the linear character index
1146 corresponding to the first element of the per_char array,
1147 max_char_or_byte2 is the index of the last character. A
1148 character with non-zero CHAR2B->byte1 is not in the font.
1149 A character with byte2 less than min_char_or_byte2 or
1150 greater max_char_or_byte2 is not in the font. */
1151 if (char2b->byte1 == 0
1152 && char2b->byte2 >= font->min_char_or_byte2
1153 && char2b->byte2 <= font->max_char_or_byte2)
1154 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1155 }
1156 else
1157 {
1158 /* If either min_byte1 or max_byte1 are nonzero, both
1159 min_char_or_byte2 and max_char_or_byte2 are less than
1160 256, and the 2-byte character index values corresponding
1161 to the per_char array element N (counting from 0) are:
1162
1163 byte1 = N/D + min_byte1
1164 byte2 = N\D + min_char_or_byte2
1165
1166 where:
1167
1168 D = max_char_or_byte2 - min_char_or_byte2 + 1
1169 / = integer division
1170 \ = integer modulus */
1171 if (char2b->byte1 >= font->min_byte1
1172 && char2b->byte1 <= font->max_byte1
1173 && char2b->byte2 >= font->min_char_or_byte2
1174 && char2b->byte2 <= font->max_char_or_byte2)
1175 {
1176 pcm = (font->per_char
1177 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1178 * (char2b->byte1 - font->min_byte1))
1179 + (char2b->byte2 - font->min_char_or_byte2));
1180 }
1181 }
1182 }
1183 else
1184 {
1185 /* If the per_char pointer is null, all glyphs between the first
1186 and last character indexes inclusive have the same
1187 information, as given by both min_bounds and max_bounds. */
1188 if (char2b->byte2 >= font->min_char_or_byte2
1189 && char2b->byte2 <= font->max_char_or_byte2)
1190 pcm = &font->max_bounds;
1191 }
1192
1193 return ((pcm == NULL
1194 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1195 ? NULL : pcm);
1196 }
1197
1198
1199 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1200 the two-byte form of C. Encoding is returned in *CHAR2B. */
1201
1202 static INLINE void
1203 x_encode_char (c, char2b, font_info)
1204 int c;
1205 XChar2b *char2b;
1206 struct font_info *font_info;
1207 {
1208 int charset = CHAR_CHARSET (c);
1209 XFontStruct *font = font_info->font;
1210
1211 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1212 This may be either a program in a special encoder language or a
1213 fixed encoding. */
1214 if (font_info->font_encoder)
1215 {
1216 /* It's a program. */
1217 struct ccl_program *ccl = font_info->font_encoder;
1218
1219 if (CHARSET_DIMENSION (charset) == 1)
1220 {
1221 ccl->reg[0] = charset;
1222 ccl->reg[1] = char2b->byte2;
1223 }
1224 else
1225 {
1226 ccl->reg[0] = charset;
1227 ccl->reg[1] = char2b->byte1;
1228 ccl->reg[2] = char2b->byte2;
1229 }
1230
1231 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1232
1233 /* We assume that MSBs are appropriately set/reset by CCL
1234 program. */
1235 if (font->max_byte1 == 0) /* 1-byte font */
1236 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1237 else
1238 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1239 }
1240 else if (font_info->encoding[charset])
1241 {
1242 /* Fixed encoding scheme. See fontset.h for the meaning of the
1243 encoding numbers. */
1244 int enc = font_info->encoding[charset];
1245
1246 if ((enc == 1 || enc == 2)
1247 && CHARSET_DIMENSION (charset) == 2)
1248 char2b->byte1 |= 0x80;
1249
1250 if (enc == 1 || enc == 3)
1251 char2b->byte2 |= 0x80;
1252 }
1253 }
1254
1255
1256 /* Get face and two-byte form of character C in face FACE_ID on frame
1257 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1258 means we want to display multibyte text. Value is a pointer to a
1259 realized face that is ready for display. */
1260
1261 static INLINE struct face *
1262 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1263 struct frame *f;
1264 int c, face_id;
1265 XChar2b *char2b;
1266 int multibyte_p;
1267 {
1268 struct face *face = FACE_FROM_ID (f, face_id);
1269
1270 if (!multibyte_p)
1271 {
1272 /* Unibyte case. We don't have to encode, but we have to make
1273 sure to use a face suitable for unibyte. */
1274 char2b->byte1 = 0;
1275 char2b->byte2 = c;
1276 face_id = FACE_FOR_CHAR (f, face, c);
1277 face = FACE_FROM_ID (f, face_id);
1278 }
1279 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1280 {
1281 /* Case of ASCII in a face known to fit ASCII. */
1282 char2b->byte1 = 0;
1283 char2b->byte2 = c;
1284 }
1285 else
1286 {
1287 int c1, c2, charset;
1288
1289 /* Split characters into bytes. If c2 is -1 afterwards, C is
1290 really a one-byte character so that byte1 is zero. */
1291 SPLIT_CHAR (c, charset, c1, c2);
1292 if (c2 > 0)
1293 char2b->byte1 = c1, char2b->byte2 = c2;
1294 else
1295 char2b->byte1 = 0, char2b->byte2 = c1;
1296
1297 /* Maybe encode the character in *CHAR2B. */
1298 if (face->font != NULL)
1299 {
1300 struct font_info *font_info
1301 = FONT_INFO_FROM_ID (f, face->font_info_id);
1302 if (font_info)
1303 x_encode_char (c, char2b, font_info);
1304 }
1305 }
1306
1307 /* Make sure X resources of the face are allocated. */
1308 xassert (face != NULL);
1309 PREPARE_FACE_FOR_DISPLAY (f, face);
1310
1311 return face;
1312 }
1313
1314
1315 /* Get face and two-byte form of character glyph GLYPH on frame F.
1316 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1317 a pointer to a realized face that is ready for display. */
1318
1319 static INLINE struct face *
1320 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1321 struct frame *f;
1322 struct glyph *glyph;
1323 XChar2b *char2b;
1324 int *two_byte_p;
1325 {
1326 struct face *face;
1327
1328 xassert (glyph->type == CHAR_GLYPH);
1329 face = FACE_FROM_ID (f, glyph->face_id);
1330
1331 if (two_byte_p)
1332 *two_byte_p = 0;
1333
1334 if (!glyph->multibyte_p)
1335 {
1336 /* Unibyte case. We don't have to encode, but we have to make
1337 sure to use a face suitable for unibyte. */
1338 char2b->byte1 = 0;
1339 char2b->byte2 = glyph->u.ch;
1340 }
1341 else if (glyph->u.ch < 128
1342 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1343 {
1344 /* Case of ASCII in a face known to fit ASCII. */
1345 char2b->byte1 = 0;
1346 char2b->byte2 = glyph->u.ch;
1347 }
1348 else
1349 {
1350 int c1, c2, charset;
1351
1352 /* Split characters into bytes. If c2 is -1 afterwards, C is
1353 really a one-byte character so that byte1 is zero. */
1354 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1355 if (c2 > 0)
1356 char2b->byte1 = c1, char2b->byte2 = c2;
1357 else
1358 char2b->byte1 = 0, char2b->byte2 = c1;
1359
1360 /* Maybe encode the character in *CHAR2B. */
1361 if (charset != CHARSET_ASCII)
1362 {
1363 struct font_info *font_info
1364 = FONT_INFO_FROM_ID (f, face->font_info_id);
1365 if (font_info)
1366 {
1367 x_encode_char (glyph->u.ch, char2b, font_info);
1368 if (two_byte_p)
1369 *two_byte_p
1370 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1371 }
1372 }
1373 }
1374
1375 /* Make sure X resources of the face are allocated. */
1376 xassert (face != NULL);
1377 PREPARE_FACE_FOR_DISPLAY (f, face);
1378 return face;
1379 }
1380
1381
1382 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1383 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1384
1385 static INLINE void
1386 x_append_glyph (it)
1387 struct it *it;
1388 {
1389 struct glyph *glyph;
1390 enum glyph_row_area area = it->area;
1391
1392 xassert (it->glyph_row);
1393 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1394
1395 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1396 if (glyph < it->glyph_row->glyphs[area + 1])
1397 {
1398 glyph->charpos = CHARPOS (it->position);
1399 glyph->object = it->object;
1400 glyph->pixel_width = it->pixel_width;
1401 glyph->voffset = it->voffset;
1402 glyph->type = CHAR_GLYPH;
1403 glyph->multibyte_p = it->multibyte_p;
1404 glyph->left_box_line_p = it->start_of_box_run_p;
1405 glyph->right_box_line_p = it->end_of_box_run_p;
1406 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1407 || it->phys_descent > it->descent);
1408 glyph->padding_p = 0;
1409 glyph->glyph_not_available_p = it->glyph_not_available_p;
1410 glyph->face_id = it->face_id;
1411 glyph->u.ch = it->char_to_display;
1412 ++it->glyph_row->used[area];
1413 }
1414 }
1415
1416 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1417 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1418
1419 static INLINE void
1420 x_append_composite_glyph (it)
1421 struct it *it;
1422 {
1423 struct glyph *glyph;
1424 enum glyph_row_area area = it->area;
1425
1426 xassert (it->glyph_row);
1427
1428 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1429 if (glyph < it->glyph_row->glyphs[area + 1])
1430 {
1431 glyph->charpos = CHARPOS (it->position);
1432 glyph->object = it->object;
1433 glyph->pixel_width = it->pixel_width;
1434 glyph->voffset = it->voffset;
1435 glyph->type = COMPOSITE_GLYPH;
1436 glyph->multibyte_p = it->multibyte_p;
1437 glyph->left_box_line_p = it->start_of_box_run_p;
1438 glyph->right_box_line_p = it->end_of_box_run_p;
1439 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1440 || it->phys_descent > it->descent);
1441 glyph->padding_p = 0;
1442 glyph->glyph_not_available_p = 0;
1443 glyph->face_id = it->face_id;
1444 glyph->u.cmp_id = it->cmp_id;
1445 ++it->glyph_row->used[area];
1446 }
1447 }
1448
1449
1450 /* Change IT->ascent and IT->height according to the setting of
1451 IT->voffset. */
1452
1453 static INLINE void
1454 take_vertical_position_into_account (it)
1455 struct it *it;
1456 {
1457 if (it->voffset)
1458 {
1459 if (it->voffset < 0)
1460 /* Increase the ascent so that we can display the text higher
1461 in the line. */
1462 it->ascent += abs (it->voffset);
1463 else
1464 /* Increase the descent so that we can display the text lower
1465 in the line. */
1466 it->descent += it->voffset;
1467 }
1468 }
1469
1470
1471 /* Produce glyphs/get display metrics for the image IT is loaded with.
1472 See the description of struct display_iterator in dispextern.h for
1473 an overview of struct display_iterator. */
1474
1475 static void
1476 x_produce_image_glyph (it)
1477 struct it *it;
1478 {
1479 struct image *img;
1480 struct face *face;
1481
1482 xassert (it->what == IT_IMAGE);
1483
1484 face = FACE_FROM_ID (it->f, it->face_id);
1485 img = IMAGE_FROM_ID (it->f, it->image_id);
1486 xassert (img);
1487
1488 /* Make sure X resources of the face and image are loaded. */
1489 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1490 prepare_image_for_display (it->f, img);
1491
1492 it->ascent = it->phys_ascent = image_ascent (img, face);
1493 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1494 it->pixel_width = img->width + 2 * img->margin;
1495
1496 it->nglyphs = 1;
1497
1498 if (face->box != FACE_NO_BOX)
1499 {
1500 it->ascent += face->box_line_width;
1501 it->descent += face->box_line_width;
1502
1503 if (it->start_of_box_run_p)
1504 it->pixel_width += face->box_line_width;
1505 if (it->end_of_box_run_p)
1506 it->pixel_width += face->box_line_width;
1507 }
1508
1509 take_vertical_position_into_account (it);
1510
1511 if (it->glyph_row)
1512 {
1513 struct glyph *glyph;
1514 enum glyph_row_area area = it->area;
1515
1516 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1517 if (glyph < it->glyph_row->glyphs[area + 1])
1518 {
1519 glyph->charpos = CHARPOS (it->position);
1520 glyph->object = it->object;
1521 glyph->pixel_width = it->pixel_width;
1522 glyph->voffset = it->voffset;
1523 glyph->type = IMAGE_GLYPH;
1524 glyph->multibyte_p = it->multibyte_p;
1525 glyph->left_box_line_p = it->start_of_box_run_p;
1526 glyph->right_box_line_p = it->end_of_box_run_p;
1527 glyph->overlaps_vertically_p = 0;
1528 glyph->padding_p = 0;
1529 glyph->glyph_not_available_p = 0;
1530 glyph->face_id = it->face_id;
1531 glyph->u.img_id = img->id;
1532 ++it->glyph_row->used[area];
1533 }
1534 }
1535 }
1536
1537
1538 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1539 of the glyph, WIDTH and HEIGHT are the width and height of the
1540 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1541 ascent of the glyph (0 <= ASCENT <= 1). */
1542
1543 static void
1544 x_append_stretch_glyph (it, object, width, height, ascent)
1545 struct it *it;
1546 Lisp_Object object;
1547 int width, height;
1548 double ascent;
1549 {
1550 struct glyph *glyph;
1551 enum glyph_row_area area = it->area;
1552
1553 xassert (ascent >= 0 && ascent <= 1);
1554
1555 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1556 if (glyph < it->glyph_row->glyphs[area + 1])
1557 {
1558 glyph->charpos = CHARPOS (it->position);
1559 glyph->object = object;
1560 glyph->pixel_width = width;
1561 glyph->voffset = it->voffset;
1562 glyph->type = STRETCH_GLYPH;
1563 glyph->multibyte_p = it->multibyte_p;
1564 glyph->left_box_line_p = it->start_of_box_run_p;
1565 glyph->right_box_line_p = it->end_of_box_run_p;
1566 glyph->overlaps_vertically_p = 0;
1567 glyph->padding_p = 0;
1568 glyph->glyph_not_available_p = 0;
1569 glyph->face_id = it->face_id;
1570 glyph->u.stretch.ascent = height * ascent;
1571 glyph->u.stretch.height = height;
1572 ++it->glyph_row->used[area];
1573 }
1574 }
1575
1576
1577 /* Produce a stretch glyph for iterator IT. IT->object is the value
1578 of the glyph property displayed. The value must be a list
1579 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1580 being recognized:
1581
1582 1. `:width WIDTH' specifies that the space should be WIDTH *
1583 canonical char width wide. WIDTH may be an integer or floating
1584 point number.
1585
1586 2. `:relative-width FACTOR' specifies that the width of the stretch
1587 should be computed from the width of the first character having the
1588 `glyph' property, and should be FACTOR times that width.
1589
1590 3. `:align-to HPOS' specifies that the space should be wide enough
1591 to reach HPOS, a value in canonical character units.
1592
1593 Exactly one of the above pairs must be present.
1594
1595 4. `:height HEIGHT' specifies that the height of the stretch produced
1596 should be HEIGHT, measured in canonical character units.
1597
1598 5. `:relative-height FACTOR' specifies that the height of the the
1599 stretch should be FACTOR times the height of the characters having
1600 the glyph property.
1601
1602 Either none or exactly one of 4 or 5 must be present.
1603
1604 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1605 of the stretch should be used for the ascent of the stretch.
1606 ASCENT must be in the range 0 <= ASCENT <= 100. */
1607
1608 #define NUMVAL(X) \
1609 ((INTEGERP (X) || FLOATP (X)) \
1610 ? XFLOATINT (X) \
1611 : - 1)
1612
1613
1614 static void
1615 x_produce_stretch_glyph (it)
1616 struct it *it;
1617 {
1618 /* (space :width WIDTH :height HEIGHT. */
1619 #if GLYPH_DEBUG
1620 extern Lisp_Object Qspace;
1621 #endif
1622 extern Lisp_Object QCwidth, QCheight, QCascent;
1623 extern Lisp_Object QCrelative_width, QCrelative_height;
1624 extern Lisp_Object QCalign_to;
1625 Lisp_Object prop, plist;
1626 double width = 0, height = 0, ascent = 0;
1627 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1628 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1629
1630 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1631
1632 /* List should start with `space'. */
1633 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1634 plist = XCDR (it->object);
1635
1636 /* Compute the width of the stretch. */
1637 if (prop = Fplist_get (plist, QCwidth),
1638 NUMVAL (prop) > 0)
1639 /* Absolute width `:width WIDTH' specified and valid. */
1640 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1641 else if (prop = Fplist_get (plist, QCrelative_width),
1642 NUMVAL (prop) > 0)
1643 {
1644 /* Relative width `:relative-width FACTOR' specified and valid.
1645 Compute the width of the characters having the `glyph'
1646 property. */
1647 struct it it2;
1648 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1649
1650 it2 = *it;
1651 if (it->multibyte_p)
1652 {
1653 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1654 - IT_BYTEPOS (*it));
1655 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1656 }
1657 else
1658 it2.c = *p, it2.len = 1;
1659
1660 it2.glyph_row = NULL;
1661 it2.what = IT_CHARACTER;
1662 x_produce_glyphs (&it2);
1663 width = NUMVAL (prop) * it2.pixel_width;
1664 }
1665 else if (prop = Fplist_get (plist, QCalign_to),
1666 NUMVAL (prop) > 0)
1667 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1668 else
1669 /* Nothing specified -> width defaults to canonical char width. */
1670 width = CANON_X_UNIT (it->f);
1671
1672 /* Compute height. */
1673 if (prop = Fplist_get (plist, QCheight),
1674 NUMVAL (prop) > 0)
1675 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1676 else if (prop = Fplist_get (plist, QCrelative_height),
1677 NUMVAL (prop) > 0)
1678 height = FONT_HEIGHT (font) * NUMVAL (prop);
1679 else
1680 height = FONT_HEIGHT (font);
1681
1682 /* Compute percentage of height used for ascent. If
1683 `:ascent ASCENT' is present and valid, use that. Otherwise,
1684 derive the ascent from the font in use. */
1685 if (prop = Fplist_get (plist, QCascent),
1686 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1687 ascent = NUMVAL (prop) / 100.0;
1688 else
1689 ascent = (double) font->ascent / FONT_HEIGHT (font);
1690
1691 if (width <= 0)
1692 width = 1;
1693 if (height <= 0)
1694 height = 1;
1695
1696 if (it->glyph_row)
1697 {
1698 Lisp_Object object = it->stack[it->sp - 1].string;
1699 if (!STRINGP (object))
1700 object = it->w->buffer;
1701 x_append_stretch_glyph (it, object, width, height, ascent);
1702 }
1703
1704 it->pixel_width = width;
1705 it->ascent = it->phys_ascent = height * ascent;
1706 it->descent = it->phys_descent = height - it->ascent;
1707 it->nglyphs = 1;
1708
1709 if (face->box != FACE_NO_BOX)
1710 {
1711 it->ascent += face->box_line_width;
1712 it->descent += face->box_line_width;
1713
1714 if (it->start_of_box_run_p)
1715 it->pixel_width += face->box_line_width;
1716 if (it->end_of_box_run_p)
1717 it->pixel_width += face->box_line_width;
1718 }
1719
1720 take_vertical_position_into_account (it);
1721 }
1722
1723 /* Return proper value to be used as baseline offset of font that has
1724 ASCENT and DESCENT to draw characters by the font at the vertical
1725 center of the line of frame F.
1726
1727 Here, out task is to find the value of BOFF in the following figure;
1728
1729 -------------------------+-----------+-
1730 -+-+---------+-+ | |
1731 | | | | | |
1732 | | | | F_ASCENT F_HEIGHT
1733 | | | ASCENT | |
1734 HEIGHT | | | | |
1735 | | |-|-+------+-----------|------- baseline
1736 | | | | BOFF | |
1737 | |---------|-+-+ | |
1738 | | | DESCENT | |
1739 -+-+---------+-+ F_DESCENT |
1740 -------------------------+-----------+-
1741
1742 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1743 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1744 DESCENT = FONT->descent
1745 HEIGHT = FONT_HEIGHT (FONT)
1746 F_DESCENT = (F->output_data.x->font->descent
1747 - F->output_data.x->baseline_offset)
1748 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1749 */
1750
1751 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1752 ((FONT)->descent \
1753 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1754 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
1755
1756 /* Produce glyphs/get display metrics for the display element IT is
1757 loaded with. See the description of struct display_iterator in
1758 dispextern.h for an overview of struct display_iterator. */
1759
1760 static void
1761 x_produce_glyphs (it)
1762 struct it *it;
1763 {
1764 it->glyph_not_available_p = 0;
1765
1766 if (it->what == IT_CHARACTER)
1767 {
1768 XChar2b char2b;
1769 XFontStruct *font;
1770 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1771 XCharStruct *pcm;
1772 int font_not_found_p;
1773 struct font_info *font_info;
1774 int boff; /* baseline offset */
1775
1776 /* Maybe translate single-byte characters to multibyte, or the
1777 other way. */
1778 it->char_to_display = it->c;
1779 if (!ASCII_BYTE_P (it->c))
1780 {
1781 if (unibyte_display_via_language_environment
1782 && SINGLE_BYTE_CHAR_P (it->c)
1783 && (it->c >= 0240
1784 || !NILP (Vnonascii_translation_table)))
1785 {
1786 it->char_to_display = unibyte_char_to_multibyte (it->c);
1787 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1788 face = FACE_FROM_ID (it->f, it->face_id);
1789 }
1790 else if (!SINGLE_BYTE_CHAR_P (it->c)
1791 && !it->multibyte_p)
1792 {
1793 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1794 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1795 face = FACE_FROM_ID (it->f, it->face_id);
1796 }
1797 }
1798
1799 /* Get font to use. Encode IT->char_to_display. */
1800 x_get_char_face_and_encoding (it->f, it->char_to_display,
1801 it->face_id, &char2b,
1802 it->multibyte_p);
1803 font = face->font;
1804
1805 /* When no suitable font found, use the default font. */
1806 font_not_found_p = font == NULL;
1807 if (font_not_found_p)
1808 {
1809 font = FRAME_FONT (it->f);
1810 boff = it->f->output_data.x->baseline_offset;
1811 font_info = NULL;
1812 }
1813 else
1814 {
1815 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1816 boff = font_info->baseline_offset;
1817 if (font_info->vertical_centering)
1818 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1819 }
1820
1821 if (it->char_to_display >= ' '
1822 && (!it->multibyte_p || it->char_to_display < 128))
1823 {
1824 /* Either unibyte or ASCII. */
1825 int stretched_p;
1826
1827 it->nglyphs = 1;
1828
1829 pcm = x_per_char_metric (font, &char2b);
1830 it->ascent = font->ascent + boff;
1831 it->descent = font->descent - boff;
1832
1833 if (pcm)
1834 {
1835 it->phys_ascent = pcm->ascent + boff;
1836 it->phys_descent = pcm->descent - boff;
1837 it->pixel_width = pcm->width;
1838 }
1839 else
1840 {
1841 it->glyph_not_available_p = 1;
1842 it->phys_ascent = font->ascent + boff;
1843 it->phys_descent = font->descent - boff;
1844 it->pixel_width = FONT_WIDTH (font);
1845 }
1846
1847 /* If this is a space inside a region of text with
1848 `space-width' property, change its width. */
1849 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1850 if (stretched_p)
1851 it->pixel_width *= XFLOATINT (it->space_width);
1852
1853 /* If face has a box, add the box thickness to the character
1854 height. If character has a box line to the left and/or
1855 right, add the box line width to the character's width. */
1856 if (face->box != FACE_NO_BOX)
1857 {
1858 int thick = face->box_line_width;
1859
1860 it->ascent += thick;
1861 it->descent += thick;
1862
1863 if (it->start_of_box_run_p)
1864 it->pixel_width += thick;
1865 if (it->end_of_box_run_p)
1866 it->pixel_width += thick;
1867 }
1868
1869 /* If face has an overline, add the height of the overline
1870 (1 pixel) and a 1 pixel margin to the character height. */
1871 if (face->overline_p)
1872 it->ascent += 2;
1873
1874 take_vertical_position_into_account (it);
1875
1876 /* If we have to actually produce glyphs, do it. */
1877 if (it->glyph_row)
1878 {
1879 if (stretched_p)
1880 {
1881 /* Translate a space with a `space-width' property
1882 into a stretch glyph. */
1883 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1884 x_append_stretch_glyph (it, it->object, it->pixel_width,
1885 it->ascent + it->descent, ascent);
1886 }
1887 else
1888 x_append_glyph (it);
1889
1890 /* If characters with lbearing or rbearing are displayed
1891 in this line, record that fact in a flag of the
1892 glyph row. This is used to optimize X output code. */
1893 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
1894 it->glyph_row->contains_overlapping_glyphs_p = 1;
1895 }
1896 }
1897 else if (it->char_to_display == '\n')
1898 {
1899 /* A newline has no width but we need the height of the line. */
1900 it->pixel_width = 0;
1901 it->nglyphs = 0;
1902 it->ascent = it->phys_ascent = font->ascent + boff;
1903 it->descent = it->phys_descent = font->descent - boff;
1904
1905 if (face->box != FACE_NO_BOX)
1906 {
1907 int thick = face->box_line_width;
1908 it->ascent += thick;
1909 it->descent += thick;
1910 }
1911 }
1912 else if (it->char_to_display == '\t')
1913 {
1914 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1915 int x = it->current_x + it->continuation_lines_width;
1916 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1917
1918 it->pixel_width = next_tab_x - x;
1919 it->nglyphs = 1;
1920 it->ascent = it->phys_ascent = font->ascent + boff;
1921 it->descent = it->phys_descent = font->descent - boff;
1922
1923 if (it->glyph_row)
1924 {
1925 double ascent = (double) it->ascent / (it->ascent + it->descent);
1926 x_append_stretch_glyph (it, it->object, it->pixel_width,
1927 it->ascent + it->descent, ascent);
1928 }
1929 }
1930 else
1931 {
1932 /* A multi-byte character. Assume that the display width of the
1933 character is the width of the character multiplied by the
1934 width of the font. */
1935
1936 /* If we found a font, this font should give us the right
1937 metrics. If we didn't find a font, use the frame's
1938 default font and calculate the width of the character
1939 from the charset width; this is what old redisplay code
1940 did. */
1941 pcm = x_per_char_metric (font, &char2b);
1942 if (font_not_found_p || !pcm)
1943 {
1944 int charset = CHAR_CHARSET (it->char_to_display);
1945
1946 it->glyph_not_available_p = 1;
1947 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1948 * CHARSET_WIDTH (charset));
1949 it->phys_ascent = font->ascent + boff;
1950 it->phys_descent = font->descent - boff;
1951 }
1952 else
1953 {
1954 it->pixel_width = pcm->width;
1955 it->phys_ascent = pcm->ascent + boff;
1956 it->phys_descent = pcm->descent - boff;
1957 if (it->glyph_row
1958 && (pcm->lbearing < 0
1959 || pcm->rbearing > pcm->width))
1960 it->glyph_row->contains_overlapping_glyphs_p = 1;
1961 }
1962 it->nglyphs = 1;
1963 it->ascent = font->ascent + boff;
1964 it->descent = font->descent - boff;
1965 if (face->box != FACE_NO_BOX)
1966 {
1967 int thick = face->box_line_width;
1968 it->ascent += thick;
1969 it->descent += thick;
1970
1971 if (it->start_of_box_run_p)
1972 it->pixel_width += thick;
1973 if (it->end_of_box_run_p)
1974 it->pixel_width += thick;
1975 }
1976
1977 /* If face has an overline, add the height of the overline
1978 (1 pixel) and a 1 pixel margin to the character height. */
1979 if (face->overline_p)
1980 it->ascent += 2;
1981
1982 take_vertical_position_into_account (it);
1983
1984 if (it->glyph_row)
1985 x_append_glyph (it);
1986 }
1987 }
1988 else if (it->what == IT_COMPOSITION)
1989 {
1990 /* Note: A composition is represented as one glyph in the
1991 glyph matrix. There are no padding glyphs. */
1992 XChar2b char2b;
1993 XFontStruct *font;
1994 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1995 XCharStruct *pcm;
1996 int font_not_found_p;
1997 struct font_info *font_info;
1998 int boff; /* baseline offset */
1999 struct composition *cmp = composition_table[it->cmp_id];
2000
2001 /* Maybe translate single-byte characters to multibyte. */
2002 it->char_to_display = it->c;
2003 if (unibyte_display_via_language_environment
2004 && SINGLE_BYTE_CHAR_P (it->c)
2005 && (it->c >= 0240
2006 || (it->c >= 0200
2007 && !NILP (Vnonascii_translation_table))))
2008 {
2009 it->char_to_display = unibyte_char_to_multibyte (it->c);
2010 }
2011
2012 /* Get face and font to use. Encode IT->char_to_display. */
2013 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2014 face = FACE_FROM_ID (it->f, it->face_id);
2015 x_get_char_face_and_encoding (it->f, it->char_to_display,
2016 it->face_id, &char2b, it->multibyte_p);
2017 font = face->font;
2018
2019 /* When no suitable font found, use the default font. */
2020 font_not_found_p = font == NULL;
2021 if (font_not_found_p)
2022 {
2023 font = FRAME_FONT (it->f);
2024 boff = it->f->output_data.x->baseline_offset;
2025 font_info = NULL;
2026 }
2027 else
2028 {
2029 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2030 boff = font_info->baseline_offset;
2031 if (font_info->vertical_centering)
2032 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2033 }
2034
2035 /* There are no padding glyphs, so there is only one glyph to
2036 produce for the composition. Important is that pixel_width,
2037 ascent and descent are the values of what is drawn by
2038 draw_glyphs (i.e. the values of the overall glyphs composed). */
2039 it->nglyphs = 1;
2040
2041 /* If we have not yet calculated pixel size data of glyphs of
2042 the composition for the current face font, calculate them
2043 now. Theoretically, we have to check all fonts for the
2044 glyphs, but that requires much time and memory space. So,
2045 here we check only the font of the first glyph. This leads
2046 to incorrect display very rarely, and C-l (recenter) can
2047 correct the display anyway. */
2048 if (cmp->font != (void *) font)
2049 {
2050 /* Ascent and descent of the font of the first character of
2051 this composition (adjusted by baseline offset). Ascent
2052 and descent of overall glyphs should not be less than
2053 them respectively. */
2054 int font_ascent = font->ascent + boff;
2055 int font_descent = font->descent - boff;
2056 /* Bounding box of the overall glyphs. */
2057 int leftmost, rightmost, lowest, highest;
2058 int i, width, ascent, descent;
2059
2060 cmp->font = (void *) font;
2061
2062 /* Initialize the bounding box. */
2063 pcm = x_per_char_metric (font, &char2b);
2064 if (pcm)
2065 {
2066 width = pcm->width;
2067 ascent = pcm->ascent;
2068 descent = pcm->descent;
2069 }
2070 else
2071 {
2072 width = FONT_WIDTH (font);
2073 ascent = font->ascent;
2074 descent = font->descent;
2075 }
2076
2077 rightmost = width;
2078 lowest = - descent + boff;
2079 highest = ascent + boff;
2080 leftmost = 0;
2081
2082 if (font_info
2083 && font_info->default_ascent
2084 && CHAR_TABLE_P (Vuse_default_ascent)
2085 && !NILP (Faref (Vuse_default_ascent,
2086 make_number (it->char_to_display))))
2087 highest = font_info->default_ascent + boff;
2088
2089 /* Draw the first glyph at the normal position. It may be
2090 shifted to right later if some other glyphs are drawn at
2091 the left. */
2092 cmp->offsets[0] = 0;
2093 cmp->offsets[1] = boff;
2094
2095 /* Set cmp->offsets for the remaining glyphs. */
2096 for (i = 1; i < cmp->glyph_len; i++)
2097 {
2098 int left, right, btm, top;
2099 int ch = COMPOSITION_GLYPH (cmp, i);
2100 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2101
2102 face = FACE_FROM_ID (it->f, face_id);
2103 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2104 it->multibyte_p);
2105 font = face->font;
2106 if (font == NULL)
2107 {
2108 font = FRAME_FONT (it->f);
2109 boff = it->f->output_data.x->baseline_offset;
2110 font_info = NULL;
2111 }
2112 else
2113 {
2114 font_info
2115 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2116 boff = font_info->baseline_offset;
2117 if (font_info->vertical_centering)
2118 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2119 }
2120
2121 pcm = x_per_char_metric (font, &char2b);
2122 if (pcm)
2123 {
2124 width = pcm->width;
2125 ascent = pcm->ascent;
2126 descent = pcm->descent;
2127 }
2128 else
2129 {
2130 width = FONT_WIDTH (font);
2131 ascent = font->ascent;
2132 descent = font->descent;
2133 }
2134
2135 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2136 {
2137 /* Relative composition with or without
2138 alternate chars. */
2139 left = (leftmost + rightmost - width) / 2;
2140 btm = - descent + boff;
2141 if (font_info && font_info->relative_compose
2142 && (! CHAR_TABLE_P (Vignore_relative_composition)
2143 || NILP (Faref (Vignore_relative_composition,
2144 make_number (ch)))))
2145 {
2146
2147 if (- descent >= font_info->relative_compose)
2148 /* One extra pixel between two glyphs. */
2149 btm = highest + 1;
2150 else if (ascent <= 0)
2151 /* One extra pixel between two glyphs. */
2152 btm = lowest - 1 - ascent - descent;
2153 }
2154 }
2155 else
2156 {
2157 /* A composition rule is specified by an integer
2158 value that encodes global and new reference
2159 points (GREF and NREF). GREF and NREF are
2160 specified by numbers as below:
2161
2162 0---1---2 -- ascent
2163 | |
2164 | |
2165 | |
2166 9--10--11 -- center
2167 | |
2168 ---3---4---5--- baseline
2169 | |
2170 6---7---8 -- descent
2171 */
2172 int rule = COMPOSITION_RULE (cmp, i);
2173 int gref, nref, grefx, grefy, nrefx, nrefy;
2174
2175 COMPOSITION_DECODE_RULE (rule, gref, nref);
2176 grefx = gref % 3, nrefx = nref % 3;
2177 grefy = gref / 3, nrefy = nref / 3;
2178
2179 left = (leftmost
2180 + grefx * (rightmost - leftmost) / 2
2181 - nrefx * width / 2);
2182 btm = ((grefy == 0 ? highest
2183 : grefy == 1 ? 0
2184 : grefy == 2 ? lowest
2185 : (highest + lowest) / 2)
2186 - (nrefy == 0 ? ascent + descent
2187 : nrefy == 1 ? descent - boff
2188 : nrefy == 2 ? 0
2189 : (ascent + descent) / 2));
2190 }
2191
2192 cmp->offsets[i * 2] = left;
2193 cmp->offsets[i * 2 + 1] = btm + descent;
2194
2195 /* Update the bounding box of the overall glyphs. */
2196 right = left + width;
2197 top = btm + descent + ascent;
2198 if (left < leftmost)
2199 leftmost = left;
2200 if (right > rightmost)
2201 rightmost = right;
2202 if (top > highest)
2203 highest = top;
2204 if (btm < lowest)
2205 lowest = btm;
2206 }
2207
2208 /* If there are glyphs whose x-offsets are negative,
2209 shift all glyphs to the right and make all x-offsets
2210 non-negative. */
2211 if (leftmost < 0)
2212 {
2213 for (i = 0; i < cmp->glyph_len; i++)
2214 cmp->offsets[i * 2] -= leftmost;
2215 rightmost -= leftmost;
2216 }
2217
2218 cmp->pixel_width = rightmost;
2219 cmp->ascent = highest;
2220 cmp->descent = - lowest;
2221 if (cmp->ascent < font_ascent)
2222 cmp->ascent = font_ascent;
2223 if (cmp->descent < font_descent)
2224 cmp->descent = font_descent;
2225 }
2226
2227 it->pixel_width = cmp->pixel_width;
2228 it->ascent = it->phys_ascent = cmp->ascent;
2229 it->descent = it->phys_descent = cmp->descent;
2230
2231 if (face->box != FACE_NO_BOX)
2232 {
2233 int thick = face->box_line_width;
2234 it->ascent += thick;
2235 it->descent += thick;
2236
2237 if (it->start_of_box_run_p)
2238 it->pixel_width += thick;
2239 if (it->end_of_box_run_p)
2240 it->pixel_width += thick;
2241 }
2242
2243 /* If face has an overline, add the height of the overline
2244 (1 pixel) and a 1 pixel margin to the character height. */
2245 if (face->overline_p)
2246 it->ascent += 2;
2247
2248 take_vertical_position_into_account (it);
2249
2250 if (it->glyph_row)
2251 x_append_composite_glyph (it);
2252 }
2253 else if (it->what == IT_IMAGE)
2254 x_produce_image_glyph (it);
2255 else if (it->what == IT_STRETCH)
2256 x_produce_stretch_glyph (it);
2257
2258 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2259 because this isn't true for images with `:ascent 100'. */
2260 xassert (it->ascent >= 0 && it->descent >= 0);
2261 if (it->area == TEXT_AREA)
2262 it->current_x += it->pixel_width;
2263
2264 it->descent += it->extra_line_spacing;
2265
2266 it->max_ascent = max (it->max_ascent, it->ascent);
2267 it->max_descent = max (it->max_descent, it->descent);
2268 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2269 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2270 }
2271
2272
2273 /* Estimate the pixel height of the mode or top line on frame F.
2274 FACE_ID specifies what line's height to estimate. */
2275
2276 int
2277 x_estimate_mode_line_height (f, face_id)
2278 struct frame *f;
2279 enum face_id face_id;
2280 {
2281 int height = 1;
2282
2283 /* This function is called so early when Emacs starts that the face
2284 cache and mode line face are not yet initialized. */
2285 if (FRAME_FACE_CACHE (f))
2286 {
2287 struct face *face = FACE_FROM_ID (f, face_id);
2288 if (face)
2289 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2290 }
2291
2292 return height;
2293 }
2294
2295 \f
2296 /***********************************************************************
2297 Glyph display
2298 ***********************************************************************/
2299
2300 /* A sequence of glyphs to be drawn in the same face.
2301
2302 This data structure is not really completely X specific, so it
2303 could possibly, at least partially, be useful for other systems. It
2304 is currently not part of the external redisplay interface because
2305 it's not clear what other systems will need. */
2306
2307 struct glyph_string
2308 {
2309 /* X-origin of the string. */
2310 int x;
2311
2312 /* Y-origin and y-position of the base line of this string. */
2313 int y, ybase;
2314
2315 /* The width of the string, not including a face extension. */
2316 int width;
2317
2318 /* The width of the string, including a face extension. */
2319 int background_width;
2320
2321 /* The height of this string. This is the height of the line this
2322 string is drawn in, and can be different from the height of the
2323 font the string is drawn in. */
2324 int height;
2325
2326 /* Number of pixels this string overwrites in front of its x-origin.
2327 This number is zero if the string has an lbearing >= 0; it is
2328 -lbearing, if the string has an lbearing < 0. */
2329 int left_overhang;
2330
2331 /* Number of pixels this string overwrites past its right-most
2332 nominal x-position, i.e. x + width. Zero if the string's
2333 rbearing is <= its nominal width, rbearing - width otherwise. */
2334 int right_overhang;
2335
2336 /* The frame on which the glyph string is drawn. */
2337 struct frame *f;
2338
2339 /* The window on which the glyph string is drawn. */
2340 struct window *w;
2341
2342 /* X display and window for convenience. */
2343 Display *display;
2344 Window window;
2345
2346 /* The glyph row for which this string was built. It determines the
2347 y-origin and height of the string. */
2348 struct glyph_row *row;
2349
2350 /* The area within row. */
2351 enum glyph_row_area area;
2352
2353 /* Characters to be drawn, and number of characters. */
2354 XChar2b *char2b;
2355 int nchars;
2356
2357 /* A face-override for drawing cursors, mouse face and similar. */
2358 enum draw_glyphs_face hl;
2359
2360 /* Face in which this string is to be drawn. */
2361 struct face *face;
2362
2363 /* Font in which this string is to be drawn. */
2364 XFontStruct *font;
2365
2366 /* Font info for this string. */
2367 struct font_info *font_info;
2368
2369 /* Non-null means this string describes (part of) a composition.
2370 All characters from char2b are drawn composed. */
2371 struct composition *cmp;
2372
2373 /* Index of this glyph string's first character in the glyph
2374 definition of CMP. If this is zero, this glyph string describes
2375 the first character of a composition. */
2376 int gidx;
2377
2378 /* 1 means this glyph strings face has to be drawn to the right end
2379 of the window's drawing area. */
2380 unsigned extends_to_end_of_line_p : 1;
2381
2382 /* 1 means the background of this string has been drawn. */
2383 unsigned background_filled_p : 1;
2384
2385 /* 1 means glyph string must be drawn with 16-bit functions. */
2386 unsigned two_byte_p : 1;
2387
2388 /* 1 means that the original font determined for drawing this glyph
2389 string could not be loaded. The member `font' has been set to
2390 the frame's default font in this case. */
2391 unsigned font_not_found_p : 1;
2392
2393 /* 1 means that the face in which this glyph string is drawn has a
2394 stipple pattern. */
2395 unsigned stippled_p : 1;
2396
2397 /* 1 means only the foreground of this glyph string must be drawn,
2398 and we should use the physical height of the line this glyph
2399 string appears in as clip rect. */
2400 unsigned for_overlaps_p : 1;
2401
2402 /* The GC to use for drawing this glyph string. */
2403 GC gc;
2404
2405 /* A pointer to the first glyph in the string. This glyph
2406 corresponds to char2b[0]. Needed to draw rectangles if
2407 font_not_found_p is 1. */
2408 struct glyph *first_glyph;
2409
2410 /* Image, if any. */
2411 struct image *img;
2412
2413 struct glyph_string *next, *prev;
2414 };
2415
2416
2417 #if 0
2418
2419 static void
2420 x_dump_glyph_string (s)
2421 struct glyph_string *s;
2422 {
2423 fprintf (stderr, "glyph string\n");
2424 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2425 s->x, s->y, s->width, s->height);
2426 fprintf (stderr, " ybase = %d\n", s->ybase);
2427 fprintf (stderr, " hl = %d\n", s->hl);
2428 fprintf (stderr, " left overhang = %d, right = %d\n",
2429 s->left_overhang, s->right_overhang);
2430 fprintf (stderr, " nchars = %d\n", s->nchars);
2431 fprintf (stderr, " extends to end of line = %d\n",
2432 s->extends_to_end_of_line_p);
2433 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2434 fprintf (stderr, " bg width = %d\n", s->background_width);
2435 }
2436
2437 #endif /* GLYPH_DEBUG */
2438
2439
2440
2441 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2442 struct glyph_string **,
2443 struct glyph_string *,
2444 struct glyph_string *));
2445 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2446 struct glyph_string **,
2447 struct glyph_string *,
2448 struct glyph_string *));
2449 static void x_append_glyph_string P_ ((struct glyph_string **,
2450 struct glyph_string **,
2451 struct glyph_string *));
2452 static int x_left_overwritten P_ ((struct glyph_string *));
2453 static int x_left_overwriting P_ ((struct glyph_string *));
2454 static int x_right_overwritten P_ ((struct glyph_string *));
2455 static int x_right_overwriting P_ ((struct glyph_string *));
2456 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2457 int));
2458 static void x_init_glyph_string P_ ((struct glyph_string *,
2459 XChar2b *, struct window *,
2460 struct glyph_row *,
2461 enum glyph_row_area, int,
2462 enum draw_glyphs_face));
2463 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2464 enum glyph_row_area, int, int,
2465 enum draw_glyphs_face, int *, int *, int));
2466 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2467 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2468 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2469 int));
2470 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2471 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2472 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2473 static void x_draw_glyph_string P_ ((struct glyph_string *));
2474 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2475 static void x_set_cursor_gc P_ ((struct glyph_string *));
2476 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2477 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2478 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2479 int *, int *));
2480 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2481 static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2482 unsigned long *, double, int));
2483 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2484 double, int, unsigned long));
2485 static void x_setup_relief_colors P_ ((struct glyph_string *));
2486 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2487 static void x_draw_image_relief P_ ((struct glyph_string *));
2488 static void x_draw_image_foreground P_ ((struct glyph_string *));
2489 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2490 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2491 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2492 int, int, int));
2493 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2494 int, int, int, int, XRectangle *));
2495 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2496 int, int, int, XRectangle *));
2497 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2498 enum glyph_row_area));
2499 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2500 struct glyph_row *,
2501 enum glyph_row_area, int, int));
2502
2503 #if GLYPH_DEBUG
2504 static void x_check_font P_ ((struct frame *, XFontStruct *));
2505 #endif
2506
2507
2508 /* Append the list of glyph strings with head H and tail T to the list
2509 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2510
2511 static INLINE void
2512 x_append_glyph_string_lists (head, tail, h, t)
2513 struct glyph_string **head, **tail;
2514 struct glyph_string *h, *t;
2515 {
2516 if (h)
2517 {
2518 if (*head)
2519 (*tail)->next = h;
2520 else
2521 *head = h;
2522 h->prev = *tail;
2523 *tail = t;
2524 }
2525 }
2526
2527
2528 /* Prepend the list of glyph strings with head H and tail T to the
2529 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2530 result. */
2531
2532 static INLINE void
2533 x_prepend_glyph_string_lists (head, tail, h, t)
2534 struct glyph_string **head, **tail;
2535 struct glyph_string *h, *t;
2536 {
2537 if (h)
2538 {
2539 if (*head)
2540 (*head)->prev = t;
2541 else
2542 *tail = t;
2543 t->next = *head;
2544 *head = h;
2545 }
2546 }
2547
2548
2549 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2550 Set *HEAD and *TAIL to the resulting list. */
2551
2552 static INLINE void
2553 x_append_glyph_string (head, tail, s)
2554 struct glyph_string **head, **tail;
2555 struct glyph_string *s;
2556 {
2557 s->next = s->prev = NULL;
2558 x_append_glyph_string_lists (head, tail, s, s);
2559 }
2560
2561
2562 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2563 face. */
2564
2565 static void
2566 x_set_cursor_gc (s)
2567 struct glyph_string *s;
2568 {
2569 if (s->font == FRAME_FONT (s->f)
2570 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2571 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2572 && !s->cmp)
2573 s->gc = s->f->output_data.x->cursor_gc;
2574 else
2575 {
2576 /* Cursor on non-default face: must merge. */
2577 XGCValues xgcv;
2578 unsigned long mask;
2579
2580 xgcv.background = s->f->output_data.x->cursor_pixel;
2581 xgcv.foreground = s->face->background;
2582
2583 /* If the glyph would be invisible, try a different foreground. */
2584 if (xgcv.foreground == xgcv.background)
2585 xgcv.foreground = s->face->foreground;
2586 if (xgcv.foreground == xgcv.background)
2587 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2588 if (xgcv.foreground == xgcv.background)
2589 xgcv.foreground = s->face->foreground;
2590
2591 /* Make sure the cursor is distinct from text in this face. */
2592 if (xgcv.background == s->face->background
2593 && xgcv.foreground == s->face->foreground)
2594 {
2595 xgcv.background = s->face->foreground;
2596 xgcv.foreground = s->face->background;
2597 }
2598
2599 IF_DEBUG (x_check_font (s->f, s->font));
2600 xgcv.font = s->font->fid;
2601 xgcv.graphics_exposures = False;
2602 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2603
2604 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2605 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2606 mask, &xgcv);
2607 else
2608 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2609 = XCreateGC (s->display, s->window, mask, &xgcv);
2610
2611 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2612 }
2613 }
2614
2615
2616 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2617
2618 static void
2619 x_set_mouse_face_gc (s)
2620 struct glyph_string *s;
2621 {
2622 int face_id;
2623 struct face *face;
2624
2625 /* What face has to be used for the mouse face? */
2626 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2627 face = FACE_FROM_ID (s->f, face_id);
2628 if (s->first_glyph->type == CHAR_GLYPH)
2629 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2630 else
2631 face_id = FACE_FOR_CHAR (s->f, face, 0);
2632 s->face = FACE_FROM_ID (s->f, face_id);
2633 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2634
2635 /* If font in this face is same as S->font, use it. */
2636 if (s->font == s->face->font)
2637 s->gc = s->face->gc;
2638 else
2639 {
2640 /* Otherwise construct scratch_cursor_gc with values from FACE
2641 but font FONT. */
2642 XGCValues xgcv;
2643 unsigned long mask;
2644
2645 xgcv.background = s->face->background;
2646 xgcv.foreground = s->face->foreground;
2647 IF_DEBUG (x_check_font (s->f, s->font));
2648 xgcv.font = s->font->fid;
2649 xgcv.graphics_exposures = False;
2650 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2651
2652 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2653 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2654 mask, &xgcv);
2655 else
2656 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2657 = XCreateGC (s->display, s->window, mask, &xgcv);
2658
2659 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2660 }
2661
2662 xassert (s->gc != 0);
2663 }
2664
2665
2666 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2667 Faces to use in the mode line have already been computed when the
2668 matrix was built, so there isn't much to do, here. */
2669
2670 static INLINE void
2671 x_set_mode_line_face_gc (s)
2672 struct glyph_string *s;
2673 {
2674 s->gc = s->face->gc;
2675 }
2676
2677
2678 /* Set S->gc of glyph string S for drawing that glyph string. Set
2679 S->stippled_p to a non-zero value if the face of S has a stipple
2680 pattern. */
2681
2682 static INLINE void
2683 x_set_glyph_string_gc (s)
2684 struct glyph_string *s;
2685 {
2686 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2687
2688 if (s->hl == DRAW_NORMAL_TEXT)
2689 {
2690 s->gc = s->face->gc;
2691 s->stippled_p = s->face->stipple != 0;
2692 }
2693 else if (s->hl == DRAW_INVERSE_VIDEO)
2694 {
2695 x_set_mode_line_face_gc (s);
2696 s->stippled_p = s->face->stipple != 0;
2697 }
2698 else if (s->hl == DRAW_CURSOR)
2699 {
2700 x_set_cursor_gc (s);
2701 s->stippled_p = 0;
2702 }
2703 else if (s->hl == DRAW_MOUSE_FACE)
2704 {
2705 x_set_mouse_face_gc (s);
2706 s->stippled_p = s->face->stipple != 0;
2707 }
2708 else if (s->hl == DRAW_IMAGE_RAISED
2709 || s->hl == DRAW_IMAGE_SUNKEN)
2710 {
2711 s->gc = s->face->gc;
2712 s->stippled_p = s->face->stipple != 0;
2713 }
2714 else
2715 {
2716 s->gc = s->face->gc;
2717 s->stippled_p = s->face->stipple != 0;
2718 }
2719
2720 /* GC must have been set. */
2721 xassert (s->gc != 0);
2722 }
2723
2724
2725 /* Return in *R the clipping rectangle for glyph string S. */
2726
2727 static void
2728 x_get_glyph_string_clip_rect (s, r)
2729 struct glyph_string *s;
2730 XRectangle *r;
2731 {
2732 if (s->row->full_width_p)
2733 {
2734 /* Draw full-width. X coordinates are relative to S->w->left. */
2735 int canon_x = CANON_X_UNIT (s->f);
2736
2737 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2738 r->width = XFASTINT (s->w->width) * canon_x;
2739
2740 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2741 {
2742 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2743 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2744 r->x -= width;
2745 }
2746
2747 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2748
2749 /* Unless displaying a mode or menu bar line, which are always
2750 fully visible, clip to the visible part of the row. */
2751 if (s->w->pseudo_window_p)
2752 r->height = s->row->visible_height;
2753 else
2754 r->height = s->height;
2755 }
2756 else
2757 {
2758 /* This is a text line that may be partially visible. */
2759 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2760 r->width = window_box_width (s->w, s->area);
2761 r->height = s->row->visible_height;
2762 }
2763
2764 /* Don't use S->y for clipping because it doesn't take partially
2765 visible lines into account. For example, it can be negative for
2766 partially visible lines at the top of a window. */
2767 if (!s->row->full_width_p
2768 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2769 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2770 else
2771 r->y = max (0, s->row->y);
2772
2773 /* If drawing a tool-bar window, draw it over the internal border
2774 at the top of the window. */
2775 if (s->w == XWINDOW (s->f->tool_bar_window))
2776 r->y -= s->f->output_data.x->internal_border_width;
2777
2778 /* If S draws overlapping rows, it's sufficient to use the top and
2779 bottom of the window for clipping because this glyph string
2780 intentionally draws over other lines. */
2781 if (s->for_overlaps_p)
2782 {
2783 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2784 r->height = window_text_bottom_y (s->w) - r->y;
2785 }
2786
2787 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2788 }
2789
2790
2791 /* Set clipping for output of glyph string S. S may be part of a mode
2792 line or menu if we don't have X toolkit support. */
2793
2794 static INLINE void
2795 x_set_glyph_string_clipping (s)
2796 struct glyph_string *s;
2797 {
2798 XRectangle r;
2799 x_get_glyph_string_clip_rect (s, &r);
2800 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2801 }
2802
2803
2804 /* Compute left and right overhang of glyph string S. If S is a glyph
2805 string for a composition, assume overhangs don't exist. */
2806
2807 static INLINE void
2808 x_compute_glyph_string_overhangs (s)
2809 struct glyph_string *s;
2810 {
2811 if (s->cmp == NULL
2812 && s->first_glyph->type == CHAR_GLYPH)
2813 {
2814 XCharStruct cs;
2815 int direction, font_ascent, font_descent;
2816 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2817 &font_ascent, &font_descent, &cs);
2818 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2819 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2820 }
2821 }
2822
2823
2824 /* Compute overhangs and x-positions for glyph string S and its
2825 predecessors, or successors. X is the starting x-position for S.
2826 BACKWARD_P non-zero means process predecessors. */
2827
2828 static void
2829 x_compute_overhangs_and_x (s, x, backward_p)
2830 struct glyph_string *s;
2831 int x;
2832 int backward_p;
2833 {
2834 if (backward_p)
2835 {
2836 while (s)
2837 {
2838 x_compute_glyph_string_overhangs (s);
2839 x -= s->width;
2840 s->x = x;
2841 s = s->prev;
2842 }
2843 }
2844 else
2845 {
2846 while (s)
2847 {
2848 x_compute_glyph_string_overhangs (s);
2849 s->x = x;
2850 x += s->width;
2851 s = s->next;
2852 }
2853 }
2854 }
2855
2856
2857 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2858 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2859 assumed to be zero. */
2860
2861 static void
2862 x_get_glyph_overhangs (glyph, f, left, right)
2863 struct glyph *glyph;
2864 struct frame *f;
2865 int *left, *right;
2866 {
2867 *left = *right = 0;
2868
2869 if (glyph->type == CHAR_GLYPH)
2870 {
2871 XFontStruct *font;
2872 struct face *face;
2873 struct font_info *font_info;
2874 XChar2b char2b;
2875 XCharStruct *pcm;
2876
2877 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2878 font = face->font;
2879 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2880 if (font
2881 && (pcm = x_per_char_metric (font, &char2b)))
2882 {
2883 if (pcm->rbearing > pcm->width)
2884 *right = pcm->rbearing - pcm->width;
2885 if (pcm->lbearing < 0)
2886 *left = -pcm->lbearing;
2887 }
2888 }
2889 }
2890
2891
2892 /* Return the index of the first glyph preceding glyph string S that
2893 is overwritten by S because of S's left overhang. Value is -1
2894 if no glyphs are overwritten. */
2895
2896 static int
2897 x_left_overwritten (s)
2898 struct glyph_string *s;
2899 {
2900 int k;
2901
2902 if (s->left_overhang)
2903 {
2904 int x = 0, i;
2905 struct glyph *glyphs = s->row->glyphs[s->area];
2906 int first = s->first_glyph - glyphs;
2907
2908 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2909 x -= glyphs[i].pixel_width;
2910
2911 k = i + 1;
2912 }
2913 else
2914 k = -1;
2915
2916 return k;
2917 }
2918
2919
2920 /* Return the index of the first glyph preceding glyph string S that
2921 is overwriting S because of its right overhang. Value is -1 if no
2922 glyph in front of S overwrites S. */
2923
2924 static int
2925 x_left_overwriting (s)
2926 struct glyph_string *s;
2927 {
2928 int i, k, x;
2929 struct glyph *glyphs = s->row->glyphs[s->area];
2930 int first = s->first_glyph - glyphs;
2931
2932 k = -1;
2933 x = 0;
2934 for (i = first - 1; i >= 0; --i)
2935 {
2936 int left, right;
2937 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2938 if (x + right > 0)
2939 k = i;
2940 x -= glyphs[i].pixel_width;
2941 }
2942
2943 return k;
2944 }
2945
2946
2947 /* Return the index of the last glyph following glyph string S that is
2948 not overwritten by S because of S's right overhang. Value is -1 if
2949 no such glyph is found. */
2950
2951 static int
2952 x_right_overwritten (s)
2953 struct glyph_string *s;
2954 {
2955 int k = -1;
2956
2957 if (s->right_overhang)
2958 {
2959 int x = 0, i;
2960 struct glyph *glyphs = s->row->glyphs[s->area];
2961 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2962 int end = s->row->used[s->area];
2963
2964 for (i = first; i < end && s->right_overhang > x; ++i)
2965 x += glyphs[i].pixel_width;
2966
2967 k = i;
2968 }
2969
2970 return k;
2971 }
2972
2973
2974 /* Return the index of the last glyph following glyph string S that
2975 overwrites S because of its left overhang. Value is negative
2976 if no such glyph is found. */
2977
2978 static int
2979 x_right_overwriting (s)
2980 struct glyph_string *s;
2981 {
2982 int i, k, x;
2983 int end = s->row->used[s->area];
2984 struct glyph *glyphs = s->row->glyphs[s->area];
2985 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2986
2987 k = -1;
2988 x = 0;
2989 for (i = first; i < end; ++i)
2990 {
2991 int left, right;
2992 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2993 if (x - left < 0)
2994 k = i;
2995 x += glyphs[i].pixel_width;
2996 }
2997
2998 return k;
2999 }
3000
3001
3002 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3003
3004 static INLINE void
3005 x_clear_glyph_string_rect (s, x, y, w, h)
3006 struct glyph_string *s;
3007 int x, y, w, h;
3008 {
3009 XGCValues xgcv;
3010 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3011 XSetForeground (s->display, s->gc, xgcv.background);
3012 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3013 XSetForeground (s->display, s->gc, xgcv.foreground);
3014 }
3015
3016
3017 /* Draw the background of glyph_string S. If S->background_filled_p
3018 is non-zero don't draw it. FORCE_P non-zero means draw the
3019 background even if it wouldn't be drawn normally. This is used
3020 when a string preceding S draws into the background of S, or S
3021 contains the first component of a composition. */
3022
3023 static void
3024 x_draw_glyph_string_background (s, force_p)
3025 struct glyph_string *s;
3026 int force_p;
3027 {
3028 /* Nothing to do if background has already been drawn or if it
3029 shouldn't be drawn in the first place. */
3030 if (!s->background_filled_p)
3031 {
3032 if (s->stippled_p)
3033 {
3034 /* Fill background with a stipple pattern. */
3035 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3036 XFillRectangle (s->display, s->window, s->gc, s->x,
3037 s->y + s->face->box_line_width,
3038 s->background_width,
3039 s->height - 2 * s->face->box_line_width);
3040 XSetFillStyle (s->display, s->gc, FillSolid);
3041 s->background_filled_p = 1;
3042 }
3043 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3044 || s->font_not_found_p
3045 || s->extends_to_end_of_line_p
3046 || force_p)
3047 {
3048 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3049 s->background_width,
3050 s->height - 2 * s->face->box_line_width);
3051 s->background_filled_p = 1;
3052 }
3053 }
3054 }
3055
3056
3057 /* Draw the foreground of glyph string S. */
3058
3059 static void
3060 x_draw_glyph_string_foreground (s)
3061 struct glyph_string *s;
3062 {
3063 int i, x;
3064
3065 /* If first glyph of S has a left box line, start drawing the text
3066 of S to the right of that box line. */
3067 if (s->face->box != FACE_NO_BOX
3068 && s->first_glyph->left_box_line_p)
3069 x = s->x + s->face->box_line_width;
3070 else
3071 x = s->x;
3072
3073 /* Draw characters of S as rectangles if S's font could not be
3074 loaded. */
3075 if (s->font_not_found_p)
3076 {
3077 for (i = 0; i < s->nchars; ++i)
3078 {
3079 struct glyph *g = s->first_glyph + i;
3080 XDrawRectangle (s->display, s->window,
3081 s->gc, x, s->y, g->pixel_width - 1,
3082 s->height - 1);
3083 x += g->pixel_width;
3084 }
3085 }
3086 else
3087 {
3088 char *char1b = (char *) s->char2b;
3089 int boff = s->font_info->baseline_offset;
3090
3091 if (s->font_info->vertical_centering)
3092 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3093
3094 /* If we can use 8-bit functions, condense S->char2b. */
3095 if (!s->two_byte_p)
3096 for (i = 0; i < s->nchars; ++i)
3097 char1b[i] = s->char2b[i].byte2;
3098
3099 /* Draw text with XDrawString if background has already been
3100 filled. Otherwise, use XDrawImageString. (Note that
3101 XDrawImageString is usually faster than XDrawString.) Always
3102 use XDrawImageString when drawing the cursor so that there is
3103 no chance that characters under a box cursor are invisible. */
3104 if (s->for_overlaps_p
3105 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3106 {
3107 /* Draw characters with 16-bit or 8-bit functions. */
3108 if (s->two_byte_p)
3109 XDrawString16 (s->display, s->window, s->gc, x,
3110 s->ybase - boff, s->char2b, s->nchars);
3111 else
3112 XDrawString (s->display, s->window, s->gc, x,
3113 s->ybase - boff, char1b, s->nchars);
3114 }
3115 else
3116 {
3117 if (s->two_byte_p)
3118 XDrawImageString16 (s->display, s->window, s->gc, x,
3119 s->ybase - boff, s->char2b, s->nchars);
3120 else
3121 XDrawImageString (s->display, s->window, s->gc, x,
3122 s->ybase - boff, char1b, s->nchars);
3123 }
3124 }
3125 }
3126
3127 /* Draw the foreground of composite glyph string S. */
3128
3129 static void
3130 x_draw_composite_glyph_string_foreground (s)
3131 struct glyph_string *s;
3132 {
3133 int i, x;
3134
3135 /* If first glyph of S has a left box line, start drawing the text
3136 of S to the right of that box line. */
3137 if (s->face->box != FACE_NO_BOX
3138 && s->first_glyph->left_box_line_p)
3139 x = s->x + s->face->box_line_width;
3140 else
3141 x = s->x;
3142
3143 /* S is a glyph string for a composition. S->gidx is the index of
3144 the first character drawn for glyphs of this composition.
3145 S->gidx == 0 means we are drawing the very first character of
3146 this composition. */
3147
3148 /* Draw a rectangle for the composition if the font for the very
3149 first character of the composition could not be loaded. */
3150 if (s->font_not_found_p)
3151 {
3152 if (s->gidx == 0)
3153 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3154 s->width - 1, s->height - 1);
3155 }
3156 else
3157 {
3158 for (i = 0; i < s->nchars; i++, ++s->gidx)
3159 XDrawString16 (s->display, s->window, s->gc,
3160 x + s->cmp->offsets[s->gidx * 2],
3161 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3162 s->char2b + i, 1);
3163 }
3164 }
3165
3166
3167 #ifdef USE_X_TOOLKIT
3168
3169 static struct frame *x_frame_of_widget P_ ((Widget));
3170
3171
3172 /* Return the frame on which widget WIDGET is used.. Abort if frame
3173 cannot be determined. */
3174
3175 static struct frame *
3176 x_frame_of_widget (widget)
3177 Widget widget;
3178 {
3179 struct x_display_info *dpyinfo;
3180 Lisp_Object tail;
3181 struct frame *f;
3182
3183 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3184
3185 /* Find the top-level shell of the widget. Note that this function
3186 can be called when the widget is not yet realized, so XtWindow
3187 (widget) == 0. That's the reason we can't simply use
3188 x_any_window_to_frame. */
3189 while (!XtIsTopLevelShell (widget))
3190 widget = XtParent (widget);
3191
3192 /* Look for a frame with that top-level widget. Allocate the color
3193 on that frame to get the right gamma correction value. */
3194 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3195 if (GC_FRAMEP (XCAR (tail))
3196 && (f = XFRAME (XCAR (tail)),
3197 (f->output_data.nothing != 1
3198 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3199 && f->output_data.x->widget == widget)
3200 return f;
3201
3202 abort ();
3203 }
3204
3205
3206 /* Allocate the color COLOR->pixel on the screen and display of
3207 widget WIDGET in colormap CMAP. If an exact match cannot be
3208 allocated, try the nearest color available. Value is non-zero
3209 if successful. This is called from lwlib. */
3210
3211 int
3212 x_alloc_nearest_color_for_widget (widget, cmap, color)
3213 Widget widget;
3214 Colormap cmap;
3215 XColor *color;
3216 {
3217 struct frame *f = x_frame_of_widget (widget);
3218 return x_alloc_nearest_color (f, cmap, color);
3219 }
3220
3221
3222 #endif /* USE_X_TOOLKIT */
3223
3224
3225 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3226 CMAP. If an exact match can't be allocated, try the nearest color
3227 available. Value is non-zero if successful. Set *COLOR to the
3228 color allocated. */
3229
3230 int
3231 x_alloc_nearest_color (f, cmap, color)
3232 struct frame *f;
3233 Colormap cmap;
3234 XColor *color;
3235 {
3236 Display *display = FRAME_X_DISPLAY (f);
3237 Screen *screen = FRAME_X_SCREEN (f);
3238 int rc;
3239
3240 gamma_correct (f, color);
3241 rc = XAllocColor (display, cmap, color);
3242 if (rc == 0)
3243 {
3244 /* If we got to this point, the colormap is full, so we're going
3245 to try to get the next closest color. The algorithm used is
3246 a least-squares matching, which is what X uses for closest
3247 color matching with StaticColor visuals. */
3248 int nearest, i;
3249 unsigned long nearest_delta = ~0;
3250 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3251 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3252
3253 for (i = 0; i < ncells; ++i)
3254 cells[i].pixel = i;
3255 XQueryColors (display, cmap, cells, ncells);
3256
3257 for (nearest = i = 0; i < ncells; ++i)
3258 {
3259 long dred = (color->red >> 8) - (cells[i].red >> 8);
3260 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3261 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3262 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3263
3264 if (delta < nearest_delta)
3265 {
3266 nearest = i;
3267 nearest_delta = delta;
3268 }
3269 }
3270
3271 color->red = cells[nearest].red;
3272 color->green = cells[nearest].green;
3273 color->blue = cells[nearest].blue;
3274 rc = XAllocColor (display, cmap, color);
3275 }
3276
3277 #ifdef DEBUG_X_COLORS
3278 if (rc)
3279 register_color (color->pixel);
3280 #endif /* DEBUG_X_COLORS */
3281
3282 return rc;
3283 }
3284
3285
3286 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3287 It's necessary to do this instead of just using PIXEL directly to
3288 get color reference counts right. */
3289
3290 unsigned long
3291 x_copy_color (f, pixel)
3292 struct frame *f;
3293 unsigned long pixel;
3294 {
3295 XColor color;
3296
3297 color.pixel = pixel;
3298 BLOCK_INPUT;
3299 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3300 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3301 UNBLOCK_INPUT;
3302 #ifdef DEBUG_X_COLORS
3303 register_color (pixel);
3304 #endif
3305 return color.pixel;
3306 }
3307
3308
3309 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3310 It's necessary to do this instead of just using PIXEL directly to
3311 get color reference counts right. */
3312
3313 unsigned long
3314 x_copy_dpy_color (dpy, cmap, pixel)
3315 Display *dpy;
3316 Colormap cmap;
3317 unsigned long pixel;
3318 {
3319 XColor color;
3320
3321 color.pixel = pixel;
3322 BLOCK_INPUT;
3323 XQueryColor (dpy, cmap, &color);
3324 XAllocColor (dpy, cmap, &color);
3325 UNBLOCK_INPUT;
3326 #ifdef DEBUG_X_COLORS
3327 register_color (pixel);
3328 #endif
3329 return color.pixel;
3330 }
3331
3332
3333 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3334 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3335 If this produces the same color as PIXEL, try a color where all RGB
3336 values have DELTA added. Return the allocated color in *PIXEL.
3337 DISPLAY is the X display, CMAP is the colormap to operate on.
3338 Value is non-zero if successful. */
3339
3340 static int
3341 x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3342 struct frame *f;
3343 Display *display;
3344 Colormap cmap;
3345 unsigned long *pixel;
3346 double factor;
3347 int delta;
3348 {
3349 XColor color, new;
3350 int success_p;
3351
3352 /* Get RGB color values. */
3353 color.pixel = *pixel;
3354 XQueryColor (display, cmap, &color);
3355
3356 /* Change RGB values by specified FACTOR. Avoid overflow! */
3357 xassert (factor >= 0);
3358 new.red = min (0xffff, factor * color.red);
3359 new.green = min (0xffff, factor * color.green);
3360 new.blue = min (0xffff, factor * color.blue);
3361
3362 /* Try to allocate the color. */
3363 success_p = x_alloc_nearest_color (f, cmap, &new);
3364 if (success_p)
3365 {
3366 if (new.pixel == *pixel)
3367 {
3368 /* If we end up with the same color as before, try adding
3369 delta to the RGB values. */
3370 x_free_colors (f, &new.pixel, 1);
3371
3372 new.red = min (0xffff, delta + color.red);
3373 new.green = min (0xffff, delta + color.green);
3374 new.blue = min (0xffff, delta + color.blue);
3375 success_p = x_alloc_nearest_color (f, cmap, &new);
3376 }
3377 else
3378 success_p = 1;
3379 *pixel = new.pixel;
3380 }
3381
3382 return success_p;
3383 }
3384
3385
3386 /* Set up the foreground color for drawing relief lines of glyph
3387 string S. RELIEF is a pointer to a struct relief containing the GC
3388 with which lines will be drawn. Use a color that is FACTOR or
3389 DELTA lighter or darker than the relief's background which is found
3390 in S->f->output_data.x->relief_background. If such a color cannot
3391 be allocated, use DEFAULT_PIXEL, instead. */
3392
3393 static void
3394 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3395 struct frame *f;
3396 struct relief *relief;
3397 double factor;
3398 int delta;
3399 unsigned long default_pixel;
3400 {
3401 XGCValues xgcv;
3402 struct x_output *di = f->output_data.x;
3403 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3404 unsigned long pixel;
3405 unsigned long background = di->relief_background;
3406 Colormap cmap = FRAME_X_COLORMAP (f);
3407 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3408 Display *dpy = FRAME_X_DISPLAY (f);
3409
3410 xgcv.graphics_exposures = False;
3411 xgcv.line_width = 1;
3412
3413 /* Free previously allocated color. The color cell will be reused
3414 when it has been freed as many times as it was allocated, so this
3415 doesn't affect faces using the same colors. */
3416 if (relief->gc
3417 && relief->allocated_p)
3418 {
3419 x_free_colors (f, &relief->pixel, 1);
3420 relief->allocated_p = 0;
3421 }
3422
3423 /* Allocate new color. */
3424 xgcv.foreground = default_pixel;
3425 pixel = background;
3426 if (dpyinfo->n_planes != 1
3427 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
3428 {
3429 relief->allocated_p = 1;
3430 xgcv.foreground = relief->pixel = pixel;
3431 }
3432
3433 if (relief->gc == 0)
3434 {
3435 xgcv.stipple = dpyinfo->gray;
3436 mask |= GCStipple;
3437 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
3438 }
3439 else
3440 XChangeGC (dpy, relief->gc, mask, &xgcv);
3441 }
3442
3443
3444 /* Set up colors for the relief lines around glyph string S. */
3445
3446 static void
3447 x_setup_relief_colors (s)
3448 struct glyph_string *s;
3449 {
3450 struct x_output *di = s->f->output_data.x;
3451 unsigned long color;
3452
3453 if (s->face->use_box_color_for_shadows_p)
3454 color = s->face->box_color;
3455 else
3456 {
3457 XGCValues xgcv;
3458
3459 /* Get the background color of the face. */
3460 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3461 color = xgcv.background;
3462 }
3463
3464 if (di->white_relief.gc == 0
3465 || color != di->relief_background)
3466 {
3467 di->relief_background = color;
3468 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3469 WHITE_PIX_DEFAULT (s->f));
3470 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3471 BLACK_PIX_DEFAULT (s->f));
3472 }
3473 }
3474
3475
3476 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3477 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3478 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3479 relief. LEFT_P non-zero means draw a relief on the left side of
3480 the rectangle. RIGHT_P non-zero means draw a relief on the right
3481 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3482 when drawing. */
3483
3484 static void
3485 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3486 raised_p, left_p, right_p, clip_rect)
3487 struct frame *f;
3488 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3489 XRectangle *clip_rect;
3490 {
3491 int i;
3492 GC gc;
3493
3494 if (raised_p)
3495 gc = f->output_data.x->white_relief.gc;
3496 else
3497 gc = f->output_data.x->black_relief.gc;
3498 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3499
3500 /* Top. */
3501 for (i = 0; i < width; ++i)
3502 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3503 left_x + i * left_p, top_y + i,
3504 right_x + 1 - i * right_p, top_y + i);
3505
3506 /* Left. */
3507 if (left_p)
3508 for (i = 0; i < width; ++i)
3509 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3510 left_x + i, top_y + i, left_x + i, bottom_y - i);
3511
3512 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3513 if (raised_p)
3514 gc = f->output_data.x->black_relief.gc;
3515 else
3516 gc = f->output_data.x->white_relief.gc;
3517 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3518
3519 /* Bottom. */
3520 for (i = 0; i < width; ++i)
3521 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3522 left_x + i * left_p, bottom_y - i,
3523 right_x + 1 - i * right_p, bottom_y - i);
3524
3525 /* Right. */
3526 if (right_p)
3527 for (i = 0; i < width; ++i)
3528 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3529 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3530
3531 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3532 }
3533
3534
3535 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3536 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3537 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3538 left side of the rectangle. RIGHT_P non-zero means draw a line
3539 on the right side of the rectangle. CLIP_RECT is the clipping
3540 rectangle to use when drawing. */
3541
3542 static void
3543 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3544 left_p, right_p, clip_rect)
3545 struct glyph_string *s;
3546 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3547 XRectangle *clip_rect;
3548 {
3549 XGCValues xgcv;
3550
3551 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3552 XSetForeground (s->display, s->gc, s->face->box_color);
3553 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3554
3555 /* Top. */
3556 XFillRectangle (s->display, s->window, s->gc,
3557 left_x, top_y, right_x - left_x, width);
3558
3559 /* Left. */
3560 if (left_p)
3561 XFillRectangle (s->display, s->window, s->gc,
3562 left_x, top_y, width, bottom_y - top_y);
3563
3564 /* Bottom. */
3565 XFillRectangle (s->display, s->window, s->gc,
3566 left_x, bottom_y - width, right_x - left_x, width);
3567
3568 /* Right. */
3569 if (right_p)
3570 XFillRectangle (s->display, s->window, s->gc,
3571 right_x - width, top_y, width, bottom_y - top_y);
3572
3573 XSetForeground (s->display, s->gc, xgcv.foreground);
3574 XSetClipMask (s->display, s->gc, None);
3575 }
3576
3577
3578 /* Draw a box around glyph string S. */
3579
3580 static void
3581 x_draw_glyph_string_box (s)
3582 struct glyph_string *s;
3583 {
3584 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3585 int left_p, right_p;
3586 struct glyph *last_glyph;
3587 XRectangle clip_rect;
3588
3589 last_x = window_box_right (s->w, s->area);
3590 if (s->row->full_width_p
3591 && !s->w->pseudo_window_p)
3592 {
3593 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3594 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3595 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3596 }
3597
3598 /* The glyph that may have a right box line. */
3599 last_glyph = (s->cmp || s->img
3600 ? s->first_glyph
3601 : s->first_glyph + s->nchars - 1);
3602
3603 width = s->face->box_line_width;
3604 raised_p = s->face->box == FACE_RAISED_BOX;
3605 left_x = s->x;
3606 right_x = ((s->row->full_width_p
3607 ? last_x - 1
3608 : min (last_x, s->x + s->background_width) - 1));
3609 top_y = s->y;
3610 bottom_y = top_y + s->height - 1;
3611
3612 left_p = (s->first_glyph->left_box_line_p
3613 || (s->hl == DRAW_MOUSE_FACE
3614 && (s->prev == NULL
3615 || s->prev->hl != s->hl)));
3616 right_p = (last_glyph->right_box_line_p
3617 || (s->hl == DRAW_MOUSE_FACE
3618 && (s->next == NULL
3619 || s->next->hl != s->hl)));
3620
3621 x_get_glyph_string_clip_rect (s, &clip_rect);
3622
3623 if (s->face->box == FACE_SIMPLE_BOX)
3624 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3625 left_p, right_p, &clip_rect);
3626 else
3627 {
3628 x_setup_relief_colors (s);
3629 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3630 width, raised_p, left_p, right_p, &clip_rect);
3631 }
3632 }
3633
3634
3635 /* Draw foreground of image glyph string S. */
3636
3637 static void
3638 x_draw_image_foreground (s)
3639 struct glyph_string *s;
3640 {
3641 int x;
3642 int y = s->ybase - image_ascent (s->img, s->face);
3643
3644 /* If first glyph of S has a left box line, start drawing it to the
3645 right of that line. */
3646 if (s->face->box != FACE_NO_BOX
3647 && s->first_glyph->left_box_line_p)
3648 x = s->x + s->face->box_line_width;
3649 else
3650 x = s->x;
3651
3652 /* If there is a margin around the image, adjust x- and y-position
3653 by that margin. */
3654 if (s->img->margin)
3655 {
3656 x += s->img->margin;
3657 y += s->img->margin;
3658 }
3659
3660 if (s->img->pixmap)
3661 {
3662 if (s->img->mask)
3663 {
3664 /* We can't set both a clip mask and use XSetClipRectangles
3665 because the latter also sets a clip mask. We also can't
3666 trust on the shape extension to be available
3667 (XShapeCombineRegion). So, compute the rectangle to draw
3668 manually. */
3669 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3670 | GCFunction);
3671 XGCValues xgcv;
3672 XRectangle clip_rect, image_rect, r;
3673
3674 xgcv.clip_mask = s->img->mask;
3675 xgcv.clip_x_origin = x;
3676 xgcv.clip_y_origin = y;
3677 xgcv.function = GXcopy;
3678 XChangeGC (s->display, s->gc, mask, &xgcv);
3679
3680 x_get_glyph_string_clip_rect (s, &clip_rect);
3681 image_rect.x = x;
3682 image_rect.y = y;
3683 image_rect.width = s->img->width;
3684 image_rect.height = s->img->height;
3685 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3686 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3687 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3688 }
3689 else
3690 {
3691 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3692 0, 0, s->img->width, s->img->height, x, y);
3693
3694 /* When the image has a mask, we can expect that at
3695 least part of a mouse highlight or a block cursor will
3696 be visible. If the image doesn't have a mask, make
3697 a block cursor visible by drawing a rectangle around
3698 the image. I believe it's looking better if we do
3699 nothing here for mouse-face. */
3700 if (s->hl == DRAW_CURSOR)
3701 XDrawRectangle (s->display, s->window, s->gc, x, y,
3702 s->img->width - 1, s->img->height - 1);
3703 }
3704 }
3705 else
3706 /* Draw a rectangle if image could not be loaded. */
3707 XDrawRectangle (s->display, s->window, s->gc, x, y,
3708 s->img->width - 1, s->img->height - 1);
3709 }
3710
3711
3712 /* Draw a relief around the image glyph string S. */
3713
3714 static void
3715 x_draw_image_relief (s)
3716 struct glyph_string *s;
3717 {
3718 int x0, y0, x1, y1, thick, raised_p;
3719 XRectangle r;
3720 int x;
3721 int y = s->ybase - image_ascent (s->img, s->face);
3722
3723 /* If first glyph of S has a left box line, start drawing it to the
3724 right of that line. */
3725 if (s->face->box != FACE_NO_BOX
3726 && s->first_glyph->left_box_line_p)
3727 x = s->x + s->face->box_line_width;
3728 else
3729 x = s->x;
3730
3731 /* If there is a margin around the image, adjust x- and y-position
3732 by that margin. */
3733 if (s->img->margin)
3734 {
3735 x += s->img->margin;
3736 y += s->img->margin;
3737 }
3738
3739 if (s->hl == DRAW_IMAGE_SUNKEN
3740 || s->hl == DRAW_IMAGE_RAISED)
3741 {
3742 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3743 raised_p = s->hl == DRAW_IMAGE_RAISED;
3744 }
3745 else
3746 {
3747 thick = abs (s->img->relief);
3748 raised_p = s->img->relief > 0;
3749 }
3750
3751 x0 = x - thick;
3752 y0 = y - thick;
3753 x1 = x + s->img->width + thick - 1;
3754 y1 = y + s->img->height + thick - 1;
3755
3756 x_setup_relief_colors (s);
3757 x_get_glyph_string_clip_rect (s, &r);
3758 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3759 }
3760
3761
3762 /* Draw the foreground of image glyph string S to PIXMAP. */
3763
3764 static void
3765 x_draw_image_foreground_1 (s, pixmap)
3766 struct glyph_string *s;
3767 Pixmap pixmap;
3768 {
3769 int x;
3770 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3771
3772 /* If first glyph of S has a left box line, start drawing it to the
3773 right of that line. */
3774 if (s->face->box != FACE_NO_BOX
3775 && s->first_glyph->left_box_line_p)
3776 x = s->face->box_line_width;
3777 else
3778 x = 0;
3779
3780 /* If there is a margin around the image, adjust x- and y-position
3781 by that margin. */
3782 if (s->img->margin)
3783 {
3784 x += s->img->margin;
3785 y += s->img->margin;
3786 }
3787
3788 if (s->img->pixmap)
3789 {
3790 if (s->img->mask)
3791 {
3792 /* We can't set both a clip mask and use XSetClipRectangles
3793 because the latter also sets a clip mask. We also can't
3794 trust on the shape extension to be available
3795 (XShapeCombineRegion). So, compute the rectangle to draw
3796 manually. */
3797 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3798 | GCFunction);
3799 XGCValues xgcv;
3800
3801 xgcv.clip_mask = s->img->mask;
3802 xgcv.clip_x_origin = x;
3803 xgcv.clip_y_origin = y;
3804 xgcv.function = GXcopy;
3805 XChangeGC (s->display, s->gc, mask, &xgcv);
3806
3807 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3808 0, 0, s->img->width, s->img->height, x, y);
3809 XSetClipMask (s->display, s->gc, None);
3810 }
3811 else
3812 {
3813 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3814 0, 0, s->img->width, s->img->height, x, y);
3815
3816 /* When the image has a mask, we can expect that at
3817 least part of a mouse highlight or a block cursor will
3818 be visible. If the image doesn't have a mask, make
3819 a block cursor visible by drawing a rectangle around
3820 the image. I believe it's looking better if we do
3821 nothing here for mouse-face. */
3822 if (s->hl == DRAW_CURSOR)
3823 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3824 s->img->width - 1, s->img->height - 1);
3825 }
3826 }
3827 else
3828 /* Draw a rectangle if image could not be loaded. */
3829 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3830 s->img->width - 1, s->img->height - 1);
3831 }
3832
3833
3834 /* Draw part of the background of glyph string S. X, Y, W, and H
3835 give the rectangle to draw. */
3836
3837 static void
3838 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3839 struct glyph_string *s;
3840 int x, y, w, h;
3841 {
3842 if (s->stippled_p)
3843 {
3844 /* Fill background with a stipple pattern. */
3845 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3846 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3847 XSetFillStyle (s->display, s->gc, FillSolid);
3848 }
3849 else
3850 x_clear_glyph_string_rect (s, x, y, w, h);
3851 }
3852
3853
3854 /* Draw image glyph string S.
3855
3856 s->y
3857 s->x +-------------------------
3858 | s->face->box
3859 |
3860 | +-------------------------
3861 | | s->img->margin
3862 | |
3863 | | +-------------------
3864 | | | the image
3865
3866 */
3867
3868 static void
3869 x_draw_image_glyph_string (s)
3870 struct glyph_string *s;
3871 {
3872 int x, y;
3873 int box_line_width = s->face->box_line_width;
3874 int margin = s->img->margin;
3875 int height;
3876 Pixmap pixmap = None;
3877
3878 height = s->height - 2 * box_line_width;
3879
3880 /* Fill background with face under the image. Do it only if row is
3881 taller than image or if image has a clip mask to reduce
3882 flickering. */
3883 s->stippled_p = s->face->stipple != 0;
3884 if (height > s->img->height
3885 || margin
3886 || s->img->mask
3887 || s->img->pixmap == 0
3888 || s->width != s->background_width)
3889 {
3890 if (box_line_width && s->first_glyph->left_box_line_p)
3891 x = s->x + box_line_width;
3892 else
3893 x = s->x;
3894
3895 y = s->y + box_line_width;
3896
3897 if (s->img->mask)
3898 {
3899 /* Create a pixmap as large as the glyph string Fill it with
3900 the background color. Copy the image to it, using its
3901 mask. Copy the temporary pixmap to the display. */
3902 Screen *screen = FRAME_X_SCREEN (s->f);
3903 int depth = DefaultDepthOfScreen (screen);
3904
3905 /* Create a pixmap as large as the glyph string. */
3906 pixmap = XCreatePixmap (s->display, s->window,
3907 s->background_width,
3908 s->height, depth);
3909
3910 /* Don't clip in the following because we're working on the
3911 pixmap. */
3912 XSetClipMask (s->display, s->gc, None);
3913
3914 /* Fill the pixmap with the background color/stipple. */
3915 if (s->stippled_p)
3916 {
3917 /* Fill background with a stipple pattern. */
3918 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3919 XFillRectangle (s->display, pixmap, s->gc,
3920 0, 0, s->background_width, s->height);
3921 XSetFillStyle (s->display, s->gc, FillSolid);
3922 }
3923 else
3924 {
3925 XGCValues xgcv;
3926 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3927 &xgcv);
3928 XSetForeground (s->display, s->gc, xgcv.background);
3929 XFillRectangle (s->display, pixmap, s->gc,
3930 0, 0, s->background_width, s->height);
3931 XSetForeground (s->display, s->gc, xgcv.foreground);
3932 }
3933 }
3934 else
3935 /* Implementation idea: Is it possible to construct a mask?
3936 We could look at the color at the margins of the image, and
3937 say that this color is probably the background color of the
3938 image. */
3939 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3940
3941 s->background_filled_p = 1;
3942 }
3943
3944 /* Draw the foreground. */
3945 if (pixmap != None)
3946 {
3947 x_draw_image_foreground_1 (s, pixmap);
3948 x_set_glyph_string_clipping (s);
3949 XCopyArea (s->display, pixmap, s->window, s->gc,
3950 0, 0, s->background_width, s->height, s->x, s->y);
3951 XFreePixmap (s->display, pixmap);
3952 }
3953 else
3954 x_draw_image_foreground (s);
3955
3956 /* If we must draw a relief around the image, do it. */
3957 if (s->img->relief
3958 || s->hl == DRAW_IMAGE_RAISED
3959 || s->hl == DRAW_IMAGE_SUNKEN)
3960 x_draw_image_relief (s);
3961 }
3962
3963
3964 /* Draw stretch glyph string S. */
3965
3966 static void
3967 x_draw_stretch_glyph_string (s)
3968 struct glyph_string *s;
3969 {
3970 xassert (s->first_glyph->type == STRETCH_GLYPH);
3971 s->stippled_p = s->face->stipple != 0;
3972
3973 if (s->hl == DRAW_CURSOR
3974 && !x_stretch_cursor_p)
3975 {
3976 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3977 as wide as the stretch glyph. */
3978 int width = min (CANON_X_UNIT (s->f), s->background_width);
3979
3980 /* Draw cursor. */
3981 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3982
3983 /* Clear rest using the GC of the original non-cursor face. */
3984 if (width < s->background_width)
3985 {
3986 GC gc = s->face->gc;
3987 int x = s->x + width, y = s->y;
3988 int w = s->background_width - width, h = s->height;
3989 XRectangle r;
3990
3991 x_get_glyph_string_clip_rect (s, &r);
3992 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
3993
3994 if (s->face->stipple)
3995 {
3996 /* Fill background with a stipple pattern. */
3997 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3998 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3999 XSetFillStyle (s->display, gc, FillSolid);
4000 }
4001 else
4002 {
4003 XGCValues xgcv;
4004 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4005 XSetForeground (s->display, gc, xgcv.background);
4006 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4007 XSetForeground (s->display, gc, xgcv.foreground);
4008 }
4009 }
4010 }
4011 else
4012 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4013 s->height);
4014
4015 s->background_filled_p = 1;
4016 }
4017
4018
4019 /* Draw glyph string S. */
4020
4021 static void
4022 x_draw_glyph_string (s)
4023 struct glyph_string *s;
4024 {
4025 /* If S draws into the background of its successor, draw the
4026 background of the successor first so that S can draw into it.
4027 This makes S->next use XDrawString instead of XDrawImageString. */
4028 if (s->next && s->right_overhang && !s->for_overlaps_p)
4029 {
4030 xassert (s->next->img == NULL);
4031 x_set_glyph_string_gc (s->next);
4032 x_set_glyph_string_clipping (s->next);
4033 x_draw_glyph_string_background (s->next, 1);
4034 }
4035
4036 /* Set up S->gc, set clipping and draw S. */
4037 x_set_glyph_string_gc (s);
4038 x_set_glyph_string_clipping (s);
4039
4040 switch (s->first_glyph->type)
4041 {
4042 case IMAGE_GLYPH:
4043 x_draw_image_glyph_string (s);
4044 break;
4045
4046 case STRETCH_GLYPH:
4047 x_draw_stretch_glyph_string (s);
4048 break;
4049
4050 case CHAR_GLYPH:
4051 if (s->for_overlaps_p)
4052 s->background_filled_p = 1;
4053 else
4054 x_draw_glyph_string_background (s, 0);
4055 x_draw_glyph_string_foreground (s);
4056 break;
4057
4058 case COMPOSITE_GLYPH:
4059 if (s->for_overlaps_p || s->gidx > 0)
4060 s->background_filled_p = 1;
4061 else
4062 x_draw_glyph_string_background (s, 1);
4063 x_draw_composite_glyph_string_foreground (s);
4064 break;
4065
4066 default:
4067 abort ();
4068 }
4069
4070 if (!s->for_overlaps_p)
4071 {
4072 /* Draw underline. */
4073 if (s->face->underline_p)
4074 {
4075 unsigned long dy, h;
4076
4077 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4078 h = 1;
4079 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4080 dy = s->height - h;
4081
4082 if (s->face->underline_defaulted_p)
4083 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4084 s->width, h);
4085 else
4086 {
4087 XGCValues xgcv;
4088 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4089 XSetForeground (s->display, s->gc, s->face->underline_color);
4090 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4091 s->width, h);
4092 XSetForeground (s->display, s->gc, xgcv.foreground);
4093 }
4094 }
4095
4096 /* Draw overline. */
4097 if (s->face->overline_p)
4098 {
4099 unsigned long dy = 0, h = 1;
4100
4101 if (s->face->overline_color_defaulted_p)
4102 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4103 s->width, h);
4104 else
4105 {
4106 XGCValues xgcv;
4107 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4108 XSetForeground (s->display, s->gc, s->face->overline_color);
4109 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4110 s->width, h);
4111 XSetForeground (s->display, s->gc, xgcv.foreground);
4112 }
4113 }
4114
4115 /* Draw strike-through. */
4116 if (s->face->strike_through_p)
4117 {
4118 unsigned long h = 1;
4119 unsigned long dy = (s->height - h) / 2;
4120
4121 if (s->face->strike_through_color_defaulted_p)
4122 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4123 s->width, h);
4124 else
4125 {
4126 XGCValues xgcv;
4127 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4128 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4129 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4130 s->width, h);
4131 XSetForeground (s->display, s->gc, xgcv.foreground);
4132 }
4133 }
4134
4135 /* Draw relief. */
4136 if (s->face->box != FACE_NO_BOX)
4137 x_draw_glyph_string_box (s);
4138 }
4139
4140 /* Reset clipping. */
4141 XSetClipMask (s->display, s->gc, None);
4142 }
4143
4144
4145 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4146 struct face **, int));
4147
4148
4149 /* Fill glyph string S with composition components specified by S->cmp.
4150
4151 FACES is an array of faces for all components of this composition.
4152 S->gidx is the index of the first component for S.
4153 OVERLAPS_P non-zero means S should draw the foreground only, and
4154 use its physical height for clipping.
4155
4156 Value is the index of a component not in S. */
4157
4158 static int
4159 x_fill_composite_glyph_string (s, faces, overlaps_p)
4160 struct glyph_string *s;
4161 struct face **faces;
4162 int overlaps_p;
4163 {
4164 int i;
4165
4166 xassert (s);
4167
4168 s->for_overlaps_p = overlaps_p;
4169
4170 s->face = faces[s->gidx];
4171 s->font = s->face->font;
4172 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4173
4174 /* For all glyphs of this composition, starting at the offset
4175 S->gidx, until we reach the end of the definition or encounter a
4176 glyph that requires the different face, add it to S. */
4177 ++s->nchars;
4178 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4179 ++s->nchars;
4180
4181 /* All glyph strings for the same composition has the same width,
4182 i.e. the width set for the first component of the composition. */
4183
4184 s->width = s->first_glyph->pixel_width;
4185
4186 /* If the specified font could not be loaded, use the frame's
4187 default font, but record the fact that we couldn't load it in
4188 the glyph string so that we can draw rectangles for the
4189 characters of the glyph string. */
4190 if (s->font == NULL)
4191 {
4192 s->font_not_found_p = 1;
4193 s->font = FRAME_FONT (s->f);
4194 }
4195
4196 /* Adjust base line for subscript/superscript text. */
4197 s->ybase += s->first_glyph->voffset;
4198
4199 xassert (s->face && s->face->gc);
4200
4201 /* This glyph string must always be drawn with 16-bit functions. */
4202 s->two_byte_p = 1;
4203
4204 return s->gidx + s->nchars;
4205 }
4206
4207
4208 /* Fill glyph string S from a sequence of character glyphs.
4209
4210 FACE_ID is the face id of the string. START is the index of the
4211 first glyph to consider, END is the index of the last + 1.
4212 OVERLAPS_P non-zero means S should draw the foreground only, and
4213 use its physical height for clipping.
4214
4215 Value is the index of the first glyph not in S. */
4216
4217 static int
4218 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4219 struct glyph_string *s;
4220 int face_id;
4221 int start, end, overlaps_p;
4222 {
4223 struct glyph *glyph, *last;
4224 int voffset;
4225 int glyph_not_available_p;
4226
4227 xassert (s->f == XFRAME (s->w->frame));
4228 xassert (s->nchars == 0);
4229 xassert (start >= 0 && end > start);
4230
4231 s->for_overlaps_p = overlaps_p,
4232 glyph = s->row->glyphs[s->area] + start;
4233 last = s->row->glyphs[s->area] + end;
4234 voffset = glyph->voffset;
4235
4236 glyph_not_available_p = glyph->glyph_not_available_p;
4237
4238 while (glyph < last
4239 && glyph->type == CHAR_GLYPH
4240 && glyph->voffset == voffset
4241 /* Same face id implies same font, nowadays. */
4242 && glyph->face_id == face_id
4243 && glyph->glyph_not_available_p == glyph_not_available_p)
4244 {
4245 int two_byte_p;
4246
4247 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4248 s->char2b + s->nchars,
4249 &two_byte_p);
4250 s->two_byte_p = two_byte_p;
4251 ++s->nchars;
4252 xassert (s->nchars <= end - start);
4253 s->width += glyph->pixel_width;
4254 ++glyph;
4255 }
4256
4257 s->font = s->face->font;
4258 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4259
4260 /* If the specified font could not be loaded, use the frame's font,
4261 but record the fact that we couldn't load it in
4262 S->font_not_found_p so that we can draw rectangles for the
4263 characters of the glyph string. */
4264 if (s->font == NULL || glyph_not_available_p)
4265 {
4266 s->font_not_found_p = 1;
4267 s->font = FRAME_FONT (s->f);
4268 }
4269
4270 /* Adjust base line for subscript/superscript text. */
4271 s->ybase += voffset;
4272
4273 xassert (s->face && s->face->gc);
4274 return glyph - s->row->glyphs[s->area];
4275 }
4276
4277
4278 /* Fill glyph string S from image glyph S->first_glyph. */
4279
4280 static void
4281 x_fill_image_glyph_string (s)
4282 struct glyph_string *s;
4283 {
4284 xassert (s->first_glyph->type == IMAGE_GLYPH);
4285 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4286 xassert (s->img);
4287 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4288 s->font = s->face->font;
4289 s->width = s->first_glyph->pixel_width;
4290
4291 /* Adjust base line for subscript/superscript text. */
4292 s->ybase += s->first_glyph->voffset;
4293 }
4294
4295
4296 /* Fill glyph string S from a sequence of stretch glyphs.
4297
4298 ROW is the glyph row in which the glyphs are found, AREA is the
4299 area within the row. START is the index of the first glyph to
4300 consider, END is the index of the last + 1.
4301
4302 Value is the index of the first glyph not in S. */
4303
4304 static int
4305 x_fill_stretch_glyph_string (s, row, area, start, end)
4306 struct glyph_string *s;
4307 struct glyph_row *row;
4308 enum glyph_row_area area;
4309 int start, end;
4310 {
4311 struct glyph *glyph, *last;
4312 int voffset, face_id;
4313
4314 xassert (s->first_glyph->type == STRETCH_GLYPH);
4315
4316 glyph = s->row->glyphs[s->area] + start;
4317 last = s->row->glyphs[s->area] + end;
4318 face_id = glyph->face_id;
4319 s->face = FACE_FROM_ID (s->f, face_id);
4320 s->font = s->face->font;
4321 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4322 s->width = glyph->pixel_width;
4323 voffset = glyph->voffset;
4324
4325 for (++glyph;
4326 (glyph < last
4327 && glyph->type == STRETCH_GLYPH
4328 && glyph->voffset == voffset
4329 && glyph->face_id == face_id);
4330 ++glyph)
4331 s->width += glyph->pixel_width;
4332
4333 /* Adjust base line for subscript/superscript text. */
4334 s->ybase += voffset;
4335
4336 xassert (s->face && s->face->gc);
4337 return glyph - s->row->glyphs[s->area];
4338 }
4339
4340
4341 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4342 of XChar2b structures for S; it can't be allocated in
4343 x_init_glyph_string because it must be allocated via `alloca'. W
4344 is the window on which S is drawn. ROW and AREA are the glyph row
4345 and area within the row from which S is constructed. START is the
4346 index of the first glyph structure covered by S. HL is a
4347 face-override for drawing S. */
4348
4349 static void
4350 x_init_glyph_string (s, char2b, w, row, area, start, hl)
4351 struct glyph_string *s;
4352 XChar2b *char2b;
4353 struct window *w;
4354 struct glyph_row *row;
4355 enum glyph_row_area area;
4356 int start;
4357 enum draw_glyphs_face hl;
4358 {
4359 bzero (s, sizeof *s);
4360 s->w = w;
4361 s->f = XFRAME (w->frame);
4362 s->display = FRAME_X_DISPLAY (s->f);
4363 s->window = FRAME_X_WINDOW (s->f);
4364 s->char2b = char2b;
4365 s->hl = hl;
4366 s->row = row;
4367 s->area = area;
4368 s->first_glyph = row->glyphs[area] + start;
4369 s->height = row->height;
4370 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4371
4372 /* Display the internal border below the tool-bar window. */
4373 if (s->w == XWINDOW (s->f->tool_bar_window))
4374 s->y -= s->f->output_data.x->internal_border_width;
4375
4376 s->ybase = s->y + row->ascent;
4377 }
4378
4379
4380 /* Set background width of glyph string S. START is the index of the
4381 first glyph following S. LAST_X is the right-most x-position + 1
4382 in the drawing area. */
4383
4384 static INLINE void
4385 x_set_glyph_string_background_width (s, start, last_x)
4386 struct glyph_string *s;
4387 int start;
4388 int last_x;
4389 {
4390 /* If the face of this glyph string has to be drawn to the end of
4391 the drawing area, set S->extends_to_end_of_line_p. */
4392 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4393
4394 if (start == s->row->used[s->area]
4395 && s->hl == DRAW_NORMAL_TEXT
4396 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4397 || s->face->background != default_face->background
4398 || s->face->stipple != default_face->stipple))
4399 s->extends_to_end_of_line_p = 1;
4400
4401 /* If S extends its face to the end of the line, set its
4402 background_width to the distance to the right edge of the drawing
4403 area. */
4404 if (s->extends_to_end_of_line_p)
4405 s->background_width = last_x - s->x + 1;
4406 else
4407 s->background_width = s->width;
4408 }
4409
4410
4411 /* Add a glyph string for a stretch glyph to the list of strings
4412 between HEAD and TAIL. START is the index of the stretch glyph in
4413 row area AREA of glyph row ROW. END is the index of the last glyph
4414 in that glyph row area. X is the current output position assigned
4415 to the new glyph string constructed. HL overrides that face of the
4416 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4417 is the right-most x-position of the drawing area. */
4418
4419 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4420 and below -- keep them on one line. */
4421 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4422 do \
4423 { \
4424 s = (struct glyph_string *) alloca (sizeof *s); \
4425 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4426 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4427 x_append_glyph_string (&HEAD, &TAIL, s); \
4428 s->x = (X); \
4429 } \
4430 while (0)
4431
4432
4433 /* Add a glyph string for an image glyph to the list of strings
4434 between HEAD and TAIL. START is the index of the image glyph in
4435 row area AREA of glyph row ROW. END is the index of the last glyph
4436 in that glyph row area. X is the current output position assigned
4437 to the new glyph string constructed. HL overrides that face of the
4438 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4439 is the right-most x-position of the drawing area. */
4440
4441 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4442 do \
4443 { \
4444 s = (struct glyph_string *) alloca (sizeof *s); \
4445 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4446 x_fill_image_glyph_string (s); \
4447 x_append_glyph_string (&HEAD, &TAIL, s); \
4448 ++START; \
4449 s->x = (X); \
4450 } \
4451 while (0)
4452
4453
4454 /* Add a glyph string for a sequence of character glyphs to the list
4455 of strings between HEAD and TAIL. START is the index of the first
4456 glyph in row area AREA of glyph row ROW that is part of the new
4457 glyph string. END is the index of the last glyph in that glyph row
4458 area. X is the current output position assigned to the new glyph
4459 string constructed. HL overrides that face of the glyph; e.g. it
4460 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4461 right-most x-position of the drawing area. */
4462
4463 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4464 do \
4465 { \
4466 int c, face_id; \
4467 XChar2b *char2b; \
4468 \
4469 c = (ROW)->glyphs[AREA][START].u.ch; \
4470 face_id = (ROW)->glyphs[AREA][START].face_id; \
4471 \
4472 s = (struct glyph_string *) alloca (sizeof *s); \
4473 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4474 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4475 x_append_glyph_string (&HEAD, &TAIL, s); \
4476 s->x = (X); \
4477 START = x_fill_glyph_string (s, face_id, START, END, \
4478 OVERLAPS_P); \
4479 } \
4480 while (0)
4481
4482
4483 /* Add a glyph string for a composite sequence to the list of strings
4484 between HEAD and TAIL. START is the index of the first glyph in
4485 row area AREA of glyph row ROW that is part of the new glyph
4486 string. END is the index of the last glyph in that glyph row area.
4487 X is the current output position assigned to the new glyph string
4488 constructed. HL overrides that face of the glyph; e.g. it is
4489 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4490 x-position of the drawing area. */
4491
4492 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4493 do { \
4494 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4495 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4496 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4497 struct composition *cmp = composition_table[cmp_id]; \
4498 int glyph_len = cmp->glyph_len; \
4499 XChar2b *char2b; \
4500 struct face **faces; \
4501 struct glyph_string *first_s = NULL; \
4502 int n; \
4503 \
4504 base_face = base_face->ascii_face; \
4505 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4506 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4507 /* At first, fill in `char2b' and `faces'. */ \
4508 for (n = 0; n < glyph_len; n++) \
4509 { \
4510 int c = COMPOSITION_GLYPH (cmp, n); \
4511 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4512 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4513 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4514 this_face_id, char2b + n, 1); \
4515 } \
4516 \
4517 /* Make glyph_strings for each glyph sequence that is drawable by \
4518 the same face, and append them to HEAD/TAIL. */ \
4519 for (n = 0; n < cmp->glyph_len;) \
4520 { \
4521 s = (struct glyph_string *) alloca (sizeof *s); \
4522 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4523 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4524 s->cmp = cmp; \
4525 s->gidx = n; \
4526 s->x = (X); \
4527 \
4528 if (n == 0) \
4529 first_s = s; \
4530 \
4531 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4532 } \
4533 \
4534 ++START; \
4535 s = first_s; \
4536 } while (0)
4537
4538
4539 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4540 of AREA of glyph row ROW on window W between indices START and END.
4541 HL overrides the face for drawing glyph strings, e.g. it is
4542 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4543 x-positions of the drawing area.
4544
4545 This is an ugly monster macro construct because we must use alloca
4546 to allocate glyph strings (because x_draw_glyphs can be called
4547 asynchronously). */
4548
4549 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4550 do \
4551 { \
4552 HEAD = TAIL = NULL; \
4553 while (START < END) \
4554 { \
4555 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4556 switch (first_glyph->type) \
4557 { \
4558 case CHAR_GLYPH: \
4559 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4560 TAIL, HL, X, LAST_X, \
4561 OVERLAPS_P); \
4562 break; \
4563 \
4564 case COMPOSITE_GLYPH: \
4565 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4566 HEAD, TAIL, HL, X, LAST_X,\
4567 OVERLAPS_P); \
4568 break; \
4569 \
4570 case STRETCH_GLYPH: \
4571 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4572 HEAD, TAIL, HL, X, LAST_X); \
4573 break; \
4574 \
4575 case IMAGE_GLYPH: \
4576 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4577 TAIL, HL, X, LAST_X); \
4578 break; \
4579 \
4580 default: \
4581 abort (); \
4582 } \
4583 \
4584 x_set_glyph_string_background_width (s, START, LAST_X); \
4585 (X) += s->width; \
4586 } \
4587 } \
4588 while (0)
4589
4590
4591 /* Draw glyphs between START and END in AREA of ROW on window W,
4592 starting at x-position X. X is relative to AREA in W. HL is a
4593 face-override with the following meaning:
4594
4595 DRAW_NORMAL_TEXT draw normally
4596 DRAW_CURSOR draw in cursor face
4597 DRAW_MOUSE_FACE draw in mouse face.
4598 DRAW_INVERSE_VIDEO draw in mode line face
4599 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4600 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4601
4602 If REAL_START is non-null, return in *REAL_START the real starting
4603 position for display. This can be different from START in case
4604 overlapping glyphs must be displayed. If REAL_END is non-null,
4605 return in *REAL_END the real end position for display. This can be
4606 different from END in case overlapping glyphs must be displayed.
4607
4608 If OVERLAPS_P is non-zero, draw only the foreground of characters
4609 and clip to the physical height of ROW.
4610
4611 Value is the x-position reached, relative to AREA of W. */
4612
4613 static int
4614 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4615 overlaps_p)
4616 struct window *w;
4617 int x;
4618 struct glyph_row *row;
4619 enum glyph_row_area area;
4620 int start, end;
4621 enum draw_glyphs_face hl;
4622 int *real_start, *real_end;
4623 int overlaps_p;
4624 {
4625 struct glyph_string *head, *tail;
4626 struct glyph_string *s;
4627 int last_x, area_width;
4628 int x_reached;
4629 int i, j;
4630
4631 /* Let's rather be paranoid than getting a SEGV. */
4632 start = max (0, start);
4633 end = min (end, row->used[area]);
4634 if (real_start)
4635 *real_start = start;
4636 if (real_end)
4637 *real_end = end;
4638
4639 /* Translate X to frame coordinates. Set last_x to the right
4640 end of the drawing area. */
4641 if (row->full_width_p)
4642 {
4643 /* X is relative to the left edge of W, without scroll bars
4644 or flag areas. */
4645 struct frame *f = XFRAME (w->frame);
4646 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4647 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4648
4649 x += window_left_x;
4650 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4651 last_x = window_left_x + area_width;
4652
4653 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4654 {
4655 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4656 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4657 last_x += width;
4658 else
4659 x -= width;
4660 }
4661
4662 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4663 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4664 }
4665 else
4666 {
4667 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4668 area_width = window_box_width (w, area);
4669 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4670 }
4671
4672 /* Build a doubly-linked list of glyph_string structures between
4673 head and tail from what we have to draw. Note that the macro
4674 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4675 the reason we use a separate variable `i'. */
4676 i = start;
4677 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4678 overlaps_p);
4679 if (tail)
4680 x_reached = tail->x + tail->background_width;
4681 else
4682 x_reached = x;
4683
4684 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4685 the row, redraw some glyphs in front or following the glyph
4686 strings built above. */
4687 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4688 {
4689 int dummy_x = 0;
4690 struct glyph_string *h, *t;
4691
4692 /* Compute overhangs for all glyph strings. */
4693 for (s = head; s; s = s->next)
4694 x_compute_glyph_string_overhangs (s);
4695
4696 /* Prepend glyph strings for glyphs in front of the first glyph
4697 string that are overwritten because of the first glyph
4698 string's left overhang. The background of all strings
4699 prepended must be drawn because the first glyph string
4700 draws over it. */
4701 i = x_left_overwritten (head);
4702 if (i >= 0)
4703 {
4704 j = i;
4705 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4706 DRAW_NORMAL_TEXT, dummy_x, last_x,
4707 overlaps_p);
4708 start = i;
4709 if (real_start)
4710 *real_start = start;
4711 x_compute_overhangs_and_x (t, head->x, 1);
4712 x_prepend_glyph_string_lists (&head, &tail, h, t);
4713 }
4714
4715 /* Prepend glyph strings for glyphs in front of the first glyph
4716 string that overwrite that glyph string because of their
4717 right overhang. For these strings, only the foreground must
4718 be drawn, because it draws over the glyph string at `head'.
4719 The background must not be drawn because this would overwrite
4720 right overhangs of preceding glyphs for which no glyph
4721 strings exist. */
4722 i = x_left_overwriting (head);
4723 if (i >= 0)
4724 {
4725 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4726 DRAW_NORMAL_TEXT, dummy_x, last_x,
4727 overlaps_p);
4728 for (s = h; s; s = s->next)
4729 s->background_filled_p = 1;
4730 if (real_start)
4731 *real_start = i;
4732 x_compute_overhangs_and_x (t, head->x, 1);
4733 x_prepend_glyph_string_lists (&head, &tail, h, t);
4734 }
4735
4736 /* Append glyphs strings for glyphs following the last glyph
4737 string tail that are overwritten by tail. The background of
4738 these strings has to be drawn because tail's foreground draws
4739 over it. */
4740 i = x_right_overwritten (tail);
4741 if (i >= 0)
4742 {
4743 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4744 DRAW_NORMAL_TEXT, x, last_x,
4745 overlaps_p);
4746 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4747 x_append_glyph_string_lists (&head, &tail, h, t);
4748 if (real_end)
4749 *real_end = i;
4750 }
4751
4752 /* Append glyph strings for glyphs following the last glyph
4753 string tail that overwrite tail. The foreground of such
4754 glyphs has to be drawn because it writes into the background
4755 of tail. The background must not be drawn because it could
4756 paint over the foreground of following glyphs. */
4757 i = x_right_overwriting (tail);
4758 if (i >= 0)
4759 {
4760 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4761 DRAW_NORMAL_TEXT, x, last_x,
4762 overlaps_p);
4763 for (s = h; s; s = s->next)
4764 s->background_filled_p = 1;
4765 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4766 x_append_glyph_string_lists (&head, &tail, h, t);
4767 if (real_end)
4768 *real_end = i;
4769 }
4770 }
4771
4772 /* Draw all strings. */
4773 for (s = head; s; s = s->next)
4774 x_draw_glyph_string (s);
4775
4776 /* Value is the x-position up to which drawn, relative to AREA of W.
4777 This doesn't include parts drawn because of overhangs. */
4778 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4779 if (!row->full_width_p)
4780 {
4781 if (area > LEFT_MARGIN_AREA)
4782 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4783 if (area > TEXT_AREA)
4784 x_reached -= window_box_width (w, TEXT_AREA);
4785 }
4786 return x_reached;
4787 }
4788
4789
4790 /* Fix the display of area AREA of overlapping row ROW in window W. */
4791
4792 static void
4793 x_fix_overlapping_area (w, row, area)
4794 struct window *w;
4795 struct glyph_row *row;
4796 enum glyph_row_area area;
4797 {
4798 int i, x;
4799
4800 BLOCK_INPUT;
4801
4802 if (area == LEFT_MARGIN_AREA)
4803 x = 0;
4804 else if (area == TEXT_AREA)
4805 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4806 else
4807 x = (window_box_width (w, LEFT_MARGIN_AREA)
4808 + window_box_width (w, TEXT_AREA));
4809
4810 for (i = 0; i < row->used[area];)
4811 {
4812 if (row->glyphs[area][i].overlaps_vertically_p)
4813 {
4814 int start = i, start_x = x;
4815
4816 do
4817 {
4818 x += row->glyphs[area][i].pixel_width;
4819 ++i;
4820 }
4821 while (i < row->used[area]
4822 && row->glyphs[area][i].overlaps_vertically_p);
4823
4824 x_draw_glyphs (w, start_x, row, area, start, i,
4825 (row->inverse_p
4826 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4827 NULL, NULL, 1);
4828 }
4829 else
4830 {
4831 x += row->glyphs[area][i].pixel_width;
4832 ++i;
4833 }
4834 }
4835
4836 UNBLOCK_INPUT;
4837 }
4838
4839
4840 /* Output LEN glyphs starting at START at the nominal cursor position.
4841 Advance the nominal cursor over the text. The global variable
4842 updated_window contains the window being updated, updated_row is
4843 the glyph row being updated, and updated_area is the area of that
4844 row being updated. */
4845
4846 static void
4847 x_write_glyphs (start, len)
4848 struct glyph *start;
4849 int len;
4850 {
4851 int x, hpos, real_start, real_end;
4852
4853 xassert (updated_window && updated_row);
4854 BLOCK_INPUT;
4855
4856 /* Write glyphs. */
4857
4858 hpos = start - updated_row->glyphs[updated_area];
4859 x = x_draw_glyphs (updated_window, output_cursor.x,
4860 updated_row, updated_area,
4861 hpos, hpos + len,
4862 (updated_row->inverse_p
4863 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4864 &real_start, &real_end, 0);
4865
4866 /* If we drew over the cursor, note that it is not visible any more. */
4867 note_overwritten_text_cursor (updated_window, real_start,
4868 real_end - real_start);
4869
4870 UNBLOCK_INPUT;
4871
4872 /* Advance the output cursor. */
4873 output_cursor.hpos += len;
4874 output_cursor.x = x;
4875 }
4876
4877
4878 /* Insert LEN glyphs from START at the nominal cursor position. */
4879
4880 static void
4881 x_insert_glyphs (start, len)
4882 struct glyph *start;
4883 register int len;
4884 {
4885 struct frame *f;
4886 struct window *w;
4887 int line_height, shift_by_width, shifted_region_width;
4888 struct glyph_row *row;
4889 struct glyph *glyph;
4890 int frame_x, frame_y, hpos, real_start, real_end;
4891
4892 xassert (updated_window && updated_row);
4893 BLOCK_INPUT;
4894 w = updated_window;
4895 f = XFRAME (WINDOW_FRAME (w));
4896
4897 /* Get the height of the line we are in. */
4898 row = updated_row;
4899 line_height = row->height;
4900
4901 /* Get the width of the glyphs to insert. */
4902 shift_by_width = 0;
4903 for (glyph = start; glyph < start + len; ++glyph)
4904 shift_by_width += glyph->pixel_width;
4905
4906 /* Get the width of the region to shift right. */
4907 shifted_region_width = (window_box_width (w, updated_area)
4908 - output_cursor.x
4909 - shift_by_width);
4910
4911 /* Shift right. */
4912 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4913 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4914 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4915 f->output_data.x->normal_gc,
4916 frame_x, frame_y,
4917 shifted_region_width, line_height,
4918 frame_x + shift_by_width, frame_y);
4919
4920 /* Write the glyphs. */
4921 hpos = start - row->glyphs[updated_area];
4922 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4923 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4924 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4925
4926 /* Advance the output cursor. */
4927 output_cursor.hpos += len;
4928 output_cursor.x += shift_by_width;
4929 UNBLOCK_INPUT;
4930 }
4931
4932
4933 /* Delete N glyphs at the nominal cursor position. Not implemented
4934 for X frames. */
4935
4936 static void
4937 x_delete_glyphs (n)
4938 register int n;
4939 {
4940 abort ();
4941 }
4942
4943
4944 /* Erase the current text line from the nominal cursor position
4945 (inclusive) to pixel column TO_X (exclusive). The idea is that
4946 everything from TO_X onward is already erased.
4947
4948 TO_X is a pixel position relative to updated_area of
4949 updated_window. TO_X == -1 means clear to the end of this area. */
4950
4951 static void
4952 x_clear_end_of_line (to_x)
4953 int to_x;
4954 {
4955 struct frame *f;
4956 struct window *w = updated_window;
4957 int max_x, min_y, max_y;
4958 int from_x, from_y, to_y;
4959
4960 xassert (updated_window && updated_row);
4961 f = XFRAME (w->frame);
4962
4963 if (updated_row->full_width_p)
4964 {
4965 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4966 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4967 && !w->pseudo_window_p)
4968 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4969 }
4970 else
4971 max_x = window_box_width (w, updated_area);
4972 max_y = window_text_bottom_y (w);
4973
4974 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4975 of window. For TO_X > 0, truncate to end of drawing area. */
4976 if (to_x == 0)
4977 return;
4978 else if (to_x < 0)
4979 to_x = max_x;
4980 else
4981 to_x = min (to_x, max_x);
4982
4983 to_y = min (max_y, output_cursor.y + updated_row->height);
4984
4985 /* Notice if the cursor will be cleared by this operation. */
4986 if (!updated_row->full_width_p)
4987 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4988
4989 from_x = output_cursor.x;
4990
4991 /* Translate to frame coordinates. */
4992 if (updated_row->full_width_p)
4993 {
4994 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4995 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4996 }
4997 else
4998 {
4999 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5000 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5001 }
5002
5003 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5004 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5005 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5006
5007 /* Prevent inadvertently clearing to end of the X window. */
5008 if (to_x > from_x && to_y > from_y)
5009 {
5010 BLOCK_INPUT;
5011 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5012 from_x, from_y, to_x - from_x, to_y - from_y,
5013 False);
5014 UNBLOCK_INPUT;
5015 }
5016 }
5017
5018
5019 /* Clear entire frame. If updating_frame is non-null, clear that
5020 frame. Otherwise clear the selected frame. */
5021
5022 static void
5023 x_clear_frame ()
5024 {
5025 struct frame *f;
5026
5027 if (updating_frame)
5028 f = updating_frame;
5029 else
5030 f = SELECTED_FRAME ();
5031
5032 /* Clearing the frame will erase any cursor, so mark them all as no
5033 longer visible. */
5034 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5035 output_cursor.hpos = output_cursor.vpos = 0;
5036 output_cursor.x = -1;
5037
5038 /* We don't set the output cursor here because there will always
5039 follow an explicit cursor_to. */
5040 BLOCK_INPUT;
5041 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5042
5043 /* We have to clear the scroll bars, too. If we have changed
5044 colors or something like that, then they should be notified. */
5045 x_scroll_bar_clear (f);
5046
5047 XFlush (FRAME_X_DISPLAY (f));
5048 UNBLOCK_INPUT;
5049 }
5050
5051
5052 \f
5053 /* Invert the middle quarter of the frame for .15 sec. */
5054
5055 /* We use the select system call to do the waiting, so we have to make
5056 sure it's available. If it isn't, we just won't do visual bells. */
5057
5058 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5059
5060
5061 /* Subtract the `struct timeval' values X and Y, storing the result in
5062 *RESULT. Return 1 if the difference is negative, otherwise 0. */
5063
5064 static int
5065 timeval_subtract (result, x, y)
5066 struct timeval *result, x, y;
5067 {
5068 /* Perform the carry for the later subtraction by updating y. This
5069 is safer because on some systems the tv_sec member is unsigned. */
5070 if (x.tv_usec < y.tv_usec)
5071 {
5072 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5073 y.tv_usec -= 1000000 * nsec;
5074 y.tv_sec += nsec;
5075 }
5076
5077 if (x.tv_usec - y.tv_usec > 1000000)
5078 {
5079 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5080 y.tv_usec += 1000000 * nsec;
5081 y.tv_sec -= nsec;
5082 }
5083
5084 /* Compute the time remaining to wait. tv_usec is certainly
5085 positive. */
5086 result->tv_sec = x.tv_sec - y.tv_sec;
5087 result->tv_usec = x.tv_usec - y.tv_usec;
5088
5089 /* Return indication of whether the result should be considered
5090 negative. */
5091 return x.tv_sec < y.tv_sec;
5092 }
5093
5094 void
5095 XTflash (f)
5096 struct frame *f;
5097 {
5098 BLOCK_INPUT;
5099
5100 {
5101 GC gc;
5102
5103 /* Create a GC that will use the GXxor function to flip foreground
5104 pixels into background pixels. */
5105 {
5106 XGCValues values;
5107
5108 values.function = GXxor;
5109 values.foreground = (f->output_data.x->foreground_pixel
5110 ^ f->output_data.x->background_pixel);
5111
5112 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5113 GCFunction | GCForeground, &values);
5114 }
5115
5116 {
5117 /* Get the height not including a menu bar widget. */
5118 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5119 /* Height of each line to flash. */
5120 int flash_height = FRAME_LINE_HEIGHT (f);
5121 /* These will be the left and right margins of the rectangles. */
5122 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5123 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5124
5125 int width;
5126
5127 /* Don't flash the area between a scroll bar and the frame
5128 edge it is next to. */
5129 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5130 {
5131 case vertical_scroll_bar_left:
5132 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5133 break;
5134
5135 case vertical_scroll_bar_right:
5136 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5137 break;
5138
5139 default:
5140 break;
5141 }
5142
5143 width = flash_right - flash_left;
5144
5145 /* If window is tall, flash top and bottom line. */
5146 if (height > 3 * FRAME_LINE_HEIGHT (f))
5147 {
5148 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5149 flash_left,
5150 (FRAME_INTERNAL_BORDER_WIDTH (f)
5151 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5152 width, flash_height);
5153 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5154 flash_left,
5155 (height - flash_height
5156 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5157 width, flash_height);
5158 }
5159 else
5160 /* If it is short, flash it all. */
5161 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5162 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5163 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5164
5165 x_flush (f);
5166
5167 {
5168 struct timeval wakeup;
5169
5170 EMACS_GET_TIME (wakeup);
5171
5172 /* Compute time to wait until, propagating carry from usecs. */
5173 wakeup.tv_usec += 150000;
5174 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5175 wakeup.tv_usec %= 1000000;
5176
5177 /* Keep waiting until past the time wakeup. */
5178 while (1)
5179 {
5180 struct timeval timeout;
5181
5182 EMACS_GET_TIME (timeout);
5183
5184 /* In effect, timeout = wakeup - timeout.
5185 Break if result would be negative. */
5186 if (timeval_subtract (&timeout, wakeup, timeout))
5187 break;
5188
5189 /* Try to wait that long--but we might wake up sooner. */
5190 select (0, NULL, NULL, NULL, &timeout);
5191 }
5192 }
5193
5194 /* If window is tall, flash top and bottom line. */
5195 if (height > 3 * FRAME_LINE_HEIGHT (f))
5196 {
5197 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5198 flash_left,
5199 (FRAME_INTERNAL_BORDER_WIDTH (f)
5200 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
5201 width, flash_height);
5202 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5203 flash_left,
5204 (height - flash_height
5205 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5206 width, flash_height);
5207 }
5208 else
5209 /* If it is short, flash it all. */
5210 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5211 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5212 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5213
5214 XFreeGC (FRAME_X_DISPLAY (f), gc);
5215 x_flush (f);
5216 }
5217 }
5218
5219 UNBLOCK_INPUT;
5220 }
5221
5222 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
5223
5224
5225 /* Make audible bell. */
5226
5227 void
5228 XTring_bell ()
5229 {
5230 struct frame *f = SELECTED_FRAME ();
5231
5232 if (FRAME_X_DISPLAY (f))
5233 {
5234 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5235 if (visible_bell)
5236 XTflash (f);
5237 else
5238 #endif
5239 {
5240 BLOCK_INPUT;
5241 XBell (FRAME_X_DISPLAY (f), 0);
5242 XFlush (FRAME_X_DISPLAY (f));
5243 UNBLOCK_INPUT;
5244 }
5245 }
5246 }
5247
5248 \f
5249 /* Specify how many text lines, from the top of the window,
5250 should be affected by insert-lines and delete-lines operations.
5251 This, and those operations, are used only within an update
5252 that is bounded by calls to x_update_begin and x_update_end. */
5253
5254 static void
5255 XTset_terminal_window (n)
5256 register int n;
5257 {
5258 /* This function intentionally left blank. */
5259 }
5260
5261
5262 \f
5263 /***********************************************************************
5264 Line Dance
5265 ***********************************************************************/
5266
5267 /* Perform an insert-lines or delete-lines operation, inserting N
5268 lines or deleting -N lines at vertical position VPOS. */
5269
5270 static void
5271 x_ins_del_lines (vpos, n)
5272 int vpos, n;
5273 {
5274 abort ();
5275 }
5276
5277
5278 /* Scroll part of the display as described by RUN. */
5279
5280 static void
5281 x_scroll_run (w, run)
5282 struct window *w;
5283 struct run *run;
5284 {
5285 struct frame *f = XFRAME (w->frame);
5286 int x, y, width, height, from_y, to_y, bottom_y;
5287
5288 /* Get frame-relative bounding box of the text display area of W,
5289 without mode lines. Include in this box the flags areas to the
5290 left and right of W. */
5291 window_box (w, -1, &x, &y, &width, &height);
5292 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5293 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
5294
5295 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5296 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5297 bottom_y = y + height;
5298
5299 if (to_y < from_y)
5300 {
5301 /* Scrolling up. Make sure we don't copy part of the mode
5302 line at the bottom. */
5303 if (from_y + run->height > bottom_y)
5304 height = bottom_y - from_y;
5305 else
5306 height = run->height;
5307 }
5308 else
5309 {
5310 /* Scolling down. Make sure we don't copy over the mode line.
5311 at the bottom. */
5312 if (to_y + run->height > bottom_y)
5313 height = bottom_y - to_y;
5314 else
5315 height = run->height;
5316 }
5317
5318 BLOCK_INPUT;
5319
5320 /* Cursor off. Will be switched on again in x_update_window_end. */
5321 updated_window = w;
5322 x_clear_cursor (w);
5323
5324 XCopyArea (FRAME_X_DISPLAY (f),
5325 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5326 f->output_data.x->normal_gc,
5327 x, from_y,
5328 width, height,
5329 x, to_y);
5330
5331 UNBLOCK_INPUT;
5332 }
5333
5334
5335 \f
5336 /***********************************************************************
5337 Exposure Events
5338 ***********************************************************************/
5339
5340 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5341 corner of the exposed rectangle. W and H are width and height of
5342 the exposed area. All are pixel values. W or H zero means redraw
5343 the entire frame. */
5344
5345 static void
5346 expose_frame (f, x, y, w, h)
5347 struct frame *f;
5348 int x, y, w, h;
5349 {
5350 XRectangle r;
5351
5352 TRACE ((stderr, "expose_frame "));
5353
5354 /* No need to redraw if frame will be redrawn soon. */
5355 if (FRAME_GARBAGED_P (f))
5356 {
5357 TRACE ((stderr, " garbaged\n"));
5358 return;
5359 }
5360
5361 /* If basic faces haven't been realized yet, there is no point in
5362 trying to redraw anything. This can happen when we get an expose
5363 event while Emacs is starting, e.g. by moving another window. */
5364 if (FRAME_FACE_CACHE (f) == NULL
5365 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5366 {
5367 TRACE ((stderr, " no faces\n"));
5368 return;
5369 }
5370
5371 if (w == 0 || h == 0)
5372 {
5373 r.x = r.y = 0;
5374 r.width = CANON_X_UNIT (f) * f->width;
5375 r.height = CANON_Y_UNIT (f) * f->height;
5376 }
5377 else
5378 {
5379 r.x = x;
5380 r.y = y;
5381 r.width = w;
5382 r.height = h;
5383 }
5384
5385 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5386 expose_window_tree (XWINDOW (f->root_window), &r);
5387
5388 if (WINDOWP (f->tool_bar_window))
5389 {
5390 struct window *w = XWINDOW (f->tool_bar_window);
5391 XRectangle window_rect;
5392 XRectangle intersection_rect;
5393 int window_x, window_y, window_width, window_height;
5394
5395
5396 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5397 window_rect.x = window_x;
5398 window_rect.y = window_y;
5399 window_rect.width = window_width;
5400 window_rect.height = window_height;
5401
5402 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5403 expose_window (w, &intersection_rect);
5404 }
5405
5406 #ifndef USE_X_TOOLKIT
5407 if (WINDOWP (f->menu_bar_window))
5408 {
5409 struct window *w = XWINDOW (f->menu_bar_window);
5410 XRectangle window_rect;
5411 XRectangle intersection_rect;
5412 int window_x, window_y, window_width, window_height;
5413
5414
5415 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5416 window_rect.x = window_x;
5417 window_rect.y = window_y;
5418 window_rect.width = window_width;
5419 window_rect.height = window_height;
5420
5421 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5422 expose_window (w, &intersection_rect);
5423 }
5424 #endif /* not USE_X_TOOLKIT */
5425 }
5426
5427
5428 /* Redraw (parts) of all windows in the window tree rooted at W that
5429 intersect R. R contains frame pixel coordinates. */
5430
5431 static void
5432 expose_window_tree (w, r)
5433 struct window *w;
5434 XRectangle *r;
5435 {
5436 while (w)
5437 {
5438 if (!NILP (w->hchild))
5439 expose_window_tree (XWINDOW (w->hchild), r);
5440 else if (!NILP (w->vchild))
5441 expose_window_tree (XWINDOW (w->vchild), r);
5442 else
5443 {
5444 XRectangle window_rect;
5445 XRectangle intersection_rect;
5446 struct frame *f = XFRAME (w->frame);
5447 int window_x, window_y, window_width, window_height;
5448
5449 /* Frame-relative pixel rectangle of W. */
5450 window_box (w, -1, &window_x, &window_y, &window_width,
5451 &window_height);
5452 window_rect.x
5453 = (window_x
5454 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
5455 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5456 window_rect.y = window_y;
5457 window_rect.width
5458 = (window_width
5459 + FRAME_X_FLAGS_AREA_WIDTH (f)
5460 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5461 window_rect.height
5462 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5463
5464 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5465 expose_window (w, &intersection_rect);
5466 }
5467
5468 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5469 }
5470 }
5471
5472
5473 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5474 which intersects rectangle R. R is in window-relative coordinates. */
5475
5476 static void
5477 expose_area (w, row, r, area)
5478 struct window *w;
5479 struct glyph_row *row;
5480 XRectangle *r;
5481 enum glyph_row_area area;
5482 {
5483 int x;
5484 struct glyph *first = row->glyphs[area];
5485 struct glyph *end = row->glyphs[area] + row->used[area];
5486 struct glyph *last;
5487 int first_x;
5488
5489 /* Set x to the window-relative start position for drawing glyphs of
5490 AREA. The first glyph of the text area can be partially visible.
5491 The first glyphs of other areas cannot. */
5492 if (area == LEFT_MARGIN_AREA)
5493 x = 0;
5494 else if (area == TEXT_AREA)
5495 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5496 else
5497 x = (window_box_width (w, LEFT_MARGIN_AREA)
5498 + window_box_width (w, TEXT_AREA));
5499
5500 if (area == TEXT_AREA && row->fill_line_p)
5501 /* If row extends face to end of line write the whole line. */
5502 x_draw_glyphs (w, x, row, area,
5503 0, row->used[area],
5504 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5505 NULL, NULL, 0);
5506 else
5507 {
5508 /* Find the first glyph that must be redrawn. */
5509 while (first < end
5510 && x + first->pixel_width < r->x)
5511 {
5512 x += first->pixel_width;
5513 ++first;
5514 }
5515
5516 /* Find the last one. */
5517 last = first;
5518 first_x = x;
5519 while (last < end
5520 && x < r->x + r->width)
5521 {
5522 x += last->pixel_width;
5523 ++last;
5524 }
5525
5526 /* Repaint. */
5527 if (last > first)
5528 x_draw_glyphs (w, first_x, row, area,
5529 first - row->glyphs[area],
5530 last - row->glyphs[area],
5531 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5532 NULL, NULL, 0);
5533 }
5534 }
5535
5536
5537 /* Redraw the parts of the glyph row ROW on window W intersecting
5538 rectangle R. R is in window-relative coordinates. */
5539
5540 static void
5541 expose_line (w, row, r)
5542 struct window *w;
5543 struct glyph_row *row;
5544 XRectangle *r;
5545 {
5546 xassert (row->enabled_p);
5547
5548 if (row->mode_line_p || w->pseudo_window_p)
5549 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5550 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5551 NULL, NULL, 0);
5552 else
5553 {
5554 if (row->used[LEFT_MARGIN_AREA])
5555 expose_area (w, row, r, LEFT_MARGIN_AREA);
5556 if (row->used[TEXT_AREA])
5557 expose_area (w, row, r, TEXT_AREA);
5558 if (row->used[RIGHT_MARGIN_AREA])
5559 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5560 x_draw_row_bitmaps (w, row);
5561 }
5562 }
5563
5564
5565 /* Return non-zero if W's cursor intersects rectangle R. */
5566
5567 static int
5568 x_phys_cursor_in_rect_p (w, r)
5569 struct window *w;
5570 XRectangle *r;
5571 {
5572 XRectangle cr, result;
5573 struct glyph *cursor_glyph;
5574
5575 cursor_glyph = get_phys_cursor_glyph (w);
5576 if (cursor_glyph)
5577 {
5578 cr.x = w->phys_cursor.x;
5579 cr.y = w->phys_cursor.y;
5580 cr.width = cursor_glyph->pixel_width;
5581 cr.height = w->phys_cursor_height;
5582 return x_intersect_rectangles (&cr, r, &result);
5583 }
5584 else
5585 return 0;
5586 }
5587
5588
5589 /* Redraw a rectangle of window W. R is a rectangle in window
5590 relative coordinates. Call this function with input blocked. */
5591
5592 static void
5593 expose_window (w, r)
5594 struct window *w;
5595 XRectangle *r;
5596 {
5597 struct glyph_row *row;
5598 int y;
5599 int yb = window_text_bottom_y (w);
5600 int cursor_cleared_p;
5601
5602 /* If window is not yet fully initialized, do nothing. This can
5603 happen when toolkit scroll bars are used and a window is split.
5604 Reconfiguring the scroll bar will generate an expose for a newly
5605 created window. */
5606 if (w->current_matrix == NULL)
5607 return;
5608
5609 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5610 r->x, r->y, r->width, r->height));
5611
5612 /* Convert to window coordinates. */
5613 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5614 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
5615
5616 /* Turn off the cursor. */
5617 if (!w->pseudo_window_p
5618 && x_phys_cursor_in_rect_p (w, r))
5619 {
5620 x_clear_cursor (w);
5621 cursor_cleared_p = 1;
5622 }
5623 else
5624 cursor_cleared_p = 0;
5625
5626 /* Find the first row intersecting the rectangle R. */
5627 row = w->current_matrix->rows;
5628 y = 0;
5629 while (row->enabled_p
5630 && y < yb
5631 && y + row->height < r->y)
5632 {
5633 y += row->height;
5634 ++row;
5635 }
5636
5637 /* Display the text in the rectangle, one text line at a time. */
5638 while (row->enabled_p
5639 && y < yb
5640 && y < r->y + r->height)
5641 {
5642 expose_line (w, row, r);
5643 y += row->height;
5644 ++row;
5645 }
5646
5647 /* Display the mode line if there is one. */
5648 if (WINDOW_WANTS_MODELINE_P (w)
5649 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5650 row->enabled_p)
5651 && row->y < r->y + r->height)
5652 expose_line (w, row, r);
5653
5654 if (!w->pseudo_window_p)
5655 {
5656 /* Draw border between windows. */
5657 x_draw_vertical_border (w);
5658
5659 /* Turn the cursor on again. */
5660 if (cursor_cleared_p)
5661 x_update_window_cursor (w, 1);
5662 }
5663 }
5664
5665
5666 /* Determine the intersection of two rectangles R1 and R2. Return
5667 the intersection in *RESULT. Value is non-zero if RESULT is not
5668 empty. */
5669
5670 static int
5671 x_intersect_rectangles (r1, r2, result)
5672 XRectangle *r1, *r2, *result;
5673 {
5674 XRectangle *left, *right;
5675 XRectangle *upper, *lower;
5676 int intersection_p = 0;
5677
5678 /* Rearrange so that R1 is the left-most rectangle. */
5679 if (r1->x < r2->x)
5680 left = r1, right = r2;
5681 else
5682 left = r2, right = r1;
5683
5684 /* X0 of the intersection is right.x0, if this is inside R1,
5685 otherwise there is no intersection. */
5686 if (right->x <= left->x + left->width)
5687 {
5688 result->x = right->x;
5689
5690 /* The right end of the intersection is the minimum of the
5691 the right ends of left and right. */
5692 result->width = (min (left->x + left->width, right->x + right->width)
5693 - result->x);
5694
5695 /* Same game for Y. */
5696 if (r1->y < r2->y)
5697 upper = r1, lower = r2;
5698 else
5699 upper = r2, lower = r1;
5700
5701 /* The upper end of the intersection is lower.y0, if this is inside
5702 of upper. Otherwise, there is no intersection. */
5703 if (lower->y <= upper->y + upper->height)
5704 {
5705 result->y = lower->y;
5706
5707 /* The lower end of the intersection is the minimum of the lower
5708 ends of upper and lower. */
5709 result->height = (min (lower->y + lower->height,
5710 upper->y + upper->height)
5711 - result->y);
5712 intersection_p = 1;
5713 }
5714 }
5715
5716 return intersection_p;
5717 }
5718
5719
5720
5721
5722 \f
5723 static void
5724 frame_highlight (f)
5725 struct frame *f;
5726 {
5727 /* We used to only do this if Vx_no_window_manager was non-nil, but
5728 the ICCCM (section 4.1.6) says that the window's border pixmap
5729 and border pixel are window attributes which are "private to the
5730 client", so we can always change it to whatever we want. */
5731 BLOCK_INPUT;
5732 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5733 f->output_data.x->border_pixel);
5734 UNBLOCK_INPUT;
5735 x_update_cursor (f, 1);
5736 }
5737
5738 static void
5739 frame_unhighlight (f)
5740 struct frame *f;
5741 {
5742 /* We used to only do this if Vx_no_window_manager was non-nil, but
5743 the ICCCM (section 4.1.6) says that the window's border pixmap
5744 and border pixel are window attributes which are "private to the
5745 client", so we can always change it to whatever we want. */
5746 BLOCK_INPUT;
5747 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5748 f->output_data.x->border_tile);
5749 UNBLOCK_INPUT;
5750 x_update_cursor (f, 1);
5751 }
5752
5753 /* The focus has changed. Update the frames as necessary to reflect
5754 the new situation. Note that we can't change the selected frame
5755 here, because the Lisp code we are interrupting might become confused.
5756 Each event gets marked with the frame in which it occurred, so the
5757 Lisp code can tell when the switch took place by examining the events. */
5758
5759 static void
5760 x_new_focus_frame (dpyinfo, frame)
5761 struct x_display_info *dpyinfo;
5762 struct frame *frame;
5763 {
5764 struct frame *old_focus = dpyinfo->x_focus_frame;
5765
5766 if (frame != dpyinfo->x_focus_frame)
5767 {
5768 /* Set this before calling other routines, so that they see
5769 the correct value of x_focus_frame. */
5770 dpyinfo->x_focus_frame = frame;
5771
5772 if (old_focus && old_focus->auto_lower)
5773 x_lower_frame (old_focus);
5774
5775 #if 0
5776 selected_frame = frame;
5777 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5778 selected_frame);
5779 Fselect_window (selected_frame->selected_window);
5780 choose_minibuf_frame ();
5781 #endif /* ! 0 */
5782
5783 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5784 pending_autoraise_frame = dpyinfo->x_focus_frame;
5785 else
5786 pending_autoraise_frame = 0;
5787 }
5788
5789 x_frame_rehighlight (dpyinfo);
5790 }
5791
5792 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5793
5794 void
5795 x_mouse_leave (dpyinfo)
5796 struct x_display_info *dpyinfo;
5797 {
5798 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
5799 }
5800
5801 /* The focus has changed, or we have redirected a frame's focus to
5802 another frame (this happens when a frame uses a surrogate
5803 mini-buffer frame). Shift the highlight as appropriate.
5804
5805 The FRAME argument doesn't necessarily have anything to do with which
5806 frame is being highlighted or un-highlighted; we only use it to find
5807 the appropriate X display info. */
5808
5809 static void
5810 XTframe_rehighlight (frame)
5811 struct frame *frame;
5812 {
5813 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5814 }
5815
5816 static void
5817 x_frame_rehighlight (dpyinfo)
5818 struct x_display_info *dpyinfo;
5819 {
5820 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5821
5822 if (dpyinfo->x_focus_frame)
5823 {
5824 dpyinfo->x_highlight_frame
5825 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5826 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5827 : dpyinfo->x_focus_frame);
5828 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
5829 {
5830 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5831 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
5832 }
5833 }
5834 else
5835 dpyinfo->x_highlight_frame = 0;
5836
5837 if (dpyinfo->x_highlight_frame != old_highlight)
5838 {
5839 if (old_highlight)
5840 frame_unhighlight (old_highlight);
5841 if (dpyinfo->x_highlight_frame)
5842 frame_highlight (dpyinfo->x_highlight_frame);
5843 }
5844 }
5845
5846
5847 \f
5848 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
5849
5850 /* Initialize mode_switch_bit and modifier_meaning. */
5851 static void
5852 x_find_modifier_meanings (dpyinfo)
5853 struct x_display_info *dpyinfo;
5854 {
5855 int min_code, max_code;
5856 KeySym *syms;
5857 int syms_per_code;
5858 XModifierKeymap *mods;
5859
5860 dpyinfo->meta_mod_mask = 0;
5861 dpyinfo->shift_lock_mask = 0;
5862 dpyinfo->alt_mod_mask = 0;
5863 dpyinfo->super_mod_mask = 0;
5864 dpyinfo->hyper_mod_mask = 0;
5865
5866 #ifdef HAVE_X11R4
5867 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
5868 #else
5869 min_code = dpyinfo->display->min_keycode;
5870 max_code = dpyinfo->display->max_keycode;
5871 #endif
5872
5873 syms = XGetKeyboardMapping (dpyinfo->display,
5874 min_code, max_code - min_code + 1,
5875 &syms_per_code);
5876 mods = XGetModifierMapping (dpyinfo->display);
5877
5878 /* Scan the modifier table to see which modifier bits the Meta and
5879 Alt keysyms are on. */
5880 {
5881 int row, col; /* The row and column in the modifier table. */
5882
5883 for (row = 3; row < 8; row++)
5884 for (col = 0; col < mods->max_keypermod; col++)
5885 {
5886 KeyCode code
5887 = mods->modifiermap[(row * mods->max_keypermod) + col];
5888
5889 /* Zeroes are used for filler. Skip them. */
5890 if (code == 0)
5891 continue;
5892
5893 /* Are any of this keycode's keysyms a meta key? */
5894 {
5895 int code_col;
5896
5897 for (code_col = 0; code_col < syms_per_code; code_col++)
5898 {
5899 int sym = syms[((code - min_code) * syms_per_code) + code_col];
5900
5901 switch (sym)
5902 {
5903 case XK_Meta_L:
5904 case XK_Meta_R:
5905 dpyinfo->meta_mod_mask |= (1 << row);
5906 break;
5907
5908 case XK_Alt_L:
5909 case XK_Alt_R:
5910 dpyinfo->alt_mod_mask |= (1 << row);
5911 break;
5912
5913 case XK_Hyper_L:
5914 case XK_Hyper_R:
5915 dpyinfo->hyper_mod_mask |= (1 << row);
5916 break;
5917
5918 case XK_Super_L:
5919 case XK_Super_R:
5920 dpyinfo->super_mod_mask |= (1 << row);
5921 break;
5922
5923 case XK_Shift_Lock:
5924 /* Ignore this if it's not on the lock modifier. */
5925 if ((1 << row) == LockMask)
5926 dpyinfo->shift_lock_mask = LockMask;
5927 break;
5928 }
5929 }
5930 }
5931 }
5932 }
5933
5934 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
5935 if (! dpyinfo->meta_mod_mask)
5936 {
5937 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5938 dpyinfo->alt_mod_mask = 0;
5939 }
5940
5941 /* If some keys are both alt and meta,
5942 make them just meta, not alt. */
5943 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
5944 {
5945 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
5946 }
5947
5948 XFree ((char *) syms);
5949 XFreeModifiermap (mods);
5950 }
5951
5952 /* Convert between the modifier bits X uses and the modifier bits
5953 Emacs uses. */
5954
5955 static unsigned int
5956 x_x_to_emacs_modifiers (dpyinfo, state)
5957 struct x_display_info *dpyinfo;
5958 unsigned int state;
5959 {
5960 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5961 | ((state & ControlMask) ? ctrl_modifier : 0)
5962 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5963 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5964 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5965 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
5966 }
5967
5968 static unsigned int
5969 x_emacs_to_x_modifiers (dpyinfo, state)
5970 struct x_display_info *dpyinfo;
5971 unsigned int state;
5972 {
5973 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5974 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5975 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5976 | ((state & shift_modifier) ? ShiftMask : 0)
5977 | ((state & ctrl_modifier) ? ControlMask : 0)
5978 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
5979 }
5980
5981 /* Convert a keysym to its name. */
5982
5983 char *
5984 x_get_keysym_name (keysym)
5985 KeySym keysym;
5986 {
5987 char *value;
5988
5989 BLOCK_INPUT;
5990 value = XKeysymToString (keysym);
5991 UNBLOCK_INPUT;
5992
5993 return value;
5994 }
5995
5996
5997 \f
5998 /* Mouse clicks and mouse movement. Rah. */
5999
6000 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6001 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6002 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6003 not force the value into range. */
6004
6005 void
6006 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
6007 FRAME_PTR f;
6008 register int pix_x, pix_y;
6009 register int *x, *y;
6010 XRectangle *bounds;
6011 int noclip;
6012 {
6013 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
6014 even for negative values. */
6015 if (pix_x < 0)
6016 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
6017 if (pix_y < 0)
6018 pix_y -= (f)->output_data.x->line_height - 1;
6019
6020 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6021 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6022
6023 if (bounds)
6024 {
6025 bounds->width = FONT_WIDTH (f->output_data.x->font);
6026 bounds->height = f->output_data.x->line_height;
6027 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6028 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6029 }
6030
6031 if (!noclip)
6032 {
6033 if (pix_x < 0)
6034 pix_x = 0;
6035 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6036 pix_x = FRAME_WINDOW_WIDTH (f);
6037
6038 if (pix_y < 0)
6039 pix_y = 0;
6040 else if (pix_y > f->height)
6041 pix_y = f->height;
6042 }
6043
6044 *x = pix_x;
6045 *y = pix_y;
6046 }
6047
6048
6049 /* Given HPOS/VPOS in the current matrix of W, return corresponding
6050 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6051 can't tell the positions because W's display is not up to date,
6052 return 0. */
6053
6054 int
6055 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6056 struct window *w;
6057 int hpos, vpos;
6058 int *frame_x, *frame_y;
6059 {
6060 int success_p;
6061
6062 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6063 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6064
6065 if (display_completed)
6066 {
6067 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6068 struct glyph *glyph = row->glyphs[TEXT_AREA];
6069 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6070
6071 *frame_y = row->y;
6072 *frame_x = row->x;
6073 while (glyph < end)
6074 {
6075 *frame_x += glyph->pixel_width;
6076 ++glyph;
6077 }
6078
6079 success_p = 1;
6080 }
6081 else
6082 {
6083 *frame_y = *frame_x = 0;
6084 success_p = 0;
6085 }
6086
6087 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6088 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6089 return success_p;
6090 }
6091
6092
6093 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6094
6095 If the event is a button press, then note that we have grabbed
6096 the mouse. */
6097
6098 static Lisp_Object
6099 construct_mouse_click (result, event, f)
6100 struct input_event *result;
6101 XButtonEvent *event;
6102 struct frame *f;
6103 {
6104 /* Make the event type no_event; we'll change that when we decide
6105 otherwise. */
6106 result->kind = mouse_click;
6107 result->code = event->button - Button1;
6108 result->timestamp = event->time;
6109 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6110 event->state)
6111 | (event->type == ButtonRelease
6112 ? up_modifier
6113 : down_modifier));
6114
6115 XSETINT (result->x, event->x);
6116 XSETINT (result->y, event->y);
6117 XSETFRAME (result->frame_or_window, f);
6118 return Qnil;
6119 }
6120
6121 #if 0 /* This function isn't called. --gerd */
6122
6123 /* Prepare a menu-event in *RESULT for placement in the input queue. */
6124
6125 static Lisp_Object
6126 construct_menu_click (result, event, f)
6127 struct input_event *result;
6128 XButtonEvent *event;
6129 struct frame *f;
6130 {
6131 /* Make the event type no_event; we'll change that when we decide
6132 otherwise. */
6133 result->kind = mouse_click;
6134 result->code = event->button - Button1;
6135 result->timestamp = event->time;
6136 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6137 event->state)
6138 | (event->type == ButtonRelease
6139 ? up_modifier
6140 : down_modifier));
6141
6142 XSETINT (result->x, event->x);
6143 XSETINT (result->y, -1);
6144 XSETFRAME (result->frame_or_window, f);
6145 }
6146
6147 #endif /* 0 */
6148
6149 \f
6150 /* Function to report a mouse movement to the mainstream Emacs code.
6151 The input handler calls this.
6152
6153 We have received a mouse movement event, which is given in *event.
6154 If the mouse is over a different glyph than it was last time, tell
6155 the mainstream emacs code by setting mouse_moved. If not, ask for
6156 another motion event, so we can check again the next time it moves. */
6157
6158 static XMotionEvent last_mouse_motion_event;
6159 static Lisp_Object last_mouse_motion_frame;
6160
6161 static void
6162 note_mouse_movement (frame, event)
6163 FRAME_PTR frame;
6164 XMotionEvent *event;
6165 {
6166 last_mouse_movement_time = event->time;
6167 last_mouse_motion_event = *event;
6168 XSETFRAME (last_mouse_motion_frame, frame);
6169
6170 if (event->window != FRAME_X_WINDOW (frame))
6171 {
6172 frame->mouse_moved = 1;
6173 last_mouse_scroll_bar = Qnil;
6174 note_mouse_highlight (frame, -1, -1);
6175 }
6176
6177 /* Has the mouse moved off the glyph it was on at the last sighting? */
6178 else if (event->x < last_mouse_glyph.x
6179 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6180 || event->y < last_mouse_glyph.y
6181 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
6182 {
6183 frame->mouse_moved = 1;
6184 last_mouse_scroll_bar = Qnil;
6185 note_mouse_highlight (frame, event->x, event->y);
6186 }
6187 }
6188
6189 /* This is used for debugging, to turn off note_mouse_highlight. */
6190
6191 int disable_mouse_highlight;
6192
6193
6194 \f
6195 /************************************************************************
6196 Mouse Face
6197 ************************************************************************/
6198
6199 /* Find the glyph under window-relative coordinates X/Y in window W.
6200 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6201 strings. Return in *HPOS and *VPOS the row and column number of
6202 the glyph found. Return in *AREA the glyph area containing X.
6203 Value is a pointer to the glyph found or null if X/Y is not on
6204 text, or we can't tell because W's current matrix is not up to
6205 date. */
6206
6207 static struct glyph *
6208 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6209 struct window *w;
6210 int x, y;
6211 int *hpos, *vpos, *area;
6212 {
6213 struct glyph *glyph, *end;
6214 struct glyph_row *row = NULL;
6215 int x0, i, left_area_width;
6216
6217 /* Find row containing Y. Give up if some row is not enabled. */
6218 for (i = 0; i < w->current_matrix->nrows; ++i)
6219 {
6220 row = MATRIX_ROW (w->current_matrix, i);
6221 if (!row->enabled_p)
6222 return NULL;
6223 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6224 break;
6225 }
6226
6227 *vpos = i;
6228 *hpos = 0;
6229
6230 /* Give up if Y is not in the window. */
6231 if (i == w->current_matrix->nrows)
6232 return NULL;
6233
6234 /* Get the glyph area containing X. */
6235 if (w->pseudo_window_p)
6236 {
6237 *area = TEXT_AREA;
6238 x0 = 0;
6239 }
6240 else
6241 {
6242 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6243 if (x < left_area_width)
6244 {
6245 *area = LEFT_MARGIN_AREA;
6246 x0 = 0;
6247 }
6248 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6249 {
6250 *area = TEXT_AREA;
6251 x0 = row->x + left_area_width;
6252 }
6253 else
6254 {
6255 *area = RIGHT_MARGIN_AREA;
6256 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6257 }
6258 }
6259
6260 /* Find glyph containing X. */
6261 glyph = row->glyphs[*area];
6262 end = glyph + row->used[*area];
6263 while (glyph < end)
6264 {
6265 if (x < x0 + glyph->pixel_width)
6266 {
6267 if (w->pseudo_window_p)
6268 break;
6269 else if (BUFFERP (glyph->object))
6270 break;
6271 }
6272
6273 x0 += glyph->pixel_width;
6274 ++glyph;
6275 }
6276
6277 if (glyph == end)
6278 return NULL;
6279
6280 *hpos = glyph - row->glyphs[*area];
6281 return glyph;
6282 }
6283
6284
6285 /* Convert frame-relative x/y to coordinates relative to window W.
6286 Takes pseudo-windows into account. */
6287
6288 static void
6289 frame_to_window_pixel_xy (w, x, y)
6290 struct window *w;
6291 int *x, *y;
6292 {
6293 if (w->pseudo_window_p)
6294 {
6295 /* A pseudo-window is always full-width, and starts at the
6296 left edge of the frame, plus a frame border. */
6297 struct frame *f = XFRAME (w->frame);
6298 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6299 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6300 }
6301 else
6302 {
6303 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6304 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6305 }
6306 }
6307
6308
6309 /* Take proper action when mouse has moved to the mode or top line of
6310 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6311 mode line. X is relative to the start of the text display area of
6312 W, so the width of bitmap areas and scroll bars must be subtracted
6313 to get a position relative to the start of the mode line. */
6314
6315 static void
6316 note_mode_line_highlight (w, x, mode_line_p)
6317 struct window *w;
6318 int x, mode_line_p;
6319 {
6320 struct frame *f = XFRAME (w->frame);
6321 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6322 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6323 struct glyph_row *row;
6324
6325 if (mode_line_p)
6326 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6327 else
6328 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6329
6330 if (row->enabled_p)
6331 {
6332 struct glyph *glyph, *end;
6333 Lisp_Object help, map;
6334 int x0;
6335
6336 /* Find the glyph under X. */
6337 glyph = row->glyphs[TEXT_AREA];
6338 end = glyph + row->used[TEXT_AREA];
6339 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6340 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
6341 while (glyph < end
6342 && x >= x0 + glyph->pixel_width)
6343 {
6344 x0 += glyph->pixel_width;
6345 ++glyph;
6346 }
6347
6348 if (glyph < end
6349 && STRINGP (glyph->object)
6350 && XSTRING (glyph->object)->intervals
6351 && glyph->charpos >= 0
6352 && glyph->charpos < XSTRING (glyph->object)->size)
6353 {
6354 /* If we're on a string with `help-echo' text property,
6355 arrange for the help to be displayed. This is done by
6356 setting the global variable help_echo to the help string. */
6357 help = Fget_text_property (make_number (glyph->charpos),
6358 Qhelp_echo, glyph->object);
6359 if (!NILP (help))
6360 help_echo = help;
6361
6362 /* Change the mouse pointer according to what is under X/Y. */
6363 map = Fget_text_property (make_number (glyph->charpos),
6364 Qlocal_map, glyph->object);
6365 if (!NILP (Fkeymapp (map)))
6366 cursor = f->output_data.x->nontext_cursor;
6367 }
6368 }
6369
6370 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6371 }
6372
6373
6374 /* Take proper action when the mouse has moved to position X, Y on
6375 frame F as regards highlighting characters that have mouse-face
6376 properties. Also de-highlighting chars where the mouse was before.
6377 X and Y can be negative or out of range. */
6378
6379 static void
6380 note_mouse_highlight (f, x, y)
6381 struct frame *f;
6382 int x, y;
6383 {
6384 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6385 int portion;
6386 Lisp_Object window;
6387 struct window *w;
6388
6389 /* When a menu is active, don't highlight because this looks odd. */
6390 #ifdef USE_X_TOOLKIT
6391 if (popup_activated ())
6392 return;
6393 #endif
6394
6395 if (disable_mouse_highlight
6396 || !f->glyphs_initialized_p)
6397 return;
6398
6399 dpyinfo->mouse_face_mouse_x = x;
6400 dpyinfo->mouse_face_mouse_y = y;
6401 dpyinfo->mouse_face_mouse_frame = f;
6402
6403 if (dpyinfo->mouse_face_defer)
6404 return;
6405
6406 if (gc_in_progress)
6407 {
6408 dpyinfo->mouse_face_deferred_gc = 1;
6409 return;
6410 }
6411
6412 /* Which window is that in? */
6413 window = window_from_coordinates (f, x, y, &portion, 1);
6414
6415 /* If we were displaying active text in another window, clear that. */
6416 if (! EQ (window, dpyinfo->mouse_face_window))
6417 clear_mouse_face (dpyinfo);
6418
6419 /* Not on a window -> return. */
6420 if (!WINDOWP (window))
6421 return;
6422
6423 /* Convert to window-relative pixel coordinates. */
6424 w = XWINDOW (window);
6425 frame_to_window_pixel_xy (w, &x, &y);
6426
6427 /* Handle tool-bar window differently since it doesn't display a
6428 buffer. */
6429 if (EQ (window, f->tool_bar_window))
6430 {
6431 note_tool_bar_highlight (f, x, y);
6432 return;
6433 }
6434
6435 if (portion == 1 || portion == 3)
6436 {
6437 /* Mouse is on the mode or top line. */
6438 note_mode_line_highlight (w, x, portion == 1);
6439 return;
6440 }
6441 else
6442 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6443 f->output_data.x->text_cursor);
6444
6445 /* Are we in a window whose display is up to date?
6446 And verify the buffer's text has not changed. */
6447 if (/* Within text portion of the window. */
6448 portion == 0
6449 && EQ (w->window_end_valid, w->buffer)
6450 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6451 && (XFASTINT (w->last_overlay_modified)
6452 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
6453 {
6454 int hpos, vpos, pos, i, area;
6455 struct glyph *glyph;
6456
6457 /* Find the glyph under X/Y. */
6458 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6459
6460 /* Clear mouse face if X/Y not over text. */
6461 if (glyph == NULL
6462 || area != TEXT_AREA
6463 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6464 {
6465 clear_mouse_face (dpyinfo);
6466 return;
6467 }
6468
6469 pos = glyph->charpos;
6470 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6471
6472 /* Check for mouse-face and help-echo. */
6473 {
6474 Lisp_Object mouse_face, overlay, position;
6475 Lisp_Object *overlay_vec;
6476 int len, noverlays;
6477 struct buffer *obuf;
6478 int obegv, ozv;
6479
6480 /* If we get an out-of-range value, return now; avoid an error. */
6481 if (pos > BUF_Z (XBUFFER (w->buffer)))
6482 return;
6483
6484 /* Make the window's buffer temporarily current for
6485 overlays_at and compute_char_face. */
6486 obuf = current_buffer;
6487 current_buffer = XBUFFER (w->buffer);
6488 obegv = BEGV;
6489 ozv = ZV;
6490 BEGV = BEG;
6491 ZV = Z;
6492
6493 /* Is this char mouse-active or does it have help-echo? */
6494 XSETINT (position, pos);
6495
6496 /* Put all the overlays we want in a vector in overlay_vec.
6497 Store the length in len. If there are more than 10, make
6498 enough space for all, and try again. */
6499 len = 10;
6500 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6501 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6502 if (noverlays > len)
6503 {
6504 len = noverlays;
6505 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6506 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6507 }
6508
6509 noverlays = sort_overlays (overlay_vec, noverlays, w);
6510
6511 /* Check mouse-face highlighting. */
6512 if (! (EQ (window, dpyinfo->mouse_face_window)
6513 && vpos >= dpyinfo->mouse_face_beg_row
6514 && vpos <= dpyinfo->mouse_face_end_row
6515 && (vpos > dpyinfo->mouse_face_beg_row
6516 || hpos >= dpyinfo->mouse_face_beg_col)
6517 && (vpos < dpyinfo->mouse_face_end_row
6518 || hpos < dpyinfo->mouse_face_end_col
6519 || dpyinfo->mouse_face_past_end)))
6520 {
6521 /* Clear the display of the old active region, if any. */
6522 clear_mouse_face (dpyinfo);
6523
6524 /* Find the highest priority overlay that has a mouse-face prop. */
6525 overlay = Qnil;
6526 for (i = 0; i < noverlays; i++)
6527 {
6528 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6529 if (!NILP (mouse_face))
6530 {
6531 overlay = overlay_vec[i];
6532 break;
6533 }
6534 }
6535
6536 /* If no overlay applies, get a text property. */
6537 if (NILP (overlay))
6538 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6539
6540 /* Handle the overlay case. */
6541 if (! NILP (overlay))
6542 {
6543 /* Find the range of text around this char that
6544 should be active. */
6545 Lisp_Object before, after;
6546 int ignore;
6547
6548 before = Foverlay_start (overlay);
6549 after = Foverlay_end (overlay);
6550 /* Record this as the current active region. */
6551 fast_find_position (w, XFASTINT (before),
6552 &dpyinfo->mouse_face_beg_col,
6553 &dpyinfo->mouse_face_beg_row,
6554 &dpyinfo->mouse_face_beg_x,
6555 &dpyinfo->mouse_face_beg_y);
6556 dpyinfo->mouse_face_past_end
6557 = !fast_find_position (w, XFASTINT (after),
6558 &dpyinfo->mouse_face_end_col,
6559 &dpyinfo->mouse_face_end_row,
6560 &dpyinfo->mouse_face_end_x,
6561 &dpyinfo->mouse_face_end_y);
6562 dpyinfo->mouse_face_window = window;
6563 dpyinfo->mouse_face_face_id
6564 = face_at_buffer_position (w, pos, 0, 0,
6565 &ignore, pos + 1, 1);
6566
6567 /* Display it as active. */
6568 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6569 }
6570 /* Handle the text property case. */
6571 else if (! NILP (mouse_face))
6572 {
6573 /* Find the range of text around this char that
6574 should be active. */
6575 Lisp_Object before, after, beginning, end;
6576 int ignore;
6577
6578 beginning = Fmarker_position (w->start);
6579 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6580 - XFASTINT (w->window_end_pos)));
6581 before
6582 = Fprevious_single_property_change (make_number (pos + 1),
6583 Qmouse_face,
6584 w->buffer, beginning);
6585 after
6586 = Fnext_single_property_change (position, Qmouse_face,
6587 w->buffer, end);
6588 /* Record this as the current active region. */
6589 fast_find_position (w, XFASTINT (before),
6590 &dpyinfo->mouse_face_beg_col,
6591 &dpyinfo->mouse_face_beg_row,
6592 &dpyinfo->mouse_face_beg_x,
6593 &dpyinfo->mouse_face_beg_y);
6594 dpyinfo->mouse_face_past_end
6595 = !fast_find_position (w, XFASTINT (after),
6596 &dpyinfo->mouse_face_end_col,
6597 &dpyinfo->mouse_face_end_row,
6598 &dpyinfo->mouse_face_end_x,
6599 &dpyinfo->mouse_face_end_y);
6600 dpyinfo->mouse_face_window = window;
6601 dpyinfo->mouse_face_face_id
6602 = face_at_buffer_position (w, pos, 0, 0,
6603 &ignore, pos + 1, 1);
6604
6605 /* Display it as active. */
6606 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6607 }
6608 }
6609
6610 /* Look for a `help-echo' property. */
6611 {
6612 Lisp_Object help;
6613
6614 /* Check overlays first. */
6615 help = Qnil;
6616 for (i = 0; i < noverlays && NILP (help); ++i)
6617 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6618
6619 /* Try text properties. */
6620 if (NILP (help)
6621 && ((STRINGP (glyph->object)
6622 && glyph->charpos >= 0
6623 && glyph->charpos < XSTRING (glyph->object)->size)
6624 || (BUFFERP (glyph->object)
6625 && glyph->charpos >= BEGV
6626 && glyph->charpos < ZV)))
6627 help = Fget_text_property (make_number (glyph->charpos),
6628 Qhelp_echo, glyph->object);
6629
6630 if (!NILP (help))
6631 help_echo = help;
6632 }
6633
6634 BEGV = obegv;
6635 ZV = ozv;
6636 current_buffer = obuf;
6637 }
6638 }
6639 }
6640
6641 static void
6642 redo_mouse_highlight ()
6643 {
6644 if (!NILP (last_mouse_motion_frame)
6645 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6646 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6647 last_mouse_motion_event.x,
6648 last_mouse_motion_event.y);
6649 }
6650
6651
6652 \f
6653 /***********************************************************************
6654 Tool-bars
6655 ***********************************************************************/
6656
6657 static int x_tool_bar_item P_ ((struct frame *, int, int,
6658 struct glyph **, int *, int *, int *));
6659
6660 /* Tool-bar item index of the item on which a mouse button was pressed
6661 or -1. */
6662
6663 static int last_tool_bar_item;
6664
6665
6666 /* Get information about the tool-bar item at position X/Y on frame F.
6667 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6668 the current matrix of the tool-bar window of F, or NULL if not
6669 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6670 item in F->current_tool_bar_items. Value is
6671
6672 -1 if X/Y is not on a tool-bar item
6673 0 if X/Y is on the same item that was highlighted before.
6674 1 otherwise. */
6675
6676 static int
6677 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6678 struct frame *f;
6679 int x, y;
6680 struct glyph **glyph;
6681 int *hpos, *vpos, *prop_idx;
6682 {
6683 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6684 struct window *w = XWINDOW (f->tool_bar_window);
6685 int area;
6686
6687 /* Find the glyph under X/Y. */
6688 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6689 if (*glyph == NULL)
6690 return -1;
6691
6692 /* Get the start of this tool-bar item's properties in
6693 f->current_tool_bar_items. */
6694 if (!tool_bar_item_info (f, *glyph, prop_idx))
6695 return -1;
6696
6697 /* Is mouse on the highlighted item? */
6698 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6699 && *vpos >= dpyinfo->mouse_face_beg_row
6700 && *vpos <= dpyinfo->mouse_face_end_row
6701 && (*vpos > dpyinfo->mouse_face_beg_row
6702 || *hpos >= dpyinfo->mouse_face_beg_col)
6703 && (*vpos < dpyinfo->mouse_face_end_row
6704 || *hpos < dpyinfo->mouse_face_end_col
6705 || dpyinfo->mouse_face_past_end))
6706 return 0;
6707
6708 return 1;
6709 }
6710
6711
6712 /* Handle mouse button event on the tool-bar of frame F, at
6713 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6714 or ButtonRelase. */
6715
6716 static void
6717 x_handle_tool_bar_click (f, button_event)
6718 struct frame *f;
6719 XButtonEvent *button_event;
6720 {
6721 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6722 struct window *w = XWINDOW (f->tool_bar_window);
6723 int hpos, vpos, prop_idx;
6724 struct glyph *glyph;
6725 Lisp_Object enabled_p;
6726 int x = button_event->x;
6727 int y = button_event->y;
6728
6729 /* If not on the highlighted tool-bar item, return. */
6730 frame_to_window_pixel_xy (w, &x, &y);
6731 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6732 return;
6733
6734 /* If item is disabled, do nothing. */
6735 enabled_p = (XVECTOR (f->current_tool_bar_items)
6736 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6737 if (NILP (enabled_p))
6738 return;
6739
6740 if (button_event->type == ButtonPress)
6741 {
6742 /* Show item in pressed state. */
6743 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6744 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6745 last_tool_bar_item = prop_idx;
6746 }
6747 else
6748 {
6749 Lisp_Object key, frame;
6750 struct input_event event;
6751
6752 /* Show item in released state. */
6753 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6754 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6755
6756 key = (XVECTOR (f->current_tool_bar_items)
6757 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6758
6759 XSETFRAME (frame, f);
6760 event.kind = TOOL_BAR_EVENT;
6761 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6762 kbd_buffer_store_event (&event);
6763
6764 event.kind = TOOL_BAR_EVENT;
6765 event.frame_or_window = Fcons (frame, key);
6766 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6767 button_event->state);
6768 kbd_buffer_store_event (&event);
6769 last_tool_bar_item = -1;
6770 }
6771 }
6772
6773
6774 /* Possibly highlight a tool-bar item on frame F when mouse moves to
6775 tool-bar window-relative coordinates X/Y. Called from
6776 note_mouse_highlight. */
6777
6778 static void
6779 note_tool_bar_highlight (f, x, y)
6780 struct frame *f;
6781 int x, y;
6782 {
6783 Lisp_Object window = f->tool_bar_window;
6784 struct window *w = XWINDOW (window);
6785 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6786 int hpos, vpos;
6787 struct glyph *glyph;
6788 struct glyph_row *row;
6789 int i;
6790 Lisp_Object enabled_p;
6791 int prop_idx;
6792 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6793 int mouse_down_p, rc;
6794
6795 /* Function note_mouse_highlight is called with negative x(y
6796 values when mouse moves outside of the frame. */
6797 if (x <= 0 || y <= 0)
6798 {
6799 clear_mouse_face (dpyinfo);
6800 return;
6801 }
6802
6803 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6804 if (rc < 0)
6805 {
6806 /* Not on tool-bar item. */
6807 clear_mouse_face (dpyinfo);
6808 return;
6809 }
6810 else if (rc == 0)
6811 /* On same tool-bar item as before. */
6812 goto set_help_echo;
6813
6814 clear_mouse_face (dpyinfo);
6815
6816 /* Mouse is down, but on different tool-bar item? */
6817 mouse_down_p = (dpyinfo->grabbed
6818 && f == last_mouse_frame
6819 && FRAME_LIVE_P (f));
6820 if (mouse_down_p
6821 && last_tool_bar_item != prop_idx)
6822 return;
6823
6824 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6825 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6826
6827 /* If tool-bar item is not enabled, don't highlight it. */
6828 enabled_p = (XVECTOR (f->current_tool_bar_items)
6829 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6830 if (!NILP (enabled_p))
6831 {
6832 /* Compute the x-position of the glyph. In front and past the
6833 image is a space. We include this is the highlighted area. */
6834 row = MATRIX_ROW (w->current_matrix, vpos);
6835 for (i = x = 0; i < hpos; ++i)
6836 x += row->glyphs[TEXT_AREA][i].pixel_width;
6837
6838 /* Record this as the current active region. */
6839 dpyinfo->mouse_face_beg_col = hpos;
6840 dpyinfo->mouse_face_beg_row = vpos;
6841 dpyinfo->mouse_face_beg_x = x;
6842 dpyinfo->mouse_face_beg_y = row->y;
6843 dpyinfo->mouse_face_past_end = 0;
6844
6845 dpyinfo->mouse_face_end_col = hpos + 1;
6846 dpyinfo->mouse_face_end_row = vpos;
6847 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6848 dpyinfo->mouse_face_end_y = row->y;
6849 dpyinfo->mouse_face_window = window;
6850 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6851
6852 /* Display it as active. */
6853 show_mouse_face (dpyinfo, draw);
6854 dpyinfo->mouse_face_image_state = draw;
6855 }
6856
6857 set_help_echo:
6858
6859 /* Set help_echo to a help string.to display for this tool-bar item.
6860 XTread_socket does the rest. */
6861 help_echo = (XVECTOR (f->current_tool_bar_items)
6862 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6863 if (NILP (help_echo))
6864 help_echo = (XVECTOR (f->current_tool_bar_items)
6865 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6866 }
6867
6868
6869 \f
6870 /* Find the glyph matrix position of buffer position POS in window W.
6871 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6872 current glyphs must be up to date. If POS is above window start
6873 return (0, 0, 0, 0). If POS is after end of W, return end of
6874 last line in W. */
6875
6876 static int
6877 fast_find_position (w, pos, hpos, vpos, x, y)
6878 struct window *w;
6879 int pos;
6880 int *hpos, *vpos, *x, *y;
6881 {
6882 int i;
6883 int lastcol;
6884 int maybe_next_line_p = 0;
6885 int line_start_position;
6886 int yb = window_text_bottom_y (w);
6887 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6888 struct glyph_row *best_row = row;
6889 int row_vpos = 0, best_row_vpos = 0;
6890 int current_x;
6891
6892 while (row->y < yb)
6893 {
6894 if (row->used[TEXT_AREA])
6895 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6896 else
6897 line_start_position = 0;
6898
6899 if (line_start_position > pos)
6900 break;
6901 /* If the position sought is the end of the buffer,
6902 don't include the blank lines at the bottom of the window. */
6903 else if (line_start_position == pos
6904 && pos == BUF_ZV (XBUFFER (w->buffer)))
6905 {
6906 maybe_next_line_p = 1;
6907 break;
6908 }
6909 else if (line_start_position > 0)
6910 {
6911 best_row = row;
6912 best_row_vpos = row_vpos;
6913 }
6914
6915 if (row->y + row->height >= yb)
6916 break;
6917
6918 ++row;
6919 ++row_vpos;
6920 }
6921
6922 /* Find the right column within BEST_ROW. */
6923 lastcol = 0;
6924 current_x = best_row->x;
6925 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6926 {
6927 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6928 int charpos;
6929
6930 charpos = glyph->charpos;
6931 if (charpos == pos)
6932 {
6933 *hpos = i;
6934 *vpos = best_row_vpos;
6935 *x = current_x;
6936 *y = best_row->y;
6937 return 1;
6938 }
6939 else if (charpos > pos)
6940 break;
6941 else if (charpos > 0)
6942 lastcol = i;
6943
6944 current_x += glyph->pixel_width;
6945 }
6946
6947 /* If we're looking for the end of the buffer,
6948 and we didn't find it in the line we scanned,
6949 use the start of the following line. */
6950 if (maybe_next_line_p)
6951 {
6952 ++best_row;
6953 ++best_row_vpos;
6954 lastcol = 0;
6955 current_x = best_row->x;
6956 }
6957
6958 *vpos = best_row_vpos;
6959 *hpos = lastcol + 1;
6960 *x = current_x;
6961 *y = best_row->y;
6962 return 0;
6963 }
6964
6965
6966 /* Display the active region described by mouse_face_*
6967 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6968
6969 static void
6970 show_mouse_face (dpyinfo, draw)
6971 struct x_display_info *dpyinfo;
6972 enum draw_glyphs_face draw;
6973 {
6974 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6975 struct frame *f = XFRAME (WINDOW_FRAME (w));
6976 int i;
6977 int cursor_off_p = 0;
6978 struct cursor_pos saved_cursor;
6979
6980 saved_cursor = output_cursor;
6981
6982 /* If window is in the process of being destroyed, don't bother
6983 to do anything. */
6984 if (w->current_matrix == NULL)
6985 goto set_x_cursor;
6986
6987 /* Recognize when we are called to operate on rows that don't exist
6988 anymore. This can happen when a window is split. */
6989 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6990 goto set_x_cursor;
6991
6992 set_output_cursor (&w->phys_cursor);
6993
6994 /* Note that mouse_face_beg_row etc. are window relative. */
6995 for (i = dpyinfo->mouse_face_beg_row;
6996 i <= dpyinfo->mouse_face_end_row;
6997 i++)
6998 {
6999 int start_hpos, end_hpos, start_x;
7000 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7001
7002 /* Don't do anything if row doesn't have valid contents. */
7003 if (!row->enabled_p)
7004 continue;
7005
7006 /* For all but the first row, the highlight starts at column 0. */
7007 if (i == dpyinfo->mouse_face_beg_row)
7008 {
7009 start_hpos = dpyinfo->mouse_face_beg_col;
7010 start_x = dpyinfo->mouse_face_beg_x;
7011 }
7012 else
7013 {
7014 start_hpos = 0;
7015 start_x = 0;
7016 }
7017
7018 if (i == dpyinfo->mouse_face_end_row)
7019 end_hpos = dpyinfo->mouse_face_end_col;
7020 else
7021 end_hpos = row->used[TEXT_AREA];
7022
7023 /* If the cursor's in the text we are about to rewrite, turn the
7024 cursor off. */
7025 if (!w->pseudo_window_p
7026 && i == output_cursor.vpos
7027 && output_cursor.hpos >= start_hpos - 1
7028 && output_cursor.hpos <= end_hpos)
7029 {
7030 x_update_window_cursor (w, 0);
7031 cursor_off_p = 1;
7032 }
7033
7034 if (end_hpos > start_hpos)
7035 {
7036 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7037 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7038 start_hpos, end_hpos, draw, NULL, NULL, 0);
7039 }
7040 }
7041
7042 /* If we turned the cursor off, turn it back on. */
7043 if (cursor_off_p)
7044 x_display_cursor (w, 1,
7045 output_cursor.hpos, output_cursor.vpos,
7046 output_cursor.x, output_cursor.y);
7047
7048 output_cursor = saved_cursor;
7049
7050 set_x_cursor:
7051
7052 /* Change the mouse cursor. */
7053 if (draw == DRAW_NORMAL_TEXT)
7054 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7055 f->output_data.x->text_cursor);
7056 else if (draw == DRAW_MOUSE_FACE)
7057 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7058 f->output_data.x->cross_cursor);
7059 else
7060 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7061 f->output_data.x->nontext_cursor);
7062 }
7063
7064 /* Clear out the mouse-highlighted active region.
7065 Redraw it un-highlighted first. */
7066
7067 void
7068 clear_mouse_face (dpyinfo)
7069 struct x_display_info *dpyinfo;
7070 {
7071 if (tip_frame)
7072 return;
7073
7074 if (! NILP (dpyinfo->mouse_face_window))
7075 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7076
7077 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7078 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7079 dpyinfo->mouse_face_window = Qnil;
7080 }
7081
7082 /* Just discard the mouse face information for frame F, if any.
7083 This is used when the size of F is changed. */
7084
7085 void
7086 cancel_mouse_face (f)
7087 FRAME_PTR f;
7088 {
7089 Lisp_Object window;
7090 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7091
7092 window = dpyinfo->mouse_face_window;
7093 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7094 {
7095 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7096 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7097 dpyinfo->mouse_face_window = Qnil;
7098 }
7099 }
7100 \f
7101 static struct scroll_bar *x_window_to_scroll_bar ();
7102 static void x_scroll_bar_report_motion ();
7103
7104 /* Return the current position of the mouse.
7105 *fp should be a frame which indicates which display to ask about.
7106
7107 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7108 and *part to the frame, window, and scroll bar part that the mouse
7109 is over. Set *x and *y to the portion and whole of the mouse's
7110 position on the scroll bar.
7111
7112 If the mouse movement started elsewhere, set *fp to the frame the
7113 mouse is on, *bar_window to nil, and *x and *y to the character cell
7114 the mouse is over.
7115
7116 Set *time to the server time-stamp for the time at which the mouse
7117 was at this position.
7118
7119 Don't store anything if we don't have a valid set of values to report.
7120
7121 This clears the mouse_moved flag, so we can wait for the next mouse
7122 movement. */
7123
7124 static void
7125 XTmouse_position (fp, insist, bar_window, part, x, y, time)
7126 FRAME_PTR *fp;
7127 int insist;
7128 Lisp_Object *bar_window;
7129 enum scroll_bar_part *part;
7130 Lisp_Object *x, *y;
7131 unsigned long *time;
7132 {
7133 FRAME_PTR f1;
7134
7135 BLOCK_INPUT;
7136
7137 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7138 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7139 else
7140 {
7141 Window root;
7142 int root_x, root_y;
7143
7144 Window dummy_window;
7145 int dummy;
7146
7147 Lisp_Object frame, tail;
7148
7149 /* Clear the mouse-moved flag for every frame on this display. */
7150 FOR_EACH_FRAME (tail, frame)
7151 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7152 XFRAME (frame)->mouse_moved = 0;
7153
7154 last_mouse_scroll_bar = Qnil;
7155
7156 /* Figure out which root window we're on. */
7157 XQueryPointer (FRAME_X_DISPLAY (*fp),
7158 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
7159
7160 /* The root window which contains the pointer. */
7161 &root,
7162
7163 /* Trash which we can't trust if the pointer is on
7164 a different screen. */
7165 &dummy_window,
7166
7167 /* The position on that root window. */
7168 &root_x, &root_y,
7169
7170 /* More trash we can't trust. */
7171 &dummy, &dummy,
7172
7173 /* Modifier keys and pointer buttons, about which
7174 we don't care. */
7175 (unsigned int *) &dummy);
7176
7177 /* Now we have a position on the root; find the innermost window
7178 containing the pointer. */
7179 {
7180 Window win, child;
7181 int win_x, win_y;
7182 int parent_x = 0, parent_y = 0;
7183 int count;
7184
7185 win = root;
7186
7187 /* XTranslateCoordinates can get errors if the window
7188 structure is changing at the same time this function
7189 is running. So at least we must not crash from them. */
7190
7191 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
7192
7193 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7194 && FRAME_LIVE_P (last_mouse_frame))
7195 {
7196 /* If mouse was grabbed on a frame, give coords for that frame
7197 even if the mouse is now outside it. */
7198 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7199
7200 /* From-window, to-window. */
7201 root, FRAME_X_WINDOW (last_mouse_frame),
7202
7203 /* From-position, to-position. */
7204 root_x, root_y, &win_x, &win_y,
7205
7206 /* Child of win. */
7207 &child);
7208 f1 = last_mouse_frame;
7209 }
7210 else
7211 {
7212 while (1)
7213 {
7214 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
7215
7216 /* From-window, to-window. */
7217 root, win,
7218
7219 /* From-position, to-position. */
7220 root_x, root_y, &win_x, &win_y,
7221
7222 /* Child of win. */
7223 &child);
7224
7225 if (child == None || child == win)
7226 break;
7227
7228 win = child;
7229 parent_x = win_x;
7230 parent_y = win_y;
7231 }
7232
7233 /* Now we know that:
7234 win is the innermost window containing the pointer
7235 (XTC says it has no child containing the pointer),
7236 win_x and win_y are the pointer's position in it
7237 (XTC did this the last time through), and
7238 parent_x and parent_y are the pointer's position in win's parent.
7239 (They are what win_x and win_y were when win was child.
7240 If win is the root window, it has no parent, and
7241 parent_{x,y} are invalid, but that's okay, because we'll
7242 never use them in that case.) */
7243
7244 /* Is win one of our frames? */
7245 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
7246 }
7247
7248 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7249 f1 = 0;
7250
7251 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
7252
7253 /* If not, is it one of our scroll bars? */
7254 if (! f1)
7255 {
7256 struct scroll_bar *bar = x_window_to_scroll_bar (win);
7257
7258 if (bar)
7259 {
7260 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7261 win_x = parent_x;
7262 win_y = parent_y;
7263 }
7264 }
7265
7266 if (f1 == 0 && insist > 0)
7267 f1 = SELECTED_FRAME ();
7268
7269 if (f1)
7270 {
7271 /* Ok, we found a frame. Store all the values.
7272 last_mouse_glyph is a rectangle used to reduce the
7273 generation of mouse events. To not miss any motion
7274 events, we must divide the frame into rectangles of the
7275 size of the smallest character that could be displayed
7276 on it, i.e. into the same rectangles that matrices on
7277 the frame are divided into. */
7278
7279 #if OLD_REDISPLAY_CODE
7280 int ignore1, ignore2;
7281 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
7282 &last_mouse_glyph,
7283 FRAME_X_DISPLAY_INFO (f1)->grabbed
7284 || insist);
7285 #else
7286 {
7287 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7288 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7289 int x = win_x;
7290 int y = win_y;
7291
7292 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7293 round down even for negative values. */
7294 if (x < 0)
7295 x -= width - 1;
7296 if (y < 0)
7297 y -= height - 1;
7298
7299 last_mouse_glyph.width = width;
7300 last_mouse_glyph.height = height;
7301 last_mouse_glyph.x = (x + width - 1) / width * width;
7302 last_mouse_glyph.y = (y + height - 1) / height * height;
7303 }
7304 #endif
7305
7306 *bar_window = Qnil;
7307 *part = 0;
7308 *fp = f1;
7309 XSETINT (*x, win_x);
7310 XSETINT (*y, win_y);
7311 *time = last_mouse_movement_time;
7312 }
7313 }
7314 }
7315
7316 UNBLOCK_INPUT;
7317 }
7318
7319
7320 #ifdef USE_X_TOOLKIT
7321
7322 /* Atimer callback function for TIMER. Called every 0.1s to process
7323 Xt timeouts, if needed. We must avoid calling XtAppPending as
7324 much as possible because that function does an implicit XFlush
7325 that slows us down. */
7326
7327 static void
7328 x_process_timeouts (timer)
7329 struct atimer *timer;
7330 {
7331 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7332 {
7333 BLOCK_INPUT;
7334 while (XtAppPending (Xt_app_con) & XtIMTimer)
7335 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7336 UNBLOCK_INPUT;
7337 }
7338 }
7339
7340 #endif /* USE_X_TOOLKIT */
7341
7342 \f
7343 /* Scroll bar support. */
7344
7345 /* Given an X window ID, find the struct scroll_bar which manages it.
7346 This can be called in GC, so we have to make sure to strip off mark
7347 bits. */
7348
7349 static struct scroll_bar *
7350 x_window_to_scroll_bar (window_id)
7351 Window window_id;
7352 {
7353 Lisp_Object tail;
7354
7355 for (tail = Vframe_list;
7356 XGCTYPE (tail) == Lisp_Cons;
7357 tail = XCDR (tail))
7358 {
7359 Lisp_Object frame, bar, condemned;
7360
7361 frame = XCAR (tail);
7362 /* All elements of Vframe_list should be frames. */
7363 if (! GC_FRAMEP (frame))
7364 abort ();
7365
7366 /* Scan this frame's scroll bar list for a scroll bar with the
7367 right window ID. */
7368 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7369 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7370 /* This trick allows us to search both the ordinary and
7371 condemned scroll bar lists with one loop. */
7372 ! GC_NILP (bar) || (bar = condemned,
7373 condemned = Qnil,
7374 ! GC_NILP (bar));
7375 bar = XSCROLL_BAR (bar)->next)
7376 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7377 return XSCROLL_BAR (bar);
7378 }
7379
7380 return 0;
7381 }
7382
7383
7384 \f
7385 /************************************************************************
7386 Toolkit scroll bars
7387 ************************************************************************/
7388
7389 #if USE_TOOLKIT_SCROLL_BARS
7390
7391 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7392 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7393 static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7394 struct scroll_bar *));
7395 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7396 int, int, int));
7397
7398
7399 /* Id of action hook installed for scroll bars. */
7400
7401 static XtActionHookId action_hook_id;
7402
7403 /* Lisp window being scrolled. Set when starting to interact with
7404 a toolkit scroll bar, reset to nil when ending the interaction. */
7405
7406 static Lisp_Object window_being_scrolled;
7407
7408 /* Last scroll bar part sent in xm_scroll_callback. */
7409
7410 static int last_scroll_bar_part;
7411
7412 /* Whether this is an Xaw with arrow-scrollbars. This should imply
7413 that movements of 1/20 of the screen size are mapped to up/down. */
7414
7415 static Boolean xaw3d_arrow_scroll;
7416
7417 /* Whether the drag scrolling maintains the mouse at the top of the
7418 thumb. If not, resizing the thumb needs to be done more carefully
7419 to avoid jerkyness. */
7420
7421 static Boolean xaw3d_pick_top;
7422
7423
7424 /* Action hook installed via XtAppAddActionHook when toolkit scroll
7425 bars are used.. The hook is responsible for detecting when
7426 the user ends an interaction with the scroll bar, and generates
7427 a `end-scroll' scroll_bar_click' event if so. */
7428
7429 static void
7430 xt_action_hook (widget, client_data, action_name, event, params,
7431 num_params)
7432 Widget widget;
7433 XtPointer client_data;
7434 String action_name;
7435 XEvent *event;
7436 String *params;
7437 Cardinal *num_params;
7438 {
7439 int scroll_bar_p;
7440 char *end_action;
7441
7442 #ifdef USE_MOTIF
7443 scroll_bar_p = XmIsScrollBar (widget);
7444 end_action = "Release";
7445 #else /* !USE_MOTIF i.e. use Xaw */
7446 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7447 end_action = "EndScroll";
7448 #endif /* USE_MOTIF */
7449
7450 if (scroll_bar_p
7451 && strcmp (action_name, end_action) == 0
7452 && WINDOWP (window_being_scrolled))
7453 {
7454 struct window *w;
7455
7456 x_send_scroll_bar_event (window_being_scrolled,
7457 scroll_bar_end_scroll, 0, 0);
7458 w = XWINDOW (window_being_scrolled);
7459 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7460 window_being_scrolled = Qnil;
7461 last_scroll_bar_part = -1;
7462
7463 /* Xt timeouts no longer needed. */
7464 toolkit_scroll_bar_interaction = 0;
7465 }
7466 }
7467
7468
7469 /* Send a client message with message type Xatom_Scrollbar for a
7470 scroll action to the frame of WINDOW. PART is a value identifying
7471 the part of the scroll bar that was clicked on. PORTION is the
7472 amount to scroll of a whole of WHOLE. */
7473
7474 static void
7475 x_send_scroll_bar_event (window, part, portion, whole)
7476 Lisp_Object window;
7477 int part, portion, whole;
7478 {
7479 XEvent event;
7480 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7481 struct frame *f = XFRAME (XWINDOW (window)->frame);
7482
7483 /* Construct a ClientMessage event to send to the frame. */
7484 ev->type = ClientMessage;
7485 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7486 ev->display = FRAME_X_DISPLAY (f);
7487 ev->window = FRAME_X_WINDOW (f);
7488 ev->format = 32;
7489 ev->data.l[0] = (long) XFASTINT (window);
7490 ev->data.l[1] = (long) part;
7491 ev->data.l[2] = (long) 0;
7492 ev->data.l[3] = (long) portion;
7493 ev->data.l[4] = (long) whole;
7494
7495 /* Make Xt timeouts work while the scroll bar is active. */
7496 toolkit_scroll_bar_interaction = 1;
7497
7498 /* Setting the event mask to zero means that the message will
7499 be sent to the client that created the window, and if that
7500 window no longer exists, no event will be sent. */
7501 BLOCK_INPUT;
7502 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7503 UNBLOCK_INPUT;
7504 }
7505
7506
7507 /* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7508 in *IEVENT. */
7509
7510 static void
7511 x_scroll_bar_to_input_event (event, ievent)
7512 XEvent *event;
7513 struct input_event *ievent;
7514 {
7515 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7516 Lisp_Object window;
7517 struct frame *f;
7518
7519 XSETFASTINT (window, ev->data.l[0]);
7520 f = XFRAME (XWINDOW (window)->frame);
7521
7522 ievent->kind = scroll_bar_click;
7523 ievent->frame_or_window = window;
7524 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7525 ievent->part = ev->data.l[1];
7526 ievent->code = ev->data.l[2];
7527 ievent->x = make_number ((int) ev->data.l[3]);
7528 ievent->y = make_number ((int) ev->data.l[4]);
7529 ievent->modifiers = 0;
7530 }
7531
7532
7533 #ifdef USE_MOTIF
7534
7535 /* Minimum and maximum values used for Motif scroll bars. */
7536
7537 #define XM_SB_MIN 1
7538 #define XM_SB_MAX 10000000
7539 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7540
7541
7542 /* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7543 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7544 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7545
7546 static void
7547 xm_scroll_callback (widget, client_data, call_data)
7548 Widget widget;
7549 XtPointer client_data, call_data;
7550 {
7551 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7552 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7553 double percent;
7554 int part = -1, whole = 0, portion = 0;
7555
7556 switch (cs->reason)
7557 {
7558 case XmCR_DECREMENT:
7559 bar->dragging = Qnil;
7560 part = scroll_bar_up_arrow;
7561 break;
7562
7563 case XmCR_INCREMENT:
7564 bar->dragging = Qnil;
7565 part = scroll_bar_down_arrow;
7566 break;
7567
7568 case XmCR_PAGE_DECREMENT:
7569 bar->dragging = Qnil;
7570 part = scroll_bar_above_handle;
7571 break;
7572
7573 case XmCR_PAGE_INCREMENT:
7574 bar->dragging = Qnil;
7575 part = scroll_bar_below_handle;
7576 break;
7577
7578 case XmCR_TO_TOP:
7579 bar->dragging = Qnil;
7580 part = scroll_bar_to_top;
7581 break;
7582
7583 case XmCR_TO_BOTTOM:
7584 bar->dragging = Qnil;
7585 part = scroll_bar_to_bottom;
7586 break;
7587
7588 case XmCR_DRAG:
7589 {
7590 int slider_size;
7591 int dragging_down_p = (INTEGERP (bar->dragging)
7592 && XINT (bar->dragging) <= cs->value);
7593
7594 /* Get the slider size. */
7595 BLOCK_INPUT;
7596 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7597 UNBLOCK_INPUT;
7598
7599 /* At the max position of the scroll bar, do a line-wise
7600 movement. Without doing anything, the LessTif scroll bar
7601 calls us with the same cs->value again and again. If we
7602 want to make sure that we can reach the end of the buffer,
7603 we have to do something.
7604
7605 Implementation note: setting bar->dragging always to
7606 cs->value gives a smoother movement at the max position.
7607 Setting it to nil when doing line-wise movement gives
7608 a better slider behavior. */
7609
7610 if (cs->value + slider_size == XM_SB_MAX
7611 || (dragging_down_p
7612 && last_scroll_bar_part == scroll_bar_down_arrow))
7613 {
7614 part = scroll_bar_down_arrow;
7615 bar->dragging = Qnil;
7616 }
7617 else
7618 {
7619 whole = XM_SB_RANGE;
7620 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7621 part = scroll_bar_handle;
7622 bar->dragging = make_number (cs->value);
7623 }
7624 }
7625 break;
7626
7627 case XmCR_VALUE_CHANGED:
7628 break;
7629 };
7630
7631 if (part >= 0)
7632 {
7633 window_being_scrolled = bar->window;
7634 last_scroll_bar_part = part;
7635 x_send_scroll_bar_event (bar->window, part, portion, whole);
7636 }
7637 }
7638
7639
7640 #else /* !USE_MOTIF, i.e. Xaw. */
7641
7642
7643 /* Xaw scroll bar callback. Invoked when the thumb is dragged.
7644 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7645 scroll bar struct. CALL_DATA is a pointer to a float saying where
7646 the thumb is. */
7647
7648 static void
7649 xaw_jump_callback (widget, client_data, call_data)
7650 Widget widget;
7651 XtPointer client_data, call_data;
7652 {
7653 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7654 float top = *(float *) call_data;
7655 float shown;
7656 int whole, portion, height;
7657 int part;
7658
7659 /* Get the size of the thumb, a value between 0 and 1. */
7660 BLOCK_INPUT;
7661 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
7662 UNBLOCK_INPUT;
7663
7664 whole = 10000000;
7665 portion = shown < 1 ? top * whole : 0;
7666
7667 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7668 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7669 the bottom, so we force the scrolling whenever we see that we're
7670 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7671 we try to ensure that we always stay two pixels away from the
7672 bottom). */
7673 part = scroll_bar_down_arrow;
7674 else
7675 part = scroll_bar_handle;
7676
7677 window_being_scrolled = bar->window;
7678 bar->dragging = make_number (portion);
7679 last_scroll_bar_part = part;
7680 x_send_scroll_bar_event (bar->window, part, portion, whole);
7681 }
7682
7683
7684 /* Xaw scroll bar callback. Invoked for incremental scrolling.,
7685 i.e. line or page up or down. WIDGET is the Xaw scroll bar
7686 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7687 the scroll bar. CALL_DATA is an integer specifying the action that
7688 has taken place. It's magnitude is in the range 0..height of the
7689 scroll bar. Negative values mean scroll towards buffer start.
7690 Values < height of scroll bar mean line-wise movement. */
7691
7692 static void
7693 xaw_scroll_callback (widget, client_data, call_data)
7694 Widget widget;
7695 XtPointer client_data, call_data;
7696 {
7697 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7698 int position = (int) call_data;
7699 Dimension height;
7700 int part;
7701
7702 /* Get the height of the scroll bar. */
7703 BLOCK_INPUT;
7704 XtVaGetValues (widget, XtNheight, &height, NULL);
7705 UNBLOCK_INPUT;
7706
7707 if (abs (position) >= height)
7708 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7709
7710 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7711 it maps line-movement to call_data = max(5, height/20). */
7712 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7713 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
7714 else
7715 part = scroll_bar_move_ratio;
7716
7717 window_being_scrolled = bar->window;
7718 bar->dragging = Qnil;
7719 last_scroll_bar_part = part;
7720 x_send_scroll_bar_event (bar->window, part, position, height);
7721 }
7722
7723
7724 #endif /* not USE_MOTIF */
7725
7726
7727 /* Create the widget for scroll bar BAR on frame F. Record the widget
7728 and X window of the scroll bar in BAR. */
7729
7730 static void
7731 x_create_toolkit_scroll_bar (f, bar)
7732 struct frame *f;
7733 struct scroll_bar *bar;
7734 {
7735 Window xwindow;
7736 Widget widget;
7737 Arg av[20];
7738 int ac = 0;
7739 char *scroll_bar_name = "verticalScrollBar";
7740 unsigned long pixel;
7741
7742 BLOCK_INPUT;
7743
7744 #ifdef USE_MOTIF
7745 /* LessTif 0.85, problems:
7746
7747 1. When the mouse if over the scroll bar, the scroll bar will
7748 get keyboard events. I didn't find a way to turn this off.
7749
7750 2. Do we have to explicitly set the cursor to get an arrow
7751 cursor (see below)? */
7752
7753 /* Set resources. Create the widget. */
7754 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7755 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7756 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7757 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7758 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7759 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7760 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7761
7762 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7763 if (pixel != -1)
7764 {
7765 XtSetArg (av[ac], XmNforeground, pixel);
7766 ++ac;
7767 }
7768
7769 pixel = f->output_data.x->scroll_bar_background_pixel;
7770 if (pixel != -1)
7771 {
7772 XtSetArg (av[ac], XmNbackground, pixel);
7773 ++ac;
7774 }
7775
7776 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7777 scroll_bar_name, av, ac);
7778
7779 /* Add one callback for everything that can happen. */
7780 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7781 (XtPointer) bar);
7782 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7783 (XtPointer) bar);
7784 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7785 (XtPointer) bar);
7786 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7787 (XtPointer) bar);
7788 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7789 (XtPointer) bar);
7790 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7791 (XtPointer) bar);
7792 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7793 (XtPointer) bar);
7794
7795 /* Realize the widget. Only after that is the X window created. */
7796 XtRealizeWidget (widget);
7797
7798 /* Set the cursor to an arrow. I didn't find a resource to do that.
7799 And I'm wondering why it hasn't an arrow cursor by default. */
7800 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7801 f->output_data.x->nontext_cursor);
7802
7803 #else /* !USE_MOTIF i.e. use Xaw */
7804
7805 /* Set resources. Create the widget. The background of the
7806 Xaw3d scroll bar widget is a little bit light for my taste.
7807 We don't alter it here to let users change it according
7808 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7809 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7810 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7811 /* For smoother scrolling with Xaw3d -sm */
7812 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7813 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
7814
7815 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7816 if (pixel != -1)
7817 {
7818 XtSetArg (av[ac], XtNforeground, pixel);
7819 ++ac;
7820 }
7821
7822 pixel = f->output_data.x->scroll_bar_background_pixel;
7823 if (pixel != -1)
7824 {
7825 XtSetArg (av[ac], XtNbackground, pixel);
7826 ++ac;
7827 }
7828
7829 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7830 f->output_data.x->edit_widget, av, ac);
7831
7832 {
7833 char *initial = "";
7834 char *val = initial;
7835 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7836 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7837 if (val == initial)
7838 { /* ARROW_SCROLL */
7839 xaw3d_arrow_scroll = True;
7840 /* Isn't that just a personal preference ? -sm */
7841 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7842 }
7843 }
7844
7845 /* Define callbacks. */
7846 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7847 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
7848 (XtPointer) bar);
7849
7850 /* Realize the widget. Only after that is the X window created. */
7851 XtRealizeWidget (widget);
7852
7853 #endif /* !USE_MOTIF */
7854
7855 /* Install an action hook that let's us detect when the user
7856 finishes interacting with a scroll bar. */
7857 if (action_hook_id == 0)
7858 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7859
7860 /* Remember X window and widget in the scroll bar vector. */
7861 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7862 xwindow = XtWindow (widget);
7863 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7864
7865 UNBLOCK_INPUT;
7866 }
7867
7868
7869 /* Set the thumb size and position of scroll bar BAR. We are currently
7870 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7871
7872 static void
7873 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7874 struct scroll_bar *bar;
7875 int portion, position, whole;
7876 {
7877 float top, shown;
7878 Widget widget = SCROLL_BAR_X_WIDGET (bar);
7879
7880 if (whole == 0)
7881 top = 0, shown = 1;
7882 else
7883 {
7884 top = (float) position / whole;
7885 shown = (float) portion / whole;
7886 }
7887
7888 BLOCK_INPUT;
7889
7890 #ifdef USE_MOTIF
7891 {
7892 int size, value;
7893 Boolean arrow1_selected, arrow2_selected;
7894 unsigned char flags;
7895 XmScrollBarWidget sb;
7896
7897 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
7898 is the scroll bar's maximum and MIN is the scroll bar's minimum
7899 value. */
7900 size = shown * XM_SB_RANGE;
7901 size = min (size, XM_SB_RANGE);
7902 size = max (size, 1);
7903
7904 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7905 value = top * XM_SB_RANGE;
7906 value = min (value, XM_SB_MAX - size);
7907 value = max (value, XM_SB_MIN);
7908
7909 /* LessTif: Calling XmScrollBarSetValues after an increment or
7910 decrement turns off auto-repeat LessTif-internally. This can
7911 be seen in ScrollBar.c which resets Arrow1Selected and
7912 Arrow2Selected. It also sets internal flags so that LessTif
7913 believes the mouse is in the slider. We either have to change
7914 our code, or work around that by accessing private data. */
7915
7916 sb = (XmScrollBarWidget) widget;
7917 arrow1_selected = sb->scrollBar.arrow1_selected;
7918 arrow2_selected = sb->scrollBar.arrow2_selected;
7919 flags = sb->scrollBar.flags;
7920
7921 if (NILP (bar->dragging))
7922 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7923 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7924 /* This has the negative side effect that the slider value is
7925 not what it would be if we scrolled here using line-wise or
7926 page-wise movement. */
7927 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7928 else
7929 {
7930 /* If currently dragging, only update the slider size.
7931 This reduces flicker effects. */
7932 int old_value, old_size, increment, page_increment;
7933
7934 XmScrollBarGetValues (widget, &old_value, &old_size,
7935 &increment, &page_increment);
7936 XmScrollBarSetValues (widget, old_value,
7937 min (size, XM_SB_RANGE - old_value),
7938 0, 0, False);
7939 }
7940
7941 sb->scrollBar.arrow1_selected = arrow1_selected;
7942 sb->scrollBar.arrow2_selected = arrow2_selected;
7943 sb->scrollBar.flags = flags;
7944 }
7945 #else /* !USE_MOTIF i.e. use Xaw */
7946 {
7947 float old_top, old_shown;
7948 Dimension height;
7949 XtVaGetValues (widget,
7950 XtNtopOfThumb, &old_top,
7951 XtNshown, &old_shown,
7952 XtNheight, &height,
7953 NULL);
7954
7955 /* Massage the top+shown values. */
7956 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7957 top = max (0, min (1, top));
7958 else
7959 top = old_top;
7960 /* Keep two pixels available for moving the thumb down. */
7961 shown = max (0, min (1 - top - (2.0 / height), shown));
7962
7963 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7964 check that your system's configuration file contains a define
7965 for `NARROWPROTO'. See s/freebsd.h for an example. */
7966 if (top != old_top || shown != old_shown)
7967 {
7968 if (NILP (bar->dragging))
7969 XawScrollbarSetThumb (widget, top, shown);
7970 else
7971 {
7972 #ifdef HAVE_XAW3D
7973 ScrollbarWidget sb = (ScrollbarWidget) widget;
7974 int scroll_mode = 0;
7975
7976 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7977 if (xaw3d_arrow_scroll)
7978 {
7979 /* Xaw3d stupidly ignores resize requests while dragging
7980 so we have to make it believe it's not in dragging mode. */
7981 scroll_mode = sb->scrollbar.scroll_mode;
7982 if (scroll_mode == 2)
7983 sb->scrollbar.scroll_mode = 0;
7984 }
7985 #endif
7986 /* Try to make the scrolling a tad smoother. */
7987 if (!xaw3d_pick_top)
7988 shown = min (shown, old_shown);
7989
7990 XawScrollbarSetThumb (widget, top, shown);
7991
7992 #ifdef HAVE_XAW3D
7993 if (xaw3d_arrow_scroll && scroll_mode == 2)
7994 sb->scrollbar.scroll_mode = scroll_mode;
7995 #endif
7996 }
7997 }
7998 }
7999 #endif /* !USE_MOTIF */
8000
8001 UNBLOCK_INPUT;
8002 }
8003
8004 #endif /* USE_TOOLKIT_SCROLL_BARS */
8005
8006
8007 \f
8008 /************************************************************************
8009 Scroll bars, general
8010 ************************************************************************/
8011
8012 /* Create a scroll bar and return the scroll bar vector for it. W is
8013 the Emacs window on which to create the scroll bar. TOP, LEFT,
8014 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8015 scroll bar. */
8016
8017 static struct scroll_bar *
8018 x_scroll_bar_create (w, top, left, width, height)
8019 struct window *w;
8020 int top, left, width, height;
8021 {
8022 struct frame *f = XFRAME (w->frame);
8023 struct scroll_bar *bar
8024 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
8025
8026 BLOCK_INPUT;
8027
8028 #if USE_TOOLKIT_SCROLL_BARS
8029 x_create_toolkit_scroll_bar (f, bar);
8030 #else /* not USE_TOOLKIT_SCROLL_BARS */
8031 {
8032 XSetWindowAttributes a;
8033 unsigned long mask;
8034 Window window;
8035
8036 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8037 if (a.background_pixel == -1)
8038 a.background_pixel = f->output_data.x->background_pixel;
8039
8040 a.event_mask = (ButtonPressMask | ButtonReleaseMask
8041 | ButtonMotionMask | PointerMotionHintMask
8042 | ExposureMask);
8043 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
8044
8045 mask = (CWBackPixel | CWEventMask | CWCursor);
8046
8047 /* Clear the area of W that will serve as a scroll bar. This is
8048 for the case that a window has been split horizontally. In
8049 this case, no clear_frame is generated to reduce flickering. */
8050 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8051 left, top, width,
8052 window_box_height (w), False);
8053
8054 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8055 /* Position and size of scroll bar. */
8056 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8057 top,
8058 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8059 height,
8060 /* Border width, depth, class, and visual. */
8061 0,
8062 CopyFromParent,
8063 CopyFromParent,
8064 CopyFromParent,
8065 /* Attributes. */
8066 mask, &a);
8067 SET_SCROLL_BAR_X_WINDOW (bar, window);
8068 }
8069 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8070
8071 XSETWINDOW (bar->window, w);
8072 XSETINT (bar->top, top);
8073 XSETINT (bar->left, left);
8074 XSETINT (bar->width, width);
8075 XSETINT (bar->height, height);
8076 XSETINT (bar->start, 0);
8077 XSETINT (bar->end, 0);
8078 bar->dragging = Qnil;
8079
8080 /* Add bar to its frame's list of scroll bars. */
8081 bar->next = FRAME_SCROLL_BARS (f);
8082 bar->prev = Qnil;
8083 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8084 if (!NILP (bar->next))
8085 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8086
8087 /* Map the window/widget. */
8088 #if USE_TOOLKIT_SCROLL_BARS
8089 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8090 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8091 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8092 top,
8093 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8094 height, 0);
8095 #else /* not USE_TOOLKIT_SCROLL_BARS */
8096 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8097 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8098
8099 UNBLOCK_INPUT;
8100 return bar;
8101 }
8102
8103
8104 /* Draw BAR's handle in the proper position.
8105
8106 If the handle is already drawn from START to END, don't bother
8107 redrawing it, unless REBUILD is non-zero; in that case, always
8108 redraw it. (REBUILD is handy for drawing the handle after expose
8109 events.)
8110
8111 Normally, we want to constrain the start and end of the handle to
8112 fit inside its rectangle, but if the user is dragging the scroll
8113 bar handle, we want to let them drag it down all the way, so that
8114 the bar's top is as far down as it goes; otherwise, there's no way
8115 to move to the very end of the buffer. */
8116
8117 #ifndef USE_TOOLKIT_SCROLL_BARS
8118
8119 static void
8120 x_scroll_bar_set_handle (bar, start, end, rebuild)
8121 struct scroll_bar *bar;
8122 int start, end;
8123 int rebuild;
8124 {
8125 int dragging = ! NILP (bar->dragging);
8126 Window w = SCROLL_BAR_X_WINDOW (bar);
8127 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8128 GC gc = f->output_data.x->normal_gc;
8129
8130 /* If the display is already accurate, do nothing. */
8131 if (! rebuild
8132 && start == XINT (bar->start)
8133 && end == XINT (bar->end))
8134 return;
8135
8136 BLOCK_INPUT;
8137
8138 {
8139 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8140 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8141 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8142
8143 /* Make sure the values are reasonable, and try to preserve
8144 the distance between start and end. */
8145 {
8146 int length = end - start;
8147
8148 if (start < 0)
8149 start = 0;
8150 else if (start > top_range)
8151 start = top_range;
8152 end = start + length;
8153
8154 if (end < start)
8155 end = start;
8156 else if (end > top_range && ! dragging)
8157 end = top_range;
8158 }
8159
8160 /* Store the adjusted setting in the scroll bar. */
8161 XSETINT (bar->start, start);
8162 XSETINT (bar->end, end);
8163
8164 /* Clip the end position, just for display. */
8165 if (end > top_range)
8166 end = top_range;
8167
8168 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
8169 below top positions, to make sure the handle is always at least
8170 that many pixels tall. */
8171 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
8172
8173 /* Draw the empty space above the handle. Note that we can't clear
8174 zero-height areas; that means "clear to end of window." */
8175 if (0 < start)
8176 XClearArea (FRAME_X_DISPLAY (f), w,
8177
8178 /* x, y, width, height, and exposures. */
8179 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8180 VERTICAL_SCROLL_BAR_TOP_BORDER,
8181 inside_width, start,
8182 False);
8183
8184 /* Change to proper foreground color if one is specified. */
8185 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8186 XSetForeground (FRAME_X_DISPLAY (f), gc,
8187 f->output_data.x->scroll_bar_foreground_pixel);
8188
8189 /* Draw the handle itself. */
8190 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
8191
8192 /* x, y, width, height */
8193 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8194 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
8195 inside_width, end - start);
8196
8197 /* Restore the foreground color of the GC if we changed it above. */
8198 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8199 XSetForeground (FRAME_X_DISPLAY (f), gc,
8200 f->output_data.x->foreground_pixel);
8201
8202 /* Draw the empty space below the handle. Note that we can't
8203 clear zero-height areas; that means "clear to end of window." */
8204 if (end < inside_height)
8205 XClearArea (FRAME_X_DISPLAY (f), w,
8206
8207 /* x, y, width, height, and exposures. */
8208 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8209 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8210 inside_width, inside_height - end,
8211 False);
8212
8213 }
8214
8215 UNBLOCK_INPUT;
8216 }
8217
8218 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8219
8220 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8221 nil. */
8222
8223 static void
8224 x_scroll_bar_remove (bar)
8225 struct scroll_bar *bar;
8226 {
8227 BLOCK_INPUT;
8228
8229 #if USE_TOOLKIT_SCROLL_BARS
8230 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8231 #else /* not USE_TOOLKIT_SCROLL_BARS */
8232 {
8233 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8234 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8235 }
8236 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8237
8238 /* Disassociate this scroll bar from its window. */
8239 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
8240
8241 UNBLOCK_INPUT;
8242 }
8243
8244
8245 /* Set the handle of the vertical scroll bar for WINDOW to indicate
8246 that we are displaying PORTION characters out of a total of WHOLE
8247 characters, starting at POSITION. If WINDOW has no scroll bar,
8248 create one. */
8249
8250 static void
8251 XTset_vertical_scroll_bar (w, portion, whole, position)
8252 struct window *w;
8253 int portion, whole, position;
8254 {
8255 struct frame *f = XFRAME (w->frame);
8256 struct scroll_bar *bar;
8257 int top, height, left, sb_left, width, sb_width;
8258 int window_x, window_y, window_width, window_height;
8259
8260 /* Get window dimensions. */
8261 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8262 top = window_y;
8263 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8264 height = window_height;
8265
8266 /* Compute the left edge of the scroll bar area. */
8267 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8268 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8269 else
8270 left = XFASTINT (w->left);
8271 left *= CANON_X_UNIT (f);
8272 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8273
8274 /* Compute the width of the scroll bar which might be less than
8275 the width of the area reserved for the scroll bar. */
8276 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8277 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8278 else
8279 sb_width = width;
8280
8281 /* Compute the left edge of the scroll bar. */
8282 #ifdef USE_TOOLKIT_SCROLL_BARS
8283 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8284 sb_left = left + width - sb_width - (width - sb_width) / 2;
8285 else
8286 sb_left = left + (width - sb_width) / 2;
8287 #else
8288 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8289 sb_left = left + width - sb_width;
8290 else
8291 sb_left = left;
8292 #endif
8293
8294 /* Does the scroll bar exist yet? */
8295 if (NILP (w->vertical_scroll_bar))
8296 {
8297 BLOCK_INPUT;
8298 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8299 left, top, width, height, False);
8300 UNBLOCK_INPUT;
8301 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8302 }
8303 else
8304 {
8305 /* It may just need to be moved and resized. */
8306 unsigned int mask = 0;
8307
8308 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8309
8310 BLOCK_INPUT;
8311
8312 if (sb_left != XINT (bar->left))
8313 mask |= CWX;
8314 if (top != XINT (bar->top))
8315 mask |= CWY;
8316 if (sb_width != XINT (bar->width))
8317 mask |= CWWidth;
8318 if (height != XINT (bar->height))
8319 mask |= CWHeight;
8320
8321 #ifdef USE_TOOLKIT_SCROLL_BARS
8322
8323 /* Since toolkit scroll bars are smaller than the space reserved
8324 for them on the frame, we have to clear "under" them. */
8325 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8326 left, top, width, height, False);
8327
8328 /* Move/size the scroll bar widget. */
8329 if (mask)
8330 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8331 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8332 top,
8333 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8334 height, 0);
8335
8336 #else /* not USE_TOOLKIT_SCROLL_BARS */
8337
8338 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8339 {
8340 /* Clear areas not covered by the scroll bar. This makes sure a
8341 previous mode line display is cleared after C-x 2 C-x 1, for
8342 example. Non-toolkit scroll bars are as wide as the area
8343 reserved for scroll bars - trim at both sides. */
8344 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8345 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8346 height, False);
8347 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8348 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8349 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8350 height, False);
8351 }
8352
8353 /* Move/size the scroll bar window. */
8354 if (mask)
8355 {
8356 XWindowChanges wc;
8357
8358 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8359 wc.y = top;
8360 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8361 wc.height = height;
8362 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8363 mask, &wc);
8364 }
8365
8366 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8367
8368 /* Remember new settings. */
8369 XSETINT (bar->left, sb_left);
8370 XSETINT (bar->top, top);
8371 XSETINT (bar->width, sb_width);
8372 XSETINT (bar->height, height);
8373
8374 UNBLOCK_INPUT;
8375 }
8376
8377 #if USE_TOOLKIT_SCROLL_BARS
8378 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8379 #else /* not USE_TOOLKIT_SCROLL_BARS */
8380 /* Set the scroll bar's current state, unless we're currently being
8381 dragged. */
8382 if (NILP (bar->dragging))
8383 {
8384 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
8385
8386 if (whole == 0)
8387 x_scroll_bar_set_handle (bar, 0, top_range, 0);
8388 else
8389 {
8390 int start = ((double) position * top_range) / whole;
8391 int end = ((double) (position + portion) * top_range) / whole;
8392 x_scroll_bar_set_handle (bar, start, end, 0);
8393 }
8394 }
8395 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8396
8397 XSETVECTOR (w->vertical_scroll_bar, bar);
8398 }
8399
8400
8401 /* The following three hooks are used when we're doing a thorough
8402 redisplay of the frame. We don't explicitly know which scroll bars
8403 are going to be deleted, because keeping track of when windows go
8404 away is a real pain - "Can you say set-window-configuration, boys
8405 and girls?" Instead, we just assert at the beginning of redisplay
8406 that *all* scroll bars are to be removed, and then save a scroll bar
8407 from the fiery pit when we actually redisplay its window. */
8408
8409 /* Arrange for all scroll bars on FRAME to be removed at the next call
8410 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8411 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8412
8413 static void
8414 XTcondemn_scroll_bars (frame)
8415 FRAME_PTR frame;
8416 {
8417 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8418 while (! NILP (FRAME_SCROLL_BARS (frame)))
8419 {
8420 Lisp_Object bar;
8421 bar = FRAME_SCROLL_BARS (frame);
8422 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8423 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8424 XSCROLL_BAR (bar)->prev = Qnil;
8425 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8426 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8427 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8428 }
8429 }
8430
8431 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8432 Note that WINDOW isn't necessarily condemned at all. */
8433 static void
8434 XTredeem_scroll_bar (window)
8435 struct window *window;
8436 {
8437 struct scroll_bar *bar;
8438
8439 /* We can't redeem this window's scroll bar if it doesn't have one. */
8440 if (NILP (window->vertical_scroll_bar))
8441 abort ();
8442
8443 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8444
8445 /* Unlink it from the condemned list. */
8446 {
8447 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8448
8449 if (NILP (bar->prev))
8450 {
8451 /* If the prev pointer is nil, it must be the first in one of
8452 the lists. */
8453 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8454 /* It's not condemned. Everything's fine. */
8455 return;
8456 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8457 window->vertical_scroll_bar))
8458 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8459 else
8460 /* If its prev pointer is nil, it must be at the front of
8461 one or the other! */
8462 abort ();
8463 }
8464 else
8465 XSCROLL_BAR (bar->prev)->next = bar->next;
8466
8467 if (! NILP (bar->next))
8468 XSCROLL_BAR (bar->next)->prev = bar->prev;
8469
8470 bar->next = FRAME_SCROLL_BARS (f);
8471 bar->prev = Qnil;
8472 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8473 if (! NILP (bar->next))
8474 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8475 }
8476 }
8477
8478 /* Remove all scroll bars on FRAME that haven't been saved since the
8479 last call to `*condemn_scroll_bars_hook'. */
8480
8481 static void
8482 XTjudge_scroll_bars (f)
8483 FRAME_PTR f;
8484 {
8485 Lisp_Object bar, next;
8486
8487 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8488
8489 /* Clear out the condemned list now so we won't try to process any
8490 more events on the hapless scroll bars. */
8491 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8492
8493 for (; ! NILP (bar); bar = next)
8494 {
8495 struct scroll_bar *b = XSCROLL_BAR (bar);
8496
8497 x_scroll_bar_remove (b);
8498
8499 next = b->next;
8500 b->next = b->prev = Qnil;
8501 }
8502
8503 /* Now there should be no references to the condemned scroll bars,
8504 and they should get garbage-collected. */
8505 }
8506
8507
8508 /* Handle an Expose or GraphicsExpose event on a scroll bar. This
8509 is a no-op when using toolkit scroll bars.
8510
8511 This may be called from a signal handler, so we have to ignore GC
8512 mark bits. */
8513
8514 static void
8515 x_scroll_bar_expose (bar, event)
8516 struct scroll_bar *bar;
8517 XEvent *event;
8518 {
8519 #ifndef USE_TOOLKIT_SCROLL_BARS
8520
8521 Window w = SCROLL_BAR_X_WINDOW (bar);
8522 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8523 GC gc = f->output_data.x->normal_gc;
8524 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8525
8526 BLOCK_INPUT;
8527
8528 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
8529
8530 /* Draw a one-pixel border just inside the edges of the scroll bar. */
8531 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
8532
8533 /* x, y, width, height */
8534 0, 0,
8535 XINT (bar->width) - 1 - width_trim - width_trim,
8536 XINT (bar->height) - 1);
8537
8538 UNBLOCK_INPUT;
8539
8540 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8541 }
8542
8543 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8544 is set to something other than no_event, it is enqueued.
8545
8546 This may be called from a signal handler, so we have to ignore GC
8547 mark bits. */
8548
8549 #ifndef USE_TOOLKIT_SCROLL_BARS
8550
8551 static void
8552 x_scroll_bar_handle_click (bar, event, emacs_event)
8553 struct scroll_bar *bar;
8554 XEvent *event;
8555 struct input_event *emacs_event;
8556 {
8557 if (! GC_WINDOWP (bar->window))
8558 abort ();
8559
8560 emacs_event->kind = scroll_bar_click;
8561 emacs_event->code = event->xbutton.button - Button1;
8562 emacs_event->modifiers
8563 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8564 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8565 event->xbutton.state)
8566 | (event->type == ButtonRelease
8567 ? up_modifier
8568 : down_modifier));
8569 emacs_event->frame_or_window = bar->window;
8570 emacs_event->timestamp = event->xbutton.time;
8571 {
8572 #if 0
8573 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8574 int internal_height
8575 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8576 #endif
8577 int top_range
8578 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8579 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
8580
8581 if (y < 0) y = 0;
8582 if (y > top_range) y = top_range;
8583
8584 if (y < XINT (bar->start))
8585 emacs_event->part = scroll_bar_above_handle;
8586 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8587 emacs_event->part = scroll_bar_handle;
8588 else
8589 emacs_event->part = scroll_bar_below_handle;
8590
8591 /* Just because the user has clicked on the handle doesn't mean
8592 they want to drag it. Lisp code needs to be able to decide
8593 whether or not we're dragging. */
8594 #if 0
8595 /* If the user has just clicked on the handle, record where they're
8596 holding it. */
8597 if (event->type == ButtonPress
8598 && emacs_event->part == scroll_bar_handle)
8599 XSETINT (bar->dragging, y - XINT (bar->start));
8600 #endif
8601
8602 /* If the user has released the handle, set it to its final position. */
8603 if (event->type == ButtonRelease
8604 && ! NILP (bar->dragging))
8605 {
8606 int new_start = y - XINT (bar->dragging);
8607 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8608
8609 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8610 bar->dragging = Qnil;
8611 }
8612
8613 /* Same deal here as the other #if 0. */
8614 #if 0
8615 /* Clicks on the handle are always reported as occurring at the top of
8616 the handle. */
8617 if (emacs_event->part == scroll_bar_handle)
8618 emacs_event->x = bar->start;
8619 else
8620 XSETINT (emacs_event->x, y);
8621 #else
8622 XSETINT (emacs_event->x, y);
8623 #endif
8624
8625 XSETINT (emacs_event->y, top_range);
8626 }
8627 }
8628
8629 /* Handle some mouse motion while someone is dragging the scroll bar.
8630
8631 This may be called from a signal handler, so we have to ignore GC
8632 mark bits. */
8633
8634 static void
8635 x_scroll_bar_note_movement (bar, event)
8636 struct scroll_bar *bar;
8637 XEvent *event;
8638 {
8639 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8640
8641 last_mouse_movement_time = event->xmotion.time;
8642
8643 f->mouse_moved = 1;
8644 XSETVECTOR (last_mouse_scroll_bar, bar);
8645
8646 /* If we're dragging the bar, display it. */
8647 if (! GC_NILP (bar->dragging))
8648 {
8649 /* Where should the handle be now? */
8650 int new_start = event->xmotion.y - XINT (bar->dragging);
8651
8652 if (new_start != XINT (bar->start))
8653 {
8654 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
8655
8656 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
8657 }
8658 }
8659 }
8660
8661 #endif /* !USE_TOOLKIT_SCROLL_BARS */
8662
8663 /* Return information to the user about the current position of the mouse
8664 on the scroll bar. */
8665
8666 static void
8667 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8668 FRAME_PTR *fp;
8669 Lisp_Object *bar_window;
8670 enum scroll_bar_part *part;
8671 Lisp_Object *x, *y;
8672 unsigned long *time;
8673 {
8674 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8675 Window w = SCROLL_BAR_X_WINDOW (bar);
8676 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8677 int win_x, win_y;
8678 Window dummy_window;
8679 int dummy_coord;
8680 unsigned int dummy_mask;
8681
8682 BLOCK_INPUT;
8683
8684 /* Get the mouse's position relative to the scroll bar window, and
8685 report that. */
8686 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
8687
8688 /* Root, child, root x and root y. */
8689 &dummy_window, &dummy_window,
8690 &dummy_coord, &dummy_coord,
8691
8692 /* Position relative to scroll bar. */
8693 &win_x, &win_y,
8694
8695 /* Mouse buttons and modifier keys. */
8696 &dummy_mask))
8697 ;
8698 else
8699 {
8700 #if 0
8701 int inside_height
8702 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8703 #endif
8704 int top_range
8705 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8706
8707 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8708
8709 if (! NILP (bar->dragging))
8710 win_y -= XINT (bar->dragging);
8711
8712 if (win_y < 0)
8713 win_y = 0;
8714 if (win_y > top_range)
8715 win_y = top_range;
8716
8717 *fp = f;
8718 *bar_window = bar->window;
8719
8720 if (! NILP (bar->dragging))
8721 *part = scroll_bar_handle;
8722 else if (win_y < XINT (bar->start))
8723 *part = scroll_bar_above_handle;
8724 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8725 *part = scroll_bar_handle;
8726 else
8727 *part = scroll_bar_below_handle;
8728
8729 XSETINT (*x, win_y);
8730 XSETINT (*y, top_range);
8731
8732 f->mouse_moved = 0;
8733 last_mouse_scroll_bar = Qnil;
8734 }
8735
8736 *time = last_mouse_movement_time;
8737
8738 UNBLOCK_INPUT;
8739 }
8740
8741
8742 /* The screen has been cleared so we may have changed foreground or
8743 background colors, and the scroll bars may need to be redrawn.
8744 Clear out the scroll bars, and ask for expose events, so we can
8745 redraw them. */
8746
8747 void
8748 x_scroll_bar_clear (f)
8749 FRAME_PTR f;
8750 {
8751 #ifndef USE_TOOLKIT_SCROLL_BARS
8752 Lisp_Object bar;
8753
8754 /* We can have scroll bars even if this is 0,
8755 if we just turned off scroll bar mode.
8756 But in that case we should not clear them. */
8757 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8758 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8759 bar = XSCROLL_BAR (bar)->next)
8760 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8761 0, 0, 0, 0, True);
8762 #endif /* not USE_TOOLKIT_SCROLL_BARS */
8763 }
8764
8765 /* This processes Expose events from the menu-bar specific X event
8766 loop in xmenu.c. This allows to redisplay the frame if necessary
8767 when handling menu-bar or pop-up items. */
8768
8769 int
8770 process_expose_from_menu (event)
8771 XEvent event;
8772 {
8773 FRAME_PTR f;
8774 struct x_display_info *dpyinfo;
8775 int frame_exposed_p = 0;
8776
8777 BLOCK_INPUT;
8778
8779 dpyinfo = x_display_info_for_display (event.xexpose.display);
8780 f = x_window_to_frame (dpyinfo, event.xexpose.window);
8781 if (f)
8782 {
8783 if (f->async_visible == 0)
8784 {
8785 f->async_visible = 1;
8786 f->async_iconified = 0;
8787 f->output_data.x->has_been_visible = 1;
8788 SET_FRAME_GARBAGED (f);
8789 }
8790 else
8791 {
8792 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8793 event.xexpose.x, event.xexpose.y,
8794 event.xexpose.width, event.xexpose.height);
8795 frame_exposed_p = 1;
8796 }
8797 }
8798 else
8799 {
8800 struct scroll_bar *bar
8801 = x_window_to_scroll_bar (event.xexpose.window);
8802
8803 if (bar)
8804 x_scroll_bar_expose (bar, &event);
8805 }
8806
8807 UNBLOCK_INPUT;
8808 return frame_exposed_p;
8809 }
8810 \f
8811 /* Define a queue to save up SelectionRequest events for later handling. */
8812
8813 struct selection_event_queue
8814 {
8815 XEvent event;
8816 struct selection_event_queue *next;
8817 };
8818
8819 static struct selection_event_queue *queue;
8820
8821 /* Nonzero means queue up certain events--don't process them yet. */
8822
8823 static int x_queue_selection_requests;
8824
8825 /* Queue up an X event *EVENT, to be processed later. */
8826
8827 static void
8828 x_queue_event (f, event)
8829 FRAME_PTR f;
8830 XEvent *event;
8831 {
8832 struct selection_event_queue *queue_tmp
8833 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
8834
8835 if (queue_tmp != NULL)
8836 {
8837 queue_tmp->event = *event;
8838 queue_tmp->next = queue;
8839 queue = queue_tmp;
8840 }
8841 }
8842
8843 /* Take all the queued events and put them back
8844 so that they get processed afresh. */
8845
8846 static void
8847 x_unqueue_events (display)
8848 Display *display;
8849 {
8850 while (queue != NULL)
8851 {
8852 struct selection_event_queue *queue_tmp = queue;
8853 XPutBackEvent (display, &queue_tmp->event);
8854 queue = queue_tmp->next;
8855 xfree ((char *)queue_tmp);
8856 }
8857 }
8858
8859 /* Start queuing SelectionRequest events. */
8860
8861 void
8862 x_start_queuing_selection_requests (display)
8863 Display *display;
8864 {
8865 x_queue_selection_requests++;
8866 }
8867
8868 /* Stop queuing SelectionRequest events. */
8869
8870 void
8871 x_stop_queuing_selection_requests (display)
8872 Display *display;
8873 {
8874 x_queue_selection_requests--;
8875 x_unqueue_events (display);
8876 }
8877 \f
8878 /* The main X event-reading loop - XTread_socket. */
8879
8880 /* Time stamp of enter window event. This is only used by XTread_socket,
8881 but we have to put it out here, since static variables within functions
8882 sometimes don't work. */
8883
8884 static Time enter_timestamp;
8885
8886 /* This holds the state XLookupString needs to implement dead keys
8887 and other tricks known as "compose processing". _X Window System_
8888 says that a portable program can't use this, but Stephen Gildea assures
8889 me that letting the compiler initialize it to zeros will work okay.
8890
8891 This must be defined outside of XTread_socket, for the same reasons
8892 given for enter_time stamp, above. */
8893
8894 static XComposeStatus compose_status;
8895
8896 /* Record the last 100 characters stored
8897 to help debug the loss-of-chars-during-GC problem. */
8898
8899 static int temp_index;
8900 static short temp_buffer[100];
8901
8902 /* Set this to nonzero to fake an "X I/O error"
8903 on a particular display. */
8904
8905 struct x_display_info *XTread_socket_fake_io_error;
8906
8907 /* When we find no input here, we occasionally do a no-op command
8908 to verify that the X server is still running and we can still talk with it.
8909 We try all the open displays, one by one.
8910 This variable is used for cycling thru the displays. */
8911
8912 static struct x_display_info *next_noop_dpyinfo;
8913
8914 #define SET_SAVED_MENU_EVENT(size) \
8915 do \
8916 { \
8917 if (f->output_data.x->saved_menu_event == 0) \
8918 f->output_data.x->saved_menu_event \
8919 = (XEvent *) xmalloc (sizeof (XEvent)); \
8920 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8921 if (numchars >= 1) \
8922 { \
8923 bufp->kind = menu_bar_activate_event; \
8924 XSETFRAME (bufp->frame_or_window, f); \
8925 bufp++; \
8926 count++; \
8927 numchars--; \
8928 } \
8929 } \
8930 while (0)
8931
8932 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
8933 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8934
8935 /* Read events coming from the X server.
8936 This routine is called by the SIGIO handler.
8937 We return as soon as there are no more events to be read.
8938
8939 Events representing keys are stored in buffer BUFP,
8940 which can hold up to NUMCHARS characters.
8941 We return the number of characters stored into the buffer,
8942 thus pretending to be `read'.
8943
8944 EXPECTED is nonzero if the caller knows input is available. */
8945
8946 int
8947 XTread_socket (sd, bufp, numchars, expected)
8948 register int sd;
8949 /* register */ struct input_event *bufp;
8950 /* register */ int numchars;
8951 int expected;
8952 {
8953 int count = 0;
8954 int nbytes = 0;
8955 XEvent event;
8956 struct frame *f;
8957 int event_found = 0;
8958 struct x_display_info *dpyinfo;
8959
8960 if (interrupt_input_blocked)
8961 {
8962 interrupt_input_pending = 1;
8963 return -1;
8964 }
8965
8966 interrupt_input_pending = 0;
8967 BLOCK_INPUT;
8968
8969 /* So people can tell when we have read the available input. */
8970 input_signal_count++;
8971
8972 if (numchars <= 0)
8973 abort (); /* Don't think this happens. */
8974
8975 ++handling_signal;
8976
8977 /* Find the display we are supposed to read input for.
8978 It's the one communicating on descriptor SD. */
8979 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8980 {
8981 #if 0 /* This ought to be unnecessary; let's verify it. */
8982 #ifdef FIOSNBIO
8983 /* If available, Xlib uses FIOSNBIO to make the socket
8984 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
8985 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
8986 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
8987 fcntl (dpyinfo->connection, F_SETFL, 0);
8988 #endif /* ! defined (FIOSNBIO) */
8989 #endif
8990
8991 #if 0 /* This code can't be made to work, with multiple displays,
8992 and appears not to be used on any system any more.
8993 Also keyboard.c doesn't turn O_NDELAY on and off
8994 for X connections. */
8995 #ifndef SIGIO
8996 #ifndef HAVE_SELECT
8997 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8998 {
8999 extern int read_alarm_should_throw;
9000 read_alarm_should_throw = 1;
9001 XPeekEvent (dpyinfo->display, &event);
9002 read_alarm_should_throw = 0;
9003 }
9004 #endif /* HAVE_SELECT */
9005 #endif /* SIGIO */
9006 #endif
9007
9008 /* For debugging, this gives a way to fake an I/O error. */
9009 if (dpyinfo == XTread_socket_fake_io_error)
9010 {
9011 XTread_socket_fake_io_error = 0;
9012 x_io_error_quitter (dpyinfo->display);
9013 }
9014
9015 while (XPending (dpyinfo->display))
9016 {
9017 XNextEvent (dpyinfo->display, &event);
9018
9019 #ifdef HAVE_X_I18N
9020 {
9021 /* Filter events for the current X input method.
9022 XFilterEvent returns non-zero if the input method has
9023 consumed the event. We pass the frame's X window to
9024 XFilterEvent because that's the one for which the IC
9025 was created. */
9026 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9027 event.xclient.window);
9028 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
9029 break;
9030 }
9031 #endif
9032 event_found = 1;
9033
9034 switch (event.type)
9035 {
9036 case ClientMessage:
9037 {
9038 if (event.xclient.message_type
9039 == dpyinfo->Xatom_wm_protocols
9040 && event.xclient.format == 32)
9041 {
9042 if (event.xclient.data.l[0]
9043 == dpyinfo->Xatom_wm_take_focus)
9044 {
9045 /* Use x_any_window_to_frame because this
9046 could be the shell widget window
9047 if the frame has no title bar. */
9048 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
9049 #ifdef HAVE_X_I18N
9050 /* Not quite sure this is needed -pd */
9051 if (f && FRAME_XIC (f))
9052 XSetICFocus (FRAME_XIC (f));
9053 #endif
9054 #if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9055 instructs the WM to set the input focus automatically for
9056 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9057 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9058 it has set the focus. So, XSetInputFocus below is not
9059 needed.
9060
9061 The call to XSetInputFocus below has also caused trouble. In
9062 cases where the XSetInputFocus done by the WM and the one
9063 below are temporally close (on a fast machine), the call
9064 below can generate additional FocusIn events which confuse
9065 Emacs. */
9066
9067 /* Since we set WM_TAKE_FOCUS, we must call
9068 XSetInputFocus explicitly. But not if f is null,
9069 since that might be an event for a deleted frame. */
9070 if (f)
9071 {
9072 Display *d = event.xclient.display;
9073 /* Catch and ignore errors, in case window has been
9074 iconified by a window manager such as GWM. */
9075 int count = x_catch_errors (d);
9076 XSetInputFocus (d, event.xclient.window,
9077 /* The ICCCM says this is
9078 the only valid choice. */
9079 RevertToParent,
9080 event.xclient.data.l[1]);
9081 /* This is needed to detect the error
9082 if there is an error. */
9083 XSync (d, False);
9084 x_uncatch_errors (d, count);
9085 }
9086 /* Not certain about handling scroll bars here */
9087 #endif /* 0 */
9088 }
9089 else if (event.xclient.data.l[0]
9090 == dpyinfo->Xatom_wm_save_yourself)
9091 {
9092 /* Save state modify the WM_COMMAND property to
9093 something which can reinstate us. This notifies
9094 the session manager, who's looking for such a
9095 PropertyNotify. Can restart processing when
9096 a keyboard or mouse event arrives. */
9097 if (numchars > 0)
9098 {
9099 f = x_top_window_to_frame (dpyinfo,
9100 event.xclient.window);
9101
9102 /* This is just so we only give real data once
9103 for a single Emacs process. */
9104 if (f == SELECTED_FRAME ())
9105 XSetCommand (FRAME_X_DISPLAY (f),
9106 event.xclient.window,
9107 initial_argv, initial_argc);
9108 else if (f)
9109 XSetCommand (FRAME_X_DISPLAY (f),
9110 event.xclient.window,
9111 0, 0);
9112 }
9113 }
9114 else if (event.xclient.data.l[0]
9115 == dpyinfo->Xatom_wm_delete_window)
9116 {
9117 struct frame *f
9118 = x_any_window_to_frame (dpyinfo,
9119 event.xclient.window);
9120
9121 if (f)
9122 {
9123 if (numchars == 0)
9124 abort ();
9125
9126 bufp->kind = delete_window_event;
9127 XSETFRAME (bufp->frame_or_window, f);
9128 bufp++;
9129
9130 count += 1;
9131 numchars -= 1;
9132 }
9133 }
9134 }
9135 else if (event.xclient.message_type
9136 == dpyinfo->Xatom_wm_configure_denied)
9137 {
9138 }
9139 else if (event.xclient.message_type
9140 == dpyinfo->Xatom_wm_window_moved)
9141 {
9142 int new_x, new_y;
9143 struct frame *f
9144 = x_window_to_frame (dpyinfo, event.xclient.window);
9145
9146 new_x = event.xclient.data.s[0];
9147 new_y = event.xclient.data.s[1];
9148
9149 if (f)
9150 {
9151 f->output_data.x->left_pos = new_x;
9152 f->output_data.x->top_pos = new_y;
9153 }
9154 }
9155 #ifdef HACK_EDITRES
9156 else if (event.xclient.message_type
9157 == dpyinfo->Xatom_editres)
9158 {
9159 struct frame *f
9160 = x_any_window_to_frame (dpyinfo, event.xclient.window);
9161 _XEditResCheckMessages (f->output_data.x->widget, NULL,
9162 &event, NULL);
9163 }
9164 #endif /* HACK_EDITRES */
9165 else if ((event.xclient.message_type
9166 == dpyinfo->Xatom_DONE)
9167 || (event.xclient.message_type
9168 == dpyinfo->Xatom_PAGE))
9169 {
9170 /* Ghostview job completed. Kill it. We could
9171 reply with "Next" if we received "Page", but we
9172 currently never do because we are interested in
9173 images, only, which should have 1 page. */
9174 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9175 struct frame *f
9176 = x_window_to_frame (dpyinfo, event.xclient.window);
9177 x_kill_gs_process (pixmap, f);
9178 expose_frame (f, 0, 0, 0, 0);
9179 }
9180 #ifdef USE_TOOLKIT_SCROLL_BARS
9181 /* Scroll bar callbacks send a ClientMessage from which
9182 we construct an input_event. */
9183 else if (event.xclient.message_type
9184 == dpyinfo->Xatom_Scrollbar)
9185 {
9186 x_scroll_bar_to_input_event (&event, bufp);
9187 ++bufp, ++count, --numchars;
9188 goto out;
9189 }
9190 #endif /* USE_TOOLKIT_SCROLL_BARS */
9191 else
9192 goto OTHER;
9193 }
9194 break;
9195
9196 case SelectionNotify:
9197 #ifdef USE_X_TOOLKIT
9198 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
9199 goto OTHER;
9200 #endif /* not USE_X_TOOLKIT */
9201 x_handle_selection_notify (&event.xselection);
9202 break;
9203
9204 case SelectionClear: /* Someone has grabbed ownership. */
9205 #ifdef USE_X_TOOLKIT
9206 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
9207 goto OTHER;
9208 #endif /* USE_X_TOOLKIT */
9209 {
9210 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
9211
9212 if (numchars == 0)
9213 abort ();
9214
9215 bufp->kind = selection_clear_event;
9216 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9217 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9218 SELECTION_EVENT_TIME (bufp) = eventp->time;
9219 bufp->frame_or_window = Qnil;
9220 bufp++;
9221
9222 count += 1;
9223 numchars -= 1;
9224 }
9225 break;
9226
9227 case SelectionRequest: /* Someone wants our selection. */
9228 #ifdef USE_X_TOOLKIT
9229 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
9230 goto OTHER;
9231 #endif /* USE_X_TOOLKIT */
9232 if (x_queue_selection_requests)
9233 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
9234 &event);
9235 else
9236 {
9237 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
9238
9239 if (numchars == 0)
9240 abort ();
9241
9242 bufp->kind = selection_request_event;
9243 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9244 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9245 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9246 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9247 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9248 SELECTION_EVENT_TIME (bufp) = eventp->time;
9249 bufp->frame_or_window = Qnil;
9250 bufp++;
9251
9252 count += 1;
9253 numchars -= 1;
9254 }
9255 break;
9256
9257 case PropertyNotify:
9258 #ifdef USE_X_TOOLKIT
9259 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
9260 goto OTHER;
9261 #endif /* not USE_X_TOOLKIT */
9262 x_handle_property_notify (&event.xproperty);
9263 break;
9264
9265 case ReparentNotify:
9266 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
9267 if (f)
9268 {
9269 int x, y;
9270 f->output_data.x->parent_desc = event.xreparent.parent;
9271 x_real_positions (f, &x, &y);
9272 f->output_data.x->left_pos = x;
9273 f->output_data.x->top_pos = y;
9274 }
9275 break;
9276
9277 case Expose:
9278 f = x_window_to_frame (dpyinfo, event.xexpose.window);
9279 if (f)
9280 {
9281 if (f->async_visible == 0)
9282 {
9283 f->async_visible = 1;
9284 f->async_iconified = 0;
9285 f->output_data.x->has_been_visible = 1;
9286 SET_FRAME_GARBAGED (f);
9287 }
9288 else
9289 expose_frame (x_window_to_frame (dpyinfo,
9290 event.xexpose.window),
9291 event.xexpose.x, event.xexpose.y,
9292 event.xexpose.width, event.xexpose.height);
9293 }
9294 else
9295 {
9296 #ifdef USE_TOOLKIT_SCROLL_BARS
9297 /* Dispatch event to the widget. */
9298 goto OTHER;
9299 #else /* not USE_TOOLKIT_SCROLL_BARS */
9300 struct scroll_bar *bar
9301 = x_window_to_scroll_bar (event.xexpose.window);
9302
9303 if (bar)
9304 x_scroll_bar_expose (bar, &event);
9305 #ifdef USE_X_TOOLKIT
9306 else
9307 goto OTHER;
9308 #endif /* USE_X_TOOLKIT */
9309 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9310 }
9311 break;
9312
9313 case GraphicsExpose: /* This occurs when an XCopyArea's
9314 source area was obscured or not
9315 available.*/
9316 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
9317 if (f)
9318 {
9319 expose_frame (f,
9320 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9321 event.xgraphicsexpose.width,
9322 event.xgraphicsexpose.height);
9323 }
9324 #ifdef USE_X_TOOLKIT
9325 else
9326 goto OTHER;
9327 #endif /* USE_X_TOOLKIT */
9328 break;
9329
9330 case NoExpose: /* This occurs when an XCopyArea's
9331 source area was completely
9332 available */
9333 break;
9334
9335 case UnmapNotify:
9336 /* Redo the mouse-highlight after the tooltip has gone. */
9337 if (event.xmap.window == tip_window)
9338 {
9339 tip_window = 0;
9340 redo_mouse_highlight ();
9341 }
9342
9343 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
9344 if (f) /* F may no longer exist if
9345 the frame was deleted. */
9346 {
9347 /* While a frame is unmapped, display generation is
9348 disabled; you don't want to spend time updating a
9349 display that won't ever be seen. */
9350 f->async_visible = 0;
9351 /* We can't distinguish, from the event, whether the window
9352 has become iconified or invisible. So assume, if it
9353 was previously visible, than now it is iconified.
9354 But x_make_frame_invisible clears both
9355 the visible flag and the iconified flag;
9356 and that way, we know the window is not iconified now. */
9357 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
9358 {
9359 f->async_iconified = 1;
9360
9361 bufp->kind = iconify_event;
9362 XSETFRAME (bufp->frame_or_window, f);
9363 bufp++;
9364 count++;
9365 numchars--;
9366 }
9367 }
9368 goto OTHER;
9369
9370 case MapNotify:
9371 if (event.xmap.window == tip_window)
9372 /* The tooltip has been drawn already. Avoid
9373 the SET_FRAME_GARBAGED below. */
9374 goto OTHER;
9375
9376 /* We use x_top_window_to_frame because map events can
9377 come for sub-windows and they don't mean that the
9378 frame is visible. */
9379 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
9380 if (f)
9381 {
9382 f->async_visible = 1;
9383 f->async_iconified = 0;
9384 f->output_data.x->has_been_visible = 1;
9385
9386 /* wait_reading_process_input will notice this and update
9387 the frame's display structures. */
9388 SET_FRAME_GARBAGED (f);
9389
9390 if (f->iconified)
9391 {
9392 bufp->kind = deiconify_event;
9393 XSETFRAME (bufp->frame_or_window, f);
9394 bufp++;
9395 count++;
9396 numchars--;
9397 }
9398 else if (! NILP (Vframe_list)
9399 && ! NILP (XCDR (Vframe_list)))
9400 /* Force a redisplay sooner or later
9401 to update the frame titles
9402 in case this is the second frame. */
9403 record_asynch_buffer_change ();
9404 }
9405 goto OTHER;
9406
9407 case KeyPress:
9408 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
9409
9410 #ifdef USE_MOTIF
9411 /* I couldn't find a way to prevent LessTif scroll bars
9412 from consuming key events. */
9413 if (f == 0)
9414 {
9415 Widget widget = XtWindowToWidget (dpyinfo->display,
9416 event.xkey.window);
9417 if (widget && XmIsScrollBar (widget))
9418 {
9419 widget = XtParent (widget);
9420 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9421 }
9422 }
9423 #endif /* USE_MOTIF */
9424
9425 if (f != 0)
9426 {
9427 KeySym keysym, orig_keysym;
9428 /* al%imercury@uunet.uu.net says that making this 81 instead of
9429 80 fixed a bug whereby meta chars made his Emacs hang. */
9430 unsigned char copy_buffer[81];
9431 int modifiers;
9432
9433 event.xkey.state
9434 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9435 extra_keyboard_modifiers);
9436 modifiers = event.xkey.state;
9437
9438 /* This will have to go some day... */
9439
9440 /* make_lispy_event turns chars into control chars.
9441 Don't do it here because XLookupString is too eager. */
9442 event.xkey.state &= ~ControlMask;
9443 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9444 | dpyinfo->super_mod_mask
9445 | dpyinfo->hyper_mod_mask
9446 | dpyinfo->alt_mod_mask);
9447
9448 /* In case Meta is ComposeCharacter,
9449 clear its status. According to Markus Ehrnsperger
9450 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9451 this enables ComposeCharacter to work whether or
9452 not it is combined with Meta. */
9453 if (modifiers & dpyinfo->meta_mod_mask)
9454 bzero (&compose_status, sizeof (compose_status));
9455
9456 #ifdef HAVE_X_I18N
9457 if (FRAME_XIC (f))
9458 {
9459 unsigned char *copy_bufptr = copy_buffer;
9460 int copy_bufsiz = sizeof (copy_buffer);
9461 Status status_return;
9462
9463 nbytes = XmbLookupString (FRAME_XIC (f),
9464 &event.xkey, copy_bufptr,
9465 copy_bufsiz, &keysym,
9466 &status_return);
9467 if (status_return == XBufferOverflow)
9468 {
9469 copy_bufsiz = nbytes + 1;
9470 copy_bufptr = (char *) alloca (copy_bufsiz);
9471 nbytes = XmbLookupString (FRAME_XIC (f),
9472 &event.xkey, copy_bufptr,
9473 copy_bufsiz, &keysym,
9474 &status_return);
9475 }
9476
9477 if (status_return == XLookupNone)
9478 break;
9479 else if (status_return == XLookupChars)
9480 {
9481 keysym = NoSymbol;
9482 modifiers = 0;
9483 }
9484 else if (status_return != XLookupKeySym
9485 && status_return != XLookupBoth)
9486 abort ();
9487 }
9488 else
9489 nbytes = XLookupString (&event.xkey, copy_buffer,
9490 80, &keysym, &compose_status);
9491 #else
9492 nbytes = XLookupString (&event.xkey, copy_buffer,
9493 80, &keysym, &compose_status);
9494 #endif
9495
9496 orig_keysym = keysym;
9497
9498 if (numchars > 1)
9499 {
9500 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9501 || keysym == XK_Delete
9502 #ifdef XK_ISO_Left_Tab
9503 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
9504 #endif
9505 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
9506 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9507 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
9508 #ifdef HPUX
9509 /* This recognizes the "extended function keys".
9510 It seems there's no cleaner way.
9511 Test IsModifierKey to avoid handling mode_switch
9512 incorrectly. */
9513 || ((unsigned) (keysym) >= XK_Select
9514 && (unsigned)(keysym) < XK_KP_Space)
9515 #endif
9516 #ifdef XK_dead_circumflex
9517 || orig_keysym == XK_dead_circumflex
9518 #endif
9519 #ifdef XK_dead_grave
9520 || orig_keysym == XK_dead_grave
9521 #endif
9522 #ifdef XK_dead_tilde
9523 || orig_keysym == XK_dead_tilde
9524 #endif
9525 #ifdef XK_dead_diaeresis
9526 || orig_keysym == XK_dead_diaeresis
9527 #endif
9528 #ifdef XK_dead_macron
9529 || orig_keysym == XK_dead_macron
9530 #endif
9531 #ifdef XK_dead_degree
9532 || orig_keysym == XK_dead_degree
9533 #endif
9534 #ifdef XK_dead_acute
9535 || orig_keysym == XK_dead_acute
9536 #endif
9537 #ifdef XK_dead_cedilla
9538 || orig_keysym == XK_dead_cedilla
9539 #endif
9540 #ifdef XK_dead_breve
9541 || orig_keysym == XK_dead_breve
9542 #endif
9543 #ifdef XK_dead_ogonek
9544 || orig_keysym == XK_dead_ogonek
9545 #endif
9546 #ifdef XK_dead_caron
9547 || orig_keysym == XK_dead_caron
9548 #endif
9549 #ifdef XK_dead_doubleacute
9550 || orig_keysym == XK_dead_doubleacute
9551 #endif
9552 #ifdef XK_dead_abovedot
9553 || orig_keysym == XK_dead_abovedot
9554 #endif
9555 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9556 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9557 /* Any "vendor-specific" key is ok. */
9558 || (orig_keysym & (1 << 28)))
9559 && ! (IsModifierKey (orig_keysym)
9560 #ifndef HAVE_X11R5
9561 #ifdef XK_Mode_switch
9562 || ((unsigned)(orig_keysym) == XK_Mode_switch)
9563 #endif
9564 #ifdef XK_Num_Lock
9565 || ((unsigned)(orig_keysym) == XK_Num_Lock)
9566 #endif
9567 #endif /* not HAVE_X11R5 */
9568 ))
9569 {
9570 if (temp_index == sizeof temp_buffer / sizeof (short))
9571 temp_index = 0;
9572 temp_buffer[temp_index++] = keysym;
9573 bufp->kind = non_ascii_keystroke;
9574 bufp->code = keysym;
9575 XSETFRAME (bufp->frame_or_window, f);
9576 bufp->modifiers
9577 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9578 modifiers);
9579 bufp->timestamp = event.xkey.time;
9580 bufp++;
9581 count++;
9582 numchars--;
9583 }
9584 else if (numchars > nbytes)
9585 {
9586 register int i;
9587
9588 for (i = 0; i < nbytes; i++)
9589 {
9590 if (temp_index == sizeof temp_buffer / sizeof (short))
9591 temp_index = 0;
9592 temp_buffer[temp_index++] = copy_buffer[i];
9593 bufp->kind = ascii_keystroke;
9594 bufp->code = copy_buffer[i];
9595 XSETFRAME (bufp->frame_or_window, f);
9596 bufp->modifiers
9597 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9598 modifiers);
9599 bufp->timestamp = event.xkey.time;
9600 bufp++;
9601 }
9602
9603 count += nbytes;
9604 numchars -= nbytes;
9605
9606 if (keysym == NoSymbol)
9607 break;
9608 }
9609 else
9610 abort ();
9611 }
9612 else
9613 abort ();
9614 }
9615 #ifdef HAVE_X_I18N
9616 /* Don't dispatch this event since XtDispatchEvent calls
9617 XFilterEvent, and two calls in a row may freeze the
9618 client. */
9619 break;
9620 #else
9621 goto OTHER;
9622 #endif
9623
9624 case KeyRelease:
9625 #ifdef HAVE_X_I18N
9626 /* Don't dispatch this event since XtDispatchEvent calls
9627 XFilterEvent, and two calls in a row may freeze the
9628 client. */
9629 break;
9630 #else
9631 goto OTHER;
9632 #endif
9633
9634 /* Here's a possible interpretation of the whole
9635 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9636 you get a FocusIn event, you have to get a FocusOut
9637 event before you relinquish the focus. If you
9638 haven't received a FocusIn event, then a mere
9639 LeaveNotify is enough to free you. */
9640
9641 case EnterNotify:
9642 {
9643 int from_menu_bar_p = 0;
9644
9645 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9646
9647 #ifdef LESSTIF_VERSION
9648 /* When clicking outside of a menu bar popup to close
9649 it, we get a FocusIn/ EnterNotify sequence of
9650 events. The flag event.xcrossing.focus is not set
9651 in the EnterNotify event of that sequence because
9652 the focus is in the menu bar,
9653 event.xcrossing.window is the frame's X window.
9654 Unconditionally setting the focus frame to null in
9655 this case is not the right thing, because no event
9656 follows that could set the focus frame to the right
9657 value.
9658
9659 This could be a LessTif bug, but I wasn't able to
9660 reproduce the behavior in a simple test program.
9661
9662 (gerd, LessTif 0.88.1). */
9663
9664 if (!event.xcrossing.focus
9665 && f
9666 && f->output_data.x->menubar_widget)
9667 {
9668 Window focus;
9669 int revert;
9670
9671 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9672 if (focus == XtWindow (f->output_data.x->menubar_widget))
9673 from_menu_bar_p = 1;
9674 }
9675 #endif /* LESSTIF_VERSION */
9676
9677 if (event.xcrossing.focus || from_menu_bar_p)
9678 {
9679 /* Avoid nasty pop/raise loops. */
9680 if (f && (!(f->auto_raise)
9681 || !(f->auto_lower)
9682 || (event.xcrossing.time - enter_timestamp) > 500))
9683 {
9684 x_new_focus_frame (dpyinfo, f);
9685 enter_timestamp = event.xcrossing.time;
9686 }
9687 }
9688 else if (f == dpyinfo->x_focus_frame)
9689 x_new_focus_frame (dpyinfo, 0);
9690
9691 /* EnterNotify counts as mouse movement,
9692 so update things that depend on mouse position. */
9693 if (f && !f->output_data.x->busy_p)
9694 note_mouse_movement (f, &event.xmotion);
9695 goto OTHER;
9696 }
9697
9698 case FocusIn:
9699 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9700 if (event.xfocus.detail != NotifyPointer)
9701 dpyinfo->x_focus_event_frame = f;
9702 if (f)
9703 {
9704 x_new_focus_frame (dpyinfo, f);
9705
9706 /* Don't stop displaying the initial startup message
9707 for a switch-frame event we don't need. */
9708 if (GC_NILP (Vterminal_frame)
9709 && GC_CONSP (Vframe_list)
9710 && !GC_NILP (XCDR (Vframe_list)))
9711 {
9712 bufp->kind = FOCUS_IN_EVENT;
9713 XSETFRAME (bufp->frame_or_window, f);
9714 ++bufp, ++count, --numchars;
9715 }
9716 }
9717
9718 #ifdef HAVE_X_I18N
9719 if (f && FRAME_XIC (f))
9720 XSetICFocus (FRAME_XIC (f));
9721 #endif
9722
9723 goto OTHER;
9724
9725 case LeaveNotify:
9726 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
9727 if (f)
9728 {
9729 Lisp_Object frame;
9730 int from_menu_bar_p = 0;
9731
9732 if (f == dpyinfo->mouse_face_mouse_frame)
9733 {
9734 /* If we move outside the frame, then we're
9735 certainly no longer on any text in the frame. */
9736 clear_mouse_face (dpyinfo);
9737 dpyinfo->mouse_face_mouse_frame = 0;
9738 }
9739
9740 /* Generate a nil HELP_EVENT to cancel a help-echo.
9741 Do it only if there's something to cancel.
9742 Otherwise, the startup message is cleared when
9743 the mouse leaves the frame. */
9744 if (any_help_event_p)
9745 {
9746 XSETFRAME (frame, f);
9747 bufp->kind = HELP_EVENT;
9748 bufp->frame_or_window = Fcons (frame, Qnil);
9749 ++bufp, ++count, --numchars;
9750 }
9751
9752 #ifdef LESSTIF_VERSION
9753 /* Please see the comment at the start of the
9754 EnterNotify case. */
9755 if (!event.xcrossing.focus
9756 && f->output_data.x->menubar_widget)
9757 {
9758 Window focus;
9759 int revert;
9760 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9761 if (focus == XtWindow (f->output_data.x->menubar_widget))
9762 from_menu_bar_p = 1;
9763 }
9764 #endif /* LESSTIF_VERSION */
9765
9766 if (event.xcrossing.focus || from_menu_bar_p)
9767 x_mouse_leave (dpyinfo);
9768 else
9769 {
9770 if (f == dpyinfo->x_focus_event_frame)
9771 dpyinfo->x_focus_event_frame = 0;
9772 if (f == dpyinfo->x_focus_frame)
9773 x_new_focus_frame (dpyinfo, 0);
9774 }
9775 }
9776 goto OTHER;
9777
9778 case FocusOut:
9779 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
9780 if (event.xfocus.detail != NotifyPointer
9781 && f == dpyinfo->x_focus_event_frame)
9782 dpyinfo->x_focus_event_frame = 0;
9783 if (f && f == dpyinfo->x_focus_frame)
9784 x_new_focus_frame (dpyinfo, 0);
9785
9786 #ifdef HAVE_X_I18N
9787 if (f && FRAME_XIC (f))
9788 XUnsetICFocus (FRAME_XIC (f));
9789 #endif
9790
9791 goto OTHER;
9792
9793 case MotionNotify:
9794 {
9795 previous_help_echo = help_echo;
9796 help_echo = Qnil;
9797
9798 if (dpyinfo->grabbed && last_mouse_frame
9799 && FRAME_LIVE_P (last_mouse_frame))
9800 f = last_mouse_frame;
9801 else
9802 f = x_window_to_frame (dpyinfo, event.xmotion.window);
9803
9804 if (f)
9805 note_mouse_movement (f, &event.xmotion);
9806 else
9807 {
9808 #ifndef USE_TOOLKIT_SCROLL_BARS
9809 struct scroll_bar *bar
9810 = x_window_to_scroll_bar (event.xmotion.window);
9811
9812 if (bar)
9813 x_scroll_bar_note_movement (bar, &event);
9814 #endif /* USE_TOOLKIT_SCROLL_BARS */
9815
9816 /* If we move outside the frame, then we're
9817 certainly no longer on any text in the frame. */
9818 clear_mouse_face (dpyinfo);
9819 }
9820
9821 /* If the contents of the global variable help_echo
9822 has changed, generate a HELP_EVENT. */
9823 if (!NILP (help_echo)
9824 || !NILP (previous_help_echo))
9825 {
9826 Lisp_Object frame;
9827
9828 if (f)
9829 XSETFRAME (frame, f);
9830 else
9831 frame = Qnil;
9832
9833 any_help_event_p = 1;
9834 bufp->kind = HELP_EVENT;
9835 bufp->frame_or_window = Fcons (frame, help_echo);
9836 ++bufp, ++count, --numchars;
9837 }
9838
9839 goto OTHER;
9840 }
9841
9842 case ConfigureNotify:
9843 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9844 if (f)
9845 {
9846 #ifndef USE_X_TOOLKIT
9847 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9848 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
9849
9850 /* In the toolkit version, change_frame_size
9851 is called by the code that handles resizing
9852 of the EmacsFrame widget. */
9853
9854 /* Even if the number of character rows and columns has
9855 not changed, the font size may have changed, so we need
9856 to check the pixel dimensions as well. */
9857 if (columns != f->width
9858 || rows != f->height
9859 || event.xconfigure.width != f->output_data.x->pixel_width
9860 || event.xconfigure.height != f->output_data.x->pixel_height)
9861 {
9862 change_frame_size (f, rows, columns, 0, 1, 0);
9863 SET_FRAME_GARBAGED (f);
9864 cancel_mouse_face (f);
9865 }
9866 #endif
9867
9868 f->output_data.x->pixel_width = event.xconfigure.width;
9869 f->output_data.x->pixel_height = event.xconfigure.height;
9870
9871 /* What we have now is the position of Emacs's own window.
9872 Convert that to the position of the window manager window. */
9873 x_real_positions (f, &f->output_data.x->left_pos,
9874 &f->output_data.x->top_pos);
9875
9876 #ifdef HAVE_X_I18N
9877 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9878 xic_set_statusarea (f);
9879 #endif
9880
9881 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9882 {
9883 /* Since the WM decorations come below top_pos now,
9884 we must put them below top_pos in the future. */
9885 f->output_data.x->win_gravity = NorthWestGravity;
9886 x_wm_set_size_hint (f, (long) 0, 0);
9887 }
9888 #ifdef USE_MOTIF
9889 /* Some window managers pass (0,0) as the location of
9890 the window, and the Motif event handler stores it
9891 in the emacs widget, which messes up Motif menus. */
9892 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9893 {
9894 event.xconfigure.x = f->output_data.x->widget->core.x;
9895 event.xconfigure.y = f->output_data.x->widget->core.y;
9896 }
9897 #endif /* USE_MOTIF */
9898 }
9899 goto OTHER;
9900
9901 case ButtonPress:
9902 case ButtonRelease:
9903 {
9904 /* If we decide we want to generate an event to be seen
9905 by the rest of Emacs, we put it here. */
9906 struct input_event emacs_event;
9907 int tool_bar_p = 0;
9908
9909 emacs_event.kind = no_event;
9910 bzero (&compose_status, sizeof (compose_status));
9911
9912 if (dpyinfo->grabbed
9913 && last_mouse_frame
9914 && FRAME_LIVE_P (last_mouse_frame))
9915 f = last_mouse_frame;
9916 else
9917 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9918
9919 if (f)
9920 {
9921 /* Is this in the tool-bar? */
9922 if (WINDOWP (f->tool_bar_window)
9923 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
9924 {
9925 Lisp_Object window;
9926 int p, x, y;
9927
9928 x = event.xbutton.x;
9929 y = event.xbutton.y;
9930
9931 /* Set x and y. */
9932 window = window_from_coordinates (f, x, y, &p, 1);
9933 if (EQ (window, f->tool_bar_window))
9934 {
9935 x_handle_tool_bar_click (f, &event.xbutton);
9936 tool_bar_p = 1;
9937 }
9938 }
9939
9940 if (!tool_bar_p)
9941 if (!dpyinfo->x_focus_frame
9942 || f == dpyinfo->x_focus_frame)
9943 construct_mouse_click (&emacs_event, &event, f);
9944 }
9945 else
9946 {
9947 #ifndef USE_TOOLKIT_SCROLL_BARS
9948 struct scroll_bar *bar
9949 = x_window_to_scroll_bar (event.xbutton.window);
9950
9951 if (bar)
9952 x_scroll_bar_handle_click (bar, &event, &emacs_event);
9953 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9954 }
9955
9956 if (event.type == ButtonPress)
9957 {
9958 dpyinfo->grabbed |= (1 << event.xbutton.button);
9959 last_mouse_frame = f;
9960 /* Ignore any mouse motion that happened
9961 before this event; any subsequent mouse-movement
9962 Emacs events should reflect only motion after
9963 the ButtonPress. */
9964 if (f != 0)
9965 f->mouse_moved = 0;
9966
9967 if (!tool_bar_p)
9968 last_tool_bar_item = -1;
9969 }
9970 else
9971 {
9972 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
9973 }
9974
9975 if (numchars >= 1 && emacs_event.kind != no_event)
9976 {
9977 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9978 bufp++;
9979 count++;
9980 numchars--;
9981 }
9982
9983 #ifdef USE_X_TOOLKIT
9984 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9985 /* For a down-event in the menu bar,
9986 don't pass it to Xt right now.
9987 Instead, save it away
9988 and we will pass it to Xt from kbd_buffer_get_event.
9989 That way, we can run some Lisp code first. */
9990 if (f && event.type == ButtonPress
9991 /* Verify the event is really within the menu bar
9992 and not just sent to it due to grabbing. */
9993 && event.xbutton.x >= 0
9994 && event.xbutton.x < f->output_data.x->pixel_width
9995 && event.xbutton.y >= 0
9996 && event.xbutton.y < f->output_data.x->menubar_height
9997 && event.xbutton.same_screen)
9998 {
9999 SET_SAVED_BUTTON_EVENT;
10000 XSETFRAME (last_mouse_press_frame, f);
10001 }
10002 else if (event.type == ButtonPress)
10003 {
10004 last_mouse_press_frame = Qnil;
10005 goto OTHER;
10006 }
10007
10008 #ifdef USE_MOTIF /* This should do not harm for Lucid,
10009 but I am trying to be cautious. */
10010 else if (event.type == ButtonRelease)
10011 {
10012 if (!NILP (last_mouse_press_frame))
10013 {
10014 f = XFRAME (last_mouse_press_frame);
10015 if (f->output_data.x)
10016 SET_SAVED_BUTTON_EVENT;
10017 }
10018 else
10019 goto OTHER;
10020 }
10021 #endif /* USE_MOTIF */
10022 else
10023 goto OTHER;
10024 #endif /* USE_X_TOOLKIT */
10025 }
10026 break;
10027
10028 case CirculateNotify:
10029 goto OTHER;
10030
10031 case CirculateRequest:
10032 goto OTHER;
10033
10034 case VisibilityNotify:
10035 goto OTHER;
10036
10037 case MappingNotify:
10038 /* Someone has changed the keyboard mapping - update the
10039 local cache. */
10040 switch (event.xmapping.request)
10041 {
10042 case MappingModifier:
10043 x_find_modifier_meanings (dpyinfo);
10044 /* This is meant to fall through. */
10045 case MappingKeyboard:
10046 XRefreshKeyboardMapping (&event.xmapping);
10047 }
10048 goto OTHER;
10049
10050 default:
10051 OTHER:
10052 #ifdef USE_X_TOOLKIT
10053 BLOCK_INPUT;
10054 XtDispatchEvent (&event);
10055 UNBLOCK_INPUT;
10056 #endif /* USE_X_TOOLKIT */
10057 break;
10058 }
10059 }
10060 }
10061
10062 out:;
10063
10064 /* On some systems, an X bug causes Emacs to get no more events
10065 when the window is destroyed. Detect that. (1994.) */
10066 if (! event_found)
10067 {
10068 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10069 One XNOOP in 100 loops will make Emacs terminate.
10070 B. Bretthauer, 1994 */
10071 x_noop_count++;
10072 if (x_noop_count >= 100)
10073 {
10074 x_noop_count=0;
10075
10076 if (next_noop_dpyinfo == 0)
10077 next_noop_dpyinfo = x_display_list;
10078
10079 XNoOp (next_noop_dpyinfo->display);
10080
10081 /* Each time we get here, cycle through the displays now open. */
10082 next_noop_dpyinfo = next_noop_dpyinfo->next;
10083 }
10084 }
10085
10086 /* If the focus was just given to an auto-raising frame,
10087 raise it now. */
10088 /* ??? This ought to be able to handle more than one such frame. */
10089 if (pending_autoraise_frame)
10090 {
10091 x_raise_frame (pending_autoraise_frame);
10092 pending_autoraise_frame = 0;
10093 }
10094
10095 UNBLOCK_INPUT;
10096 --handling_signal;
10097 return count;
10098 }
10099
10100
10101
10102 \f
10103 /***********************************************************************
10104 Text Cursor
10105 ***********************************************************************/
10106
10107 /* Note if the text cursor of window W has been overwritten by a
10108 drawing operation that outputs N glyphs starting at HPOS in the
10109 line given by output_cursor.vpos. N < 0 means all the rest of the
10110 line after HPOS has been written. */
10111
10112 static void
10113 note_overwritten_text_cursor (w, hpos, n)
10114 struct window *w;
10115 int hpos, n;
10116 {
10117 if (updated_area == TEXT_AREA
10118 && output_cursor.vpos == w->phys_cursor.vpos
10119 && hpos <= w->phys_cursor.hpos
10120 && (n < 0
10121 || hpos + n > w->phys_cursor.hpos))
10122 w->phys_cursor_on_p = 0;
10123 }
10124
10125
10126 /* Set clipping for output in glyph row ROW. W is the window in which
10127 we operate. GC is the graphics context to set clipping in.
10128 WHOLE_LINE_P non-zero means include the areas used for truncation
10129 mark display and alike in the clipping rectangle.
10130
10131 ROW may be a text row or, e.g., a mode line. Text rows must be
10132 clipped to the interior of the window dedicated to text display,
10133 mode lines must be clipped to the whole window. */
10134
10135 static void
10136 x_clip_to_row (w, row, gc, whole_line_p)
10137 struct window *w;
10138 struct glyph_row *row;
10139 GC gc;
10140 int whole_line_p;
10141 {
10142 struct frame *f = XFRAME (WINDOW_FRAME (w));
10143 XRectangle clip_rect;
10144 int window_x, window_y, window_width, window_height;
10145
10146 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
10147
10148 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10149 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10150 clip_rect.y = max (clip_rect.y, window_y);
10151 clip_rect.width = window_width;
10152 clip_rect.height = row->visible_height;
10153
10154 /* If clipping to the whole line, including trunc marks, extend
10155 the rectangle to the left and increase its width. */
10156 if (whole_line_p)
10157 {
10158 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10159 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
10160 }
10161
10162 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
10163 }
10164
10165
10166 /* Draw a hollow box cursor on window W in glyph row ROW. */
10167
10168 static void
10169 x_draw_hollow_cursor (w, row)
10170 struct window *w;
10171 struct glyph_row *row;
10172 {
10173 struct frame *f = XFRAME (WINDOW_FRAME (w));
10174 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10175 Display *dpy = FRAME_X_DISPLAY (f);
10176 int x, y, wd, h;
10177 XGCValues xgcv;
10178 struct glyph *cursor_glyph;
10179 GC gc;
10180
10181 /* Compute frame-relative coordinates from window-relative
10182 coordinates. */
10183 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10184 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10185 + row->ascent - w->phys_cursor_ascent);
10186 h = row->height - 1;
10187
10188 /* Get the glyph the cursor is on. If we can't tell because
10189 the current matrix is invalid or such, give up. */
10190 cursor_glyph = get_phys_cursor_glyph (w);
10191 if (cursor_glyph == NULL)
10192 return;
10193
10194 /* Compute the width of the rectangle to draw. If on a stretch
10195 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10196 rectangle as wide as the glyph, but use a canonical character
10197 width instead. */
10198 wd = cursor_glyph->pixel_width - 1;
10199 if (cursor_glyph->type == STRETCH_GLYPH
10200 && !x_stretch_cursor_p)
10201 wd = min (CANON_X_UNIT (f), wd);
10202
10203 /* The foreground of cursor_gc is typically the same as the normal
10204 background color, which can cause the cursor box to be invisible. */
10205 xgcv.foreground = f->output_data.x->cursor_pixel;
10206 if (dpyinfo->scratch_cursor_gc)
10207 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10208 else
10209 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10210 GCForeground, &xgcv);
10211 gc = dpyinfo->scratch_cursor_gc;
10212
10213 /* Set clipping, draw the rectangle, and reset clipping again. */
10214 x_clip_to_row (w, row, gc, 0);
10215 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10216 XSetClipMask (dpy, gc, None);
10217 }
10218
10219
10220 /* Draw a bar cursor on window W in glyph row ROW.
10221
10222 Implementation note: One would like to draw a bar cursor with an
10223 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10224 Unfortunately, I didn't find a font yet that has this property set.
10225 --gerd. */
10226
10227 static void
10228 x_draw_bar_cursor (w, row, width)
10229 struct window *w;
10230 struct glyph_row *row;
10231 int width;
10232 {
10233 /* If cursor hpos is out of bounds, don't draw garbage. This can
10234 happen in mini-buffer windows when switching between echo area
10235 glyphs and mini-buffer. */
10236 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10237 {
10238 struct frame *f = XFRAME (w->frame);
10239 struct glyph *cursor_glyph;
10240 GC gc;
10241 int x;
10242 unsigned long mask;
10243 XGCValues xgcv;
10244 Display *dpy;
10245 Window window;
10246
10247 cursor_glyph = get_phys_cursor_glyph (w);
10248 if (cursor_glyph == NULL)
10249 return;
10250
10251 xgcv.background = f->output_data.x->cursor_pixel;
10252 xgcv.foreground = f->output_data.x->cursor_pixel;
10253 xgcv.graphics_exposures = 0;
10254 mask = GCForeground | GCBackground | GCGraphicsExposures;
10255 dpy = FRAME_X_DISPLAY (f);
10256 window = FRAME_X_WINDOW (f);
10257 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10258
10259 if (gc)
10260 XChangeGC (dpy, gc, mask, &xgcv);
10261 else
10262 {
10263 gc = XCreateGC (dpy, window, mask, &xgcv);
10264 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10265 }
10266
10267 if (width < 0)
10268 width = f->output_data.x->cursor_width;
10269
10270 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10271 x_clip_to_row (w, row, gc, 0);
10272 XFillRectangle (dpy, window, gc,
10273 x,
10274 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10275 min (cursor_glyph->pixel_width, width),
10276 row->height);
10277 XSetClipMask (dpy, gc, None);
10278 }
10279 }
10280
10281
10282 /* Clear the cursor of window W to background color, and mark the
10283 cursor as not shown. This is used when the text where the cursor
10284 is is about to be rewritten. */
10285
10286 static void
10287 x_clear_cursor (w)
10288 struct window *w;
10289 {
10290 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10291 x_update_window_cursor (w, 0);
10292 }
10293
10294
10295 /* Draw the cursor glyph of window W in glyph row ROW. See the
10296 comment of x_draw_glyphs for the meaning of HL. */
10297
10298 static void
10299 x_draw_phys_cursor_glyph (w, row, hl)
10300 struct window *w;
10301 struct glyph_row *row;
10302 enum draw_glyphs_face hl;
10303 {
10304 /* If cursor hpos is out of bounds, don't draw garbage. This can
10305 happen in mini-buffer windows when switching between echo area
10306 glyphs and mini-buffer. */
10307 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10308 {
10309 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10310 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10311 hl, 0, 0, 0);
10312
10313 /* When we erase the cursor, and ROW is overlapped by other
10314 rows, make sure that these overlapping parts of other rows
10315 are redrawn. */
10316 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10317 {
10318 if (row > w->current_matrix->rows
10319 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10320 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10321
10322 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10323 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10324 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10325 }
10326 }
10327 }
10328
10329
10330 /* Erase the image of a cursor of window W from the screen. */
10331
10332 static void
10333 x_erase_phys_cursor (w)
10334 struct window *w;
10335 {
10336 struct frame *f = XFRAME (w->frame);
10337 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10338 int hpos = w->phys_cursor.hpos;
10339 int vpos = w->phys_cursor.vpos;
10340 int mouse_face_here_p = 0;
10341 struct glyph_matrix *active_glyphs = w->current_matrix;
10342 struct glyph_row *cursor_row;
10343 struct glyph *cursor_glyph;
10344 enum draw_glyphs_face hl;
10345
10346 /* No cursor displayed or row invalidated => nothing to do on the
10347 screen. */
10348 if (w->phys_cursor_type == NO_CURSOR)
10349 goto mark_cursor_off;
10350
10351 /* VPOS >= active_glyphs->nrows means that window has been resized.
10352 Don't bother to erase the cursor. */
10353 if (vpos >= active_glyphs->nrows)
10354 goto mark_cursor_off;
10355
10356 /* If row containing cursor is marked invalid, there is nothing we
10357 can do. */
10358 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10359 if (!cursor_row->enabled_p)
10360 goto mark_cursor_off;
10361
10362 /* This can happen when the new row is shorter than the old one.
10363 In this case, either x_draw_glyphs or clear_end_of_line
10364 should have cleared the cursor. Note that we wouldn't be
10365 able to erase the cursor in this case because we don't have a
10366 cursor glyph at hand. */
10367 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10368 goto mark_cursor_off;
10369
10370 /* If the cursor is in the mouse face area, redisplay that when
10371 we clear the cursor. */
10372 if (! NILP (dpyinfo->mouse_face_window)
10373 && w == XWINDOW (dpyinfo->mouse_face_window)
10374 && (vpos > dpyinfo->mouse_face_beg_row
10375 || (vpos == dpyinfo->mouse_face_beg_row
10376 && hpos >= dpyinfo->mouse_face_beg_col))
10377 && (vpos < dpyinfo->mouse_face_end_row
10378 || (vpos == dpyinfo->mouse_face_end_row
10379 && hpos < dpyinfo->mouse_face_end_col))
10380 /* Don't redraw the cursor's spot in mouse face if it is at the
10381 end of a line (on a newline). The cursor appears there, but
10382 mouse highlighting does not. */
10383 && cursor_row->used[TEXT_AREA] > hpos)
10384 mouse_face_here_p = 1;
10385
10386 /* Maybe clear the display under the cursor. */
10387 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10388 {
10389 int x;
10390 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
10391
10392 cursor_glyph = get_phys_cursor_glyph (w);
10393 if (cursor_glyph == NULL)
10394 goto mark_cursor_off;
10395
10396 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10397
10398 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10399 x,
10400 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10401 cursor_row->y)),
10402 cursor_glyph->pixel_width,
10403 cursor_row->visible_height,
10404 False);
10405 }
10406
10407 /* Erase the cursor by redrawing the character underneath it. */
10408 if (mouse_face_here_p)
10409 hl = DRAW_MOUSE_FACE;
10410 else if (cursor_row->inverse_p)
10411 hl = DRAW_INVERSE_VIDEO;
10412 else
10413 hl = DRAW_NORMAL_TEXT;
10414 x_draw_phys_cursor_glyph (w, cursor_row, hl);
10415
10416 mark_cursor_off:
10417 w->phys_cursor_on_p = 0;
10418 w->phys_cursor_type = NO_CURSOR;
10419 }
10420
10421
10422 /* Display or clear cursor of window W. If ON is zero, clear the
10423 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10424 where to put the cursor is specified by HPOS, VPOS, X and Y. */
10425
10426 void
10427 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10428 struct window *w;
10429 int on, hpos, vpos, x, y;
10430 {
10431 struct frame *f = XFRAME (w->frame);
10432 int new_cursor_type;
10433 int new_cursor_width;
10434 struct glyph_matrix *current_glyphs;
10435 struct glyph_row *glyph_row;
10436 struct glyph *glyph;
10437
10438 /* This is pointless on invisible frames, and dangerous on garbaged
10439 windows and frames; in the latter case, the frame or window may
10440 be in the midst of changing its size, and x and y may be off the
10441 window. */
10442 if (! FRAME_VISIBLE_P (f)
10443 || FRAME_GARBAGED_P (f)
10444 || vpos >= w->current_matrix->nrows
10445 || hpos >= w->current_matrix->matrix_w)
10446 return;
10447
10448 /* If cursor is off and we want it off, return quickly. */
10449 if (!on && !w->phys_cursor_on_p)
10450 return;
10451
10452 current_glyphs = w->current_matrix;
10453 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10454 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10455
10456 /* If cursor row is not enabled, we don't really know where to
10457 display the cursor. */
10458 if (!glyph_row->enabled_p)
10459 {
10460 w->phys_cursor_on_p = 0;
10461 return;
10462 }
10463
10464 xassert (interrupt_input_blocked);
10465
10466 /* Set new_cursor_type to the cursor we want to be displayed. In a
10467 mini-buffer window, we want the cursor only to appear if we are
10468 reading input from this window. For the selected window, we want
10469 the cursor type given by the frame parameter. If explicitly
10470 marked off, draw no cursor. In all other cases, we want a hollow
10471 box cursor. */
10472 new_cursor_width = -1;
10473 if (cursor_in_echo_area
10474 && FRAME_HAS_MINIBUF_P (f)
10475 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
10476 {
10477 if (w == XWINDOW (echo_area_window))
10478 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10479 else
10480 new_cursor_type = HOLLOW_BOX_CURSOR;
10481 }
10482 else
10483 {
10484 if (w != XWINDOW (selected_window)
10485 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10486 {
10487 extern int cursor_in_non_selected_windows;
10488
10489 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
10490 new_cursor_type = NO_CURSOR;
10491 else
10492 new_cursor_type = HOLLOW_BOX_CURSOR;
10493 }
10494 else if (w->cursor_off_p)
10495 new_cursor_type = NO_CURSOR;
10496 else
10497 {
10498 struct buffer *b = XBUFFER (w->buffer);
10499
10500 if (EQ (b->cursor_type, Qt))
10501 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10502 else
10503 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10504 &new_cursor_width);
10505 }
10506 }
10507
10508 /* If cursor is currently being shown and we don't want it to be or
10509 it is in the wrong place, or the cursor type is not what we want,
10510 erase it. */
10511 if (w->phys_cursor_on_p
10512 && (!on
10513 || w->phys_cursor.x != x
10514 || w->phys_cursor.y != y
10515 || new_cursor_type != w->phys_cursor_type))
10516 x_erase_phys_cursor (w);
10517
10518 /* If the cursor is now invisible and we want it to be visible,
10519 display it. */
10520 if (on && !w->phys_cursor_on_p)
10521 {
10522 w->phys_cursor_ascent = glyph_row->ascent;
10523 w->phys_cursor_height = glyph_row->height;
10524
10525 /* Set phys_cursor_.* before x_draw_.* is called because some
10526 of them may need the information. */
10527 w->phys_cursor.x = x;
10528 w->phys_cursor.y = glyph_row->y;
10529 w->phys_cursor.hpos = hpos;
10530 w->phys_cursor.vpos = vpos;
10531 w->phys_cursor_type = new_cursor_type;
10532 w->phys_cursor_on_p = 1;
10533
10534 switch (new_cursor_type)
10535 {
10536 case HOLLOW_BOX_CURSOR:
10537 x_draw_hollow_cursor (w, glyph_row);
10538 break;
10539
10540 case FILLED_BOX_CURSOR:
10541 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10542 break;
10543
10544 case BAR_CURSOR:
10545 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
10546 break;
10547
10548 case NO_CURSOR:
10549 break;
10550
10551 default:
10552 abort ();
10553 }
10554
10555 #ifdef HAVE_X_I18N
10556 if (w == XWINDOW (f->selected_window))
10557 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10558 xic_set_preeditarea (w, x, y);
10559 #endif
10560 }
10561
10562 #ifndef XFlush
10563 if (updating_frame != f)
10564 XFlush (FRAME_X_DISPLAY (f));
10565 #endif
10566 }
10567
10568
10569 /* Display the cursor on window W, or clear it. X and Y are window
10570 relative pixel coordinates. HPOS and VPOS are glyph matrix
10571 positions. If W is not the selected window, display a hollow
10572 cursor. ON non-zero means display the cursor at X, Y which
10573 correspond to HPOS, VPOS, otherwise it is cleared. */
10574
10575 void
10576 x_display_cursor (w, on, hpos, vpos, x, y)
10577 struct window *w;
10578 int on, hpos, vpos, x, y;
10579 {
10580 BLOCK_INPUT;
10581 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
10582 UNBLOCK_INPUT;
10583 }
10584
10585
10586 /* Display the cursor on window W, or clear it, according to ON_P.
10587 Don't change the cursor's position. */
10588
10589 void
10590 x_update_cursor (f, on_p)
10591 struct frame *f;
10592 {
10593 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10594 }
10595
10596
10597 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
10598 in the window tree rooted at W. */
10599
10600 static void
10601 x_update_cursor_in_window_tree (w, on_p)
10602 struct window *w;
10603 int on_p;
10604 {
10605 while (w)
10606 {
10607 if (!NILP (w->hchild))
10608 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10609 else if (!NILP (w->vchild))
10610 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10611 else
10612 x_update_window_cursor (w, on_p);
10613
10614 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10615 }
10616 }
10617
10618
10619 /* Switch the display of W's cursor on or off, according to the value
10620 of ON. */
10621
10622 static void
10623 x_update_window_cursor (w, on)
10624 struct window *w;
10625 int on;
10626 {
10627 /* Don't update cursor in windows whose frame is in the process
10628 of being deleted. */
10629 if (w->current_matrix)
10630 {
10631 BLOCK_INPUT;
10632 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10633 w->phys_cursor.x, w->phys_cursor.y);
10634 UNBLOCK_INPUT;
10635 }
10636 }
10637
10638
10639
10640 \f
10641 /* Icons. */
10642
10643 /* Refresh bitmap kitchen sink icon for frame F
10644 when we get an expose event for it. */
10645
10646 void
10647 refreshicon (f)
10648 struct frame *f;
10649 {
10650 /* Normally, the window manager handles this function. */
10651 }
10652
10653 /* Make the x-window of frame F use the gnu icon bitmap. */
10654
10655 int
10656 x_bitmap_icon (f, file)
10657 struct frame *f;
10658 Lisp_Object file;
10659 {
10660 int bitmap_id;
10661
10662 if (FRAME_X_WINDOW (f) == 0)
10663 return 1;
10664
10665 /* Free up our existing icon bitmap if any. */
10666 if (f->output_data.x->icon_bitmap > 0)
10667 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10668 f->output_data.x->icon_bitmap = 0;
10669
10670 if (STRINGP (file))
10671 bitmap_id = x_create_bitmap_from_file (f, file);
10672 else
10673 {
10674 /* Create the GNU bitmap if necessary. */
10675 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
10676 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10677 = x_create_bitmap_from_data (f, gnu_bits,
10678 gnu_width, gnu_height);
10679
10680 /* The first time we create the GNU bitmap,
10681 this increments the ref-count one extra time.
10682 As a result, the GNU bitmap is never freed.
10683 That way, we don't have to worry about allocating it again. */
10684 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
10685
10686 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
10687 }
10688
10689 x_wm_set_icon_pixmap (f, bitmap_id);
10690 f->output_data.x->icon_bitmap = bitmap_id;
10691
10692 return 0;
10693 }
10694
10695
10696 /* Make the x-window of frame F use a rectangle with text.
10697 Use ICON_NAME as the text. */
10698
10699 int
10700 x_text_icon (f, icon_name)
10701 struct frame *f;
10702 char *icon_name;
10703 {
10704 if (FRAME_X_WINDOW (f) == 0)
10705 return 1;
10706
10707 #ifdef HAVE_X11R4
10708 {
10709 XTextProperty text;
10710 text.value = (unsigned char *) icon_name;
10711 text.encoding = XA_STRING;
10712 text.format = 8;
10713 text.nitems = strlen (icon_name);
10714 #ifdef USE_X_TOOLKIT
10715 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
10716 &text);
10717 #else /* not USE_X_TOOLKIT */
10718 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10719 #endif /* not USE_X_TOOLKIT */
10720 }
10721 #else /* not HAVE_X11R4 */
10722 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10723 #endif /* not HAVE_X11R4 */
10724
10725 if (f->output_data.x->icon_bitmap > 0)
10726 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10727 f->output_data.x->icon_bitmap = 0;
10728 x_wm_set_icon_pixmap (f, 0);
10729
10730 return 0;
10731 }
10732 \f
10733 #define X_ERROR_MESSAGE_SIZE 200
10734
10735 /* If non-nil, this should be a string.
10736 It means catch X errors and store the error message in this string. */
10737
10738 static Lisp_Object x_error_message_string;
10739
10740 /* An X error handler which stores the error message in
10741 x_error_message_string. This is called from x_error_handler if
10742 x_catch_errors is in effect. */
10743
10744 static void
10745 x_error_catcher (display, error)
10746 Display *display;
10747 XErrorEvent *error;
10748 {
10749 XGetErrorText (display, error->error_code,
10750 XSTRING (x_error_message_string)->data,
10751 X_ERROR_MESSAGE_SIZE);
10752 }
10753
10754 /* Begin trapping X errors for display DPY. Actually we trap X errors
10755 for all displays, but DPY should be the display you are actually
10756 operating on.
10757
10758 After calling this function, X protocol errors no longer cause
10759 Emacs to exit; instead, they are recorded in the string
10760 stored in x_error_message_string.
10761
10762 Calling x_check_errors signals an Emacs error if an X error has
10763 occurred since the last call to x_catch_errors or x_check_errors.
10764
10765 Calling x_uncatch_errors resumes the normal error handling. */
10766
10767 void x_check_errors ();
10768 static Lisp_Object x_catch_errors_unwind ();
10769
10770 int
10771 x_catch_errors (dpy)
10772 Display *dpy;
10773 {
10774 int count = specpdl_ptr - specpdl;
10775
10776 /* Make sure any errors from previous requests have been dealt with. */
10777 XSync (dpy, False);
10778
10779 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10780
10781 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10782 XSTRING (x_error_message_string)->data[0] = 0;
10783
10784 return count;
10785 }
10786
10787 /* Unbind the binding that we made to check for X errors. */
10788
10789 static Lisp_Object
10790 x_catch_errors_unwind (old_val)
10791 Lisp_Object old_val;
10792 {
10793 x_error_message_string = old_val;
10794 return Qnil;
10795 }
10796
10797 /* If any X protocol errors have arrived since the last call to
10798 x_catch_errors or x_check_errors, signal an Emacs error using
10799 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10800
10801 void
10802 x_check_errors (dpy, format)
10803 Display *dpy;
10804 char *format;
10805 {
10806 /* Make sure to catch any errors incurred so far. */
10807 XSync (dpy, False);
10808
10809 if (XSTRING (x_error_message_string)->data[0])
10810 error (format, XSTRING (x_error_message_string)->data);
10811 }
10812
10813 /* Nonzero if we had any X protocol errors
10814 since we did x_catch_errors on DPY. */
10815
10816 int
10817 x_had_errors_p (dpy)
10818 Display *dpy;
10819 {
10820 /* Make sure to catch any errors incurred so far. */
10821 XSync (dpy, False);
10822
10823 return XSTRING (x_error_message_string)->data[0] != 0;
10824 }
10825
10826 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10827
10828 void
10829 x_clear_errors (dpy)
10830 Display *dpy;
10831 {
10832 XSTRING (x_error_message_string)->data[0] = 0;
10833 }
10834
10835 /* Stop catching X protocol errors and let them make Emacs die.
10836 DPY should be the display that was passed to x_catch_errors.
10837 COUNT should be the value that was returned by
10838 the corresponding call to x_catch_errors. */
10839
10840 void
10841 x_uncatch_errors (dpy, count)
10842 Display *dpy;
10843 int count;
10844 {
10845 unbind_to (count, Qnil);
10846 }
10847
10848 #if 0
10849 static unsigned int x_wire_count;
10850 x_trace_wire ()
10851 {
10852 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10853 }
10854 #endif /* ! 0 */
10855
10856 \f
10857 /* Handle SIGPIPE, which can happen when the connection to a server
10858 simply goes away. SIGPIPE is handled by x_connection_signal.
10859 Don't need to do anything, because the write which caused the
10860 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
10861 which will do the appropriate cleanup for us. */
10862
10863 static SIGTYPE
10864 x_connection_signal (signalnum) /* If we don't have an argument, */
10865 int signalnum; /* some compilers complain in signal calls. */
10866 {
10867 #ifdef USG
10868 /* USG systems forget handlers when they are used;
10869 must reestablish each time */
10870 signal (signalnum, x_connection_signal);
10871 #endif /* USG */
10872 }
10873 \f
10874 /* Handling X errors. */
10875
10876 /* Handle the loss of connection to display DISPLAY. */
10877
10878 static SIGTYPE
10879 x_connection_closed (display, error_message)
10880 Display *display;
10881 char *error_message;
10882 {
10883 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10884 Lisp_Object frame, tail;
10885
10886 /* Indicate that this display is dead. */
10887
10888 #if 0 /* Closing the display caused a bus error on OpenWindows. */
10889 #ifdef USE_X_TOOLKIT
10890 XtCloseDisplay (display);
10891 #endif
10892 #endif
10893
10894 if (dpyinfo)
10895 dpyinfo->display = 0;
10896
10897 /* First delete frames whose mini-buffers are on frames
10898 that are on the dead display. */
10899 FOR_EACH_FRAME (tail, frame)
10900 {
10901 Lisp_Object minibuf_frame;
10902 minibuf_frame
10903 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
10904 if (FRAME_X_P (XFRAME (frame))
10905 && FRAME_X_P (XFRAME (minibuf_frame))
10906 && ! EQ (frame, minibuf_frame)
10907 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
10908 Fdelete_frame (frame, Qt);
10909 }
10910
10911 /* Now delete all remaining frames on the dead display.
10912 We are now sure none of these is used as the mini-buffer
10913 for another frame that we need to delete. */
10914 FOR_EACH_FRAME (tail, frame)
10915 if (FRAME_X_P (XFRAME (frame))
10916 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
10917 {
10918 /* Set this to t so that Fdelete_frame won't get confused
10919 trying to find a replacement. */
10920 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10921 Fdelete_frame (frame, Qt);
10922 }
10923
10924 if (dpyinfo)
10925 x_delete_display (dpyinfo);
10926
10927 if (x_display_list == 0)
10928 {
10929 fprintf (stderr, "%s\n", error_message);
10930 shut_down_emacs (0, 0, Qnil);
10931 exit (70);
10932 }
10933
10934 /* Ordinary stack unwind doesn't deal with these. */
10935 #ifdef SIGIO
10936 sigunblock (sigmask (SIGIO));
10937 #endif
10938 sigunblock (sigmask (SIGALRM));
10939 TOTALLY_UNBLOCK_INPUT;
10940
10941 clear_waiting_for_input ();
10942 error ("%s", error_message);
10943 }
10944
10945 /* This is the usual handler for X protocol errors.
10946 It kills all frames on the display that we got the error for.
10947 If that was the only one, it prints an error message and kills Emacs. */
10948
10949 static void
10950 x_error_quitter (display, error)
10951 Display *display;
10952 XErrorEvent *error;
10953 {
10954 char buf[256], buf1[356];
10955
10956 /* Note that there is no real way portable across R3/R4 to get the
10957 original error handler. */
10958
10959 XGetErrorText (display, error->error_code, buf, sizeof (buf));
10960 sprintf (buf1, "X protocol error: %s on protocol request %d",
10961 buf, error->request_code);
10962 x_connection_closed (display, buf1);
10963 }
10964
10965 /* This is the first-level handler for X protocol errors.
10966 It calls x_error_quitter or x_error_catcher. */
10967
10968 static int
10969 x_error_handler (display, error)
10970 Display *display;
10971 XErrorEvent *error;
10972 {
10973 if (! NILP (x_error_message_string))
10974 x_error_catcher (display, error);
10975 else
10976 x_error_quitter (display, error);
10977 return 0;
10978 }
10979
10980 /* This is the handler for X IO errors, always.
10981 It kills all frames on the display that we lost touch with.
10982 If that was the only one, it prints an error message and kills Emacs. */
10983
10984 static int
10985 x_io_error_quitter (display)
10986 Display *display;
10987 {
10988 char buf[256];
10989
10990 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10991 x_connection_closed (display, buf);
10992 return 0;
10993 }
10994 \f
10995 /* Changing the font of the frame. */
10996
10997 /* Give frame F the font named FONTNAME as its default font, and
10998 return the full name of that font. FONTNAME may be a wildcard
10999 pattern; in that case, we choose some font that fits the pattern.
11000 The return value shows which font we chose. */
11001
11002 Lisp_Object
11003 x_new_font (f, fontname)
11004 struct frame *f;
11005 register char *fontname;
11006 {
11007 struct font_info *fontp
11008 = FS_LOAD_FONT (f, 0, fontname, -1);
11009
11010 if (!fontp)
11011 return Qnil;
11012
11013 f->output_data.x->font = (XFontStruct *) (fontp->font);
11014 f->output_data.x->baseline_offset = fontp->baseline_offset;
11015 f->output_data.x->fontset = -1;
11016
11017 /* Compute the scroll bar width in character columns. */
11018 if (f->scroll_bar_pixel_width > 0)
11019 {
11020 int wid = FONT_WIDTH (f->output_data.x->font);
11021 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11022 }
11023 else
11024 {
11025 int wid = FONT_WIDTH (f->output_data.x->font);
11026 f->scroll_bar_cols = (14 + wid - 1) / wid;
11027 }
11028
11029 /* Now make the frame display the given font. */
11030 if (FRAME_X_WINDOW (f) != 0)
11031 {
11032 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11033 f->output_data.x->font->fid);
11034 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11035 f->output_data.x->font->fid);
11036 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11037 f->output_data.x->font->fid);
11038
11039 frame_update_line_height (f);
11040 x_set_window_size (f, 0, f->width, f->height);
11041 }
11042 else
11043 /* If we are setting a new frame's font for the first time,
11044 there are no faces yet, so this font's height is the line height. */
11045 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
11046
11047 return build_string (fontp->full_name);
11048 }
11049
11050 /* Give frame F the fontset named FONTSETNAME as its default font, and
11051 return the full name of that fontset. FONTSETNAME may be a wildcard
11052 pattern; in that case, we choose some fontset that fits the pattern.
11053 The return value shows which fontset we chose. */
11054
11055 Lisp_Object
11056 x_new_fontset (f, fontsetname)
11057 struct frame *f;
11058 char *fontsetname;
11059 {
11060 int fontset = fs_query_fontset (build_string (fontsetname), 0);
11061 Lisp_Object result;
11062
11063 if (fontset < 0)
11064 return Qnil;
11065
11066 if (f->output_data.x->fontset == fontset)
11067 /* This fontset is already set in frame F. There's nothing more
11068 to do. */
11069 return fontset_name (fontset);
11070
11071 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
11072
11073 if (!STRINGP (result))
11074 /* Can't load ASCII font. */
11075 return Qnil;
11076
11077 /* Since x_new_font doesn't update any fontset information, do it now. */
11078 f->output_data.x->fontset = fontset;
11079
11080 #ifdef HAVE_X_I18N
11081 if (FRAME_XIC (f)
11082 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
11083 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
11084 #endif
11085
11086 return build_string (fontsetname);
11087 }
11088
11089 \f
11090 /***********************************************************************
11091 X Input Methods
11092 ***********************************************************************/
11093
11094 #ifdef HAVE_X_I18N
11095
11096 #ifdef HAVE_X11R6
11097
11098 /* XIM destroy callback function, which is called whenever the
11099 connection to input method XIM dies. CLIENT_DATA contains a
11100 pointer to the x_display_info structure corresponding to XIM. */
11101
11102 static void
11103 xim_destroy_callback (xim, client_data, call_data)
11104 XIM xim;
11105 XPointer client_data;
11106 XPointer call_data;
11107 {
11108 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11109 Lisp_Object frame, tail;
11110
11111 BLOCK_INPUT;
11112
11113 /* No need to call XDestroyIC.. */
11114 FOR_EACH_FRAME (tail, frame)
11115 {
11116 struct frame *f = XFRAME (frame);
11117 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11118 {
11119 FRAME_XIC (f) = NULL;
11120 if (FRAME_XIC_FONTSET (f))
11121 {
11122 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11123 FRAME_XIC_FONTSET (f) = NULL;
11124 }
11125 }
11126 }
11127
11128 /* No need to call XCloseIM. */
11129 dpyinfo->xim = NULL;
11130 XFree (dpyinfo->xim_styles);
11131 UNBLOCK_INPUT;
11132 }
11133
11134 #endif /* HAVE_X11R6 */
11135
11136 /* Open the connection to the XIM server on display DPYINFO.
11137 RESOURCE_NAME is the resource name Emacs uses. */
11138
11139 static void
11140 xim_open_dpy (dpyinfo, resource_name)
11141 struct x_display_info *dpyinfo;
11142 char *resource_name;
11143 {
11144 #ifdef USE_XIM
11145 XIM xim;
11146
11147 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11148 dpyinfo->xim = xim;
11149
11150 if (xim)
11151 {
11152 #ifdef HAVE_X11R6
11153 XIMCallback destroy;
11154 #endif
11155
11156 /* Get supported styles and XIM values. */
11157 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11158
11159 #ifdef HAVE_X11R6
11160 destroy.callback = xim_destroy_callback;
11161 destroy.client_data = (XPointer)dpyinfo;
11162 /* This isn't prptotyped in OSF 5.0. */
11163 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11164 #endif
11165 }
11166
11167 #else /* not USE_XIM */
11168 dpyinfo->xim = NULL;
11169 #endif /* not USE_XIM */
11170 }
11171
11172
11173 #ifdef HAVE_X11R6_XIM
11174
11175 struct xim_inst_t
11176 {
11177 struct x_display_info *dpyinfo;
11178 char *resource_name;
11179 };
11180
11181 /* XIM instantiate callback function, which is called whenever an XIM
11182 server is available. DISPLAY is teh display of the XIM.
11183 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11184 when the callback was registered. */
11185
11186 static void
11187 xim_instantiate_callback (display, client_data, call_data)
11188 Display *display;
11189 XPointer client_data;
11190 XPointer call_data;
11191 {
11192 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11193 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11194
11195 /* We don't support multiple XIM connections. */
11196 if (dpyinfo->xim)
11197 return;
11198
11199 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11200
11201 /* Create XIC for the existing frames on the same display, as long
11202 as they have no XIC. */
11203 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11204 {
11205 Lisp_Object tail, frame;
11206
11207 BLOCK_INPUT;
11208 FOR_EACH_FRAME (tail, frame)
11209 {
11210 struct frame *f = XFRAME (frame);
11211
11212 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11213 if (FRAME_XIC (f) == NULL)
11214 {
11215 create_frame_xic (f);
11216 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11217 xic_set_statusarea (f);
11218 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11219 {
11220 struct window *w = XWINDOW (f->selected_window);
11221 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11222 }
11223 }
11224 }
11225
11226 UNBLOCK_INPUT;
11227 }
11228 }
11229
11230 #endif /* HAVE_X11R6_XIM */
11231
11232
11233 /* Open a connection to the XIM server on display DPYINFO.
11234 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11235 connection only at the first time. On X11R6, open the connection
11236 in the XIM instantiate callback function. */
11237
11238 static void
11239 xim_initialize (dpyinfo, resource_name)
11240 struct x_display_info *dpyinfo;
11241 char *resource_name;
11242 {
11243 #ifdef USE_XIM
11244 #ifdef HAVE_X11R6_XIM
11245 struct xim_inst_t *xim_inst;
11246 int len;
11247
11248 dpyinfo->xim = NULL;
11249 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11250 xim_inst->dpyinfo = dpyinfo;
11251 len = strlen (resource_name);
11252 xim_inst->resource_name = (char *) xmalloc (len + 1);
11253 bcopy (resource_name, xim_inst->resource_name, len + 1);
11254 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11255 resource_name, EMACS_CLASS,
11256 xim_instantiate_callback,
11257 /* Fixme: This is XPointer in
11258 XFree86 but (XPointer *) on
11259 Tru64, at least. */
11260 (XPointer) xim_inst);
11261 #else /* not HAVE_X11R6_XIM */
11262 dpyinfo->xim = NULL;
11263 xim_open_dpy (dpyinfo, resource_name);
11264 #endif /* not HAVE_X11R6_XIM */
11265
11266 #else /* not USE_XIM */
11267 dpyinfo->xim = NULL;
11268 #endif /* not USE_XIM */
11269 }
11270
11271
11272 /* Close the connection to the XIM server on display DPYINFO. */
11273
11274 static void
11275 xim_close_dpy (dpyinfo)
11276 struct x_display_info *dpyinfo;
11277 {
11278 #ifdef USE_XIM
11279 #ifdef HAVE_X11R6_XIM
11280 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11281 NULL, EMACS_CLASS,
11282 xim_instantiate_callback, NULL);
11283 #endif /* not HAVE_X11R6_XIM */
11284 XCloseIM (dpyinfo->xim);
11285 dpyinfo->xim = NULL;
11286 XFree (dpyinfo->xim_styles);
11287 #endif /* USE_XIM */
11288 }
11289
11290 #endif /* not HAVE_X11R6_XIM */
11291
11292
11293 \f
11294 /* Calculate the absolute position in frame F
11295 from its current recorded position values and gravity. */
11296
11297 void
11298 x_calc_absolute_position (f)
11299 struct frame *f;
11300 {
11301 Window child;
11302 int win_x = 0, win_y = 0;
11303 int flags = f->output_data.x->size_hint_flags;
11304 int this_window;
11305
11306 /* We have nothing to do if the current position
11307 is already for the top-left corner. */
11308 if (! ((flags & XNegative) || (flags & YNegative)))
11309 return;
11310
11311 #ifdef USE_X_TOOLKIT
11312 this_window = XtWindow (f->output_data.x->widget);
11313 #else
11314 this_window = FRAME_X_WINDOW (f);
11315 #endif
11316
11317 /* Find the position of the outside upper-left corner of
11318 the inner window, with respect to the outer window.
11319 But do this only if we will need the results. */
11320 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
11321 {
11322 int count;
11323
11324 BLOCK_INPUT;
11325 count = x_catch_errors (FRAME_X_DISPLAY (f));
11326 while (1)
11327 {
11328 x_clear_errors (FRAME_X_DISPLAY (f));
11329 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11330
11331 /* From-window, to-window. */
11332 this_window,
11333 f->output_data.x->parent_desc,
11334
11335 /* From-position, to-position. */
11336 0, 0, &win_x, &win_y,
11337
11338 /* Child of win. */
11339 &child);
11340 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11341 {
11342 Window newroot, newparent = 0xdeadbeef;
11343 Window *newchildren;
11344 unsigned int nchildren;
11345
11346 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11347 &newparent, &newchildren, &nchildren))
11348 break;
11349
11350 XFree ((char *) newchildren);
11351
11352 f->output_data.x->parent_desc = newparent;
11353 }
11354 else
11355 break;
11356 }
11357
11358 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
11359 UNBLOCK_INPUT;
11360 }
11361
11362 /* Treat negative positions as relative to the leftmost bottommost
11363 position that fits on the screen. */
11364 if (flags & XNegative)
11365 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
11366 - 2 * f->output_data.x->border_width - win_x
11367 - PIXEL_WIDTH (f)
11368 + f->output_data.x->left_pos);
11369
11370 if (flags & YNegative)
11371 {
11372 int menubar_height = 0;
11373
11374 #ifdef USE_X_TOOLKIT
11375 if (f->output_data.x->menubar_widget)
11376 menubar_height
11377 = (f->output_data.x->menubar_widget->core.height
11378 + f->output_data.x->menubar_widget->core.border_width);
11379 #endif
11380
11381 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11382 - 2 * f->output_data.x->border_width
11383 - win_y
11384 - PIXEL_HEIGHT (f)
11385 - menubar_height
11386 + f->output_data.x->top_pos);
11387 }
11388
11389 /* The left_pos and top_pos
11390 are now relative to the top and left screen edges,
11391 so the flags should correspond. */
11392 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11393 }
11394
11395 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11396 to really change the position, and 0 when calling from
11397 x_make_frame_visible (in that case, XOFF and YOFF are the current
11398 position values). It is -1 when calling from x_set_frame_parameters,
11399 which means, do adjust for borders but don't change the gravity. */
11400
11401 void
11402 x_set_offset (f, xoff, yoff, change_gravity)
11403 struct frame *f;
11404 register int xoff, yoff;
11405 int change_gravity;
11406 {
11407 int modified_top, modified_left;
11408
11409 if (change_gravity > 0)
11410 {
11411 f->output_data.x->top_pos = yoff;
11412 f->output_data.x->left_pos = xoff;
11413 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
11414 if (xoff < 0)
11415 f->output_data.x->size_hint_flags |= XNegative;
11416 if (yoff < 0)
11417 f->output_data.x->size_hint_flags |= YNegative;
11418 f->output_data.x->win_gravity = NorthWestGravity;
11419 }
11420 x_calc_absolute_position (f);
11421
11422 BLOCK_INPUT;
11423 x_wm_set_size_hint (f, (long) 0, 0);
11424
11425 modified_left = f->output_data.x->left_pos;
11426 modified_top = f->output_data.x->top_pos;
11427 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11428 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11429 /* It is a mystery why we need to add the border_width here
11430 when the frame is already visible, but experiment says we do. */
11431 if (change_gravity != 0)
11432 {
11433 modified_left += f->output_data.x->border_width;
11434 modified_top += f->output_data.x->border_width;
11435 }
11436 #endif
11437
11438 #ifdef USE_X_TOOLKIT
11439 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
11440 modified_left, modified_top);
11441 #else /* not USE_X_TOOLKIT */
11442 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11443 modified_left, modified_top);
11444 #endif /* not USE_X_TOOLKIT */
11445 UNBLOCK_INPUT;
11446 }
11447
11448 /* Call this to change the size of frame F's x-window.
11449 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11450 for this size change and subsequent size changes.
11451 Otherwise we leave the window gravity unchanged. */
11452
11453 void
11454 x_set_window_size (f, change_gravity, cols, rows)
11455 struct frame *f;
11456 int change_gravity;
11457 int cols, rows;
11458 {
11459 #ifndef USE_X_TOOLKIT
11460 int pixelwidth, pixelheight;
11461 #endif
11462
11463 BLOCK_INPUT;
11464
11465 #ifdef USE_X_TOOLKIT
11466 {
11467 /* The x and y position of the widget is clobbered by the
11468 call to XtSetValues within EmacsFrameSetCharSize.
11469 This is a real kludge, but I don't understand Xt so I can't
11470 figure out a correct fix. Can anyone else tell me? -- rms. */
11471 int xpos = f->output_data.x->widget->core.x;
11472 int ypos = f->output_data.x->widget->core.y;
11473 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11474 f->output_data.x->widget->core.x = xpos;
11475 f->output_data.x->widget->core.y = ypos;
11476 }
11477
11478 #else /* not USE_X_TOOLKIT */
11479
11480 check_frame_size (f, &rows, &cols);
11481 f->output_data.x->vertical_scroll_bar_extra
11482 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11483 ? 0
11484 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
11485 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
11486 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
11487 f->output_data.x->flags_areas_extra
11488 = FRAME_FLAGS_AREA_WIDTH (f);
11489 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11490 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
11491
11492 f->output_data.x->win_gravity = NorthWestGravity;
11493 x_wm_set_size_hint (f, (long) 0, 0);
11494
11495 XSync (FRAME_X_DISPLAY (f), False);
11496 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11497 pixelwidth, pixelheight);
11498
11499 /* Now, strictly speaking, we can't be sure that this is accurate,
11500 but the window manager will get around to dealing with the size
11501 change request eventually, and we'll hear how it went when the
11502 ConfigureNotify event gets here.
11503
11504 We could just not bother storing any of this information here,
11505 and let the ConfigureNotify event set everything up, but that
11506 might be kind of confusing to the Lisp code, since size changes
11507 wouldn't be reported in the frame parameters until some random
11508 point in the future when the ConfigureNotify event arrives.
11509
11510 We pass 1 for DELAY since we can't run Lisp code inside of
11511 a BLOCK_INPUT. */
11512 change_frame_size (f, rows, cols, 0, 1, 0);
11513 PIXEL_WIDTH (f) = pixelwidth;
11514 PIXEL_HEIGHT (f) = pixelheight;
11515
11516 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11517 receive in the ConfigureNotify event; if we get what we asked
11518 for, then the event won't cause the screen to become garbaged, so
11519 we have to make sure to do it here. */
11520 SET_FRAME_GARBAGED (f);
11521
11522 XFlush (FRAME_X_DISPLAY (f));
11523
11524 #endif /* not USE_X_TOOLKIT */
11525
11526 /* If cursor was outside the new size, mark it as off. */
11527 mark_window_cursors_off (XWINDOW (f->root_window));
11528
11529 /* Clear out any recollection of where the mouse highlighting was,
11530 since it might be in a place that's outside the new frame size.
11531 Actually checking whether it is outside is a pain in the neck,
11532 so don't try--just let the highlighting be done afresh with new size. */
11533 cancel_mouse_face (f);
11534
11535 UNBLOCK_INPUT;
11536 }
11537 \f
11538 /* Mouse warping. */
11539
11540 void
11541 x_set_mouse_position (f, x, y)
11542 struct frame *f;
11543 int x, y;
11544 {
11545 int pix_x, pix_y;
11546
11547 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11548 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
11549
11550 if (pix_x < 0) pix_x = 0;
11551 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11552
11553 if (pix_y < 0) pix_y = 0;
11554 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
11555
11556 BLOCK_INPUT;
11557
11558 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11559 0, 0, 0, 0, pix_x, pix_y);
11560 UNBLOCK_INPUT;
11561 }
11562
11563 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11564
11565 void
11566 x_set_mouse_pixel_position (f, pix_x, pix_y)
11567 struct frame *f;
11568 int pix_x, pix_y;
11569 {
11570 BLOCK_INPUT;
11571
11572 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11573 0, 0, 0, 0, pix_x, pix_y);
11574 UNBLOCK_INPUT;
11575 }
11576 \f
11577 /* focus shifting, raising and lowering. */
11578
11579 void
11580 x_focus_on_frame (f)
11581 struct frame *f;
11582 {
11583 #if 0 /* This proves to be unpleasant. */
11584 x_raise_frame (f);
11585 #endif
11586 #if 0
11587 /* I don't think that the ICCCM allows programs to do things like this
11588 without the interaction of the window manager. Whatever you end up
11589 doing with this code, do it to x_unfocus_frame too. */
11590 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11591 RevertToPointerRoot, CurrentTime);
11592 #endif /* ! 0 */
11593 }
11594
11595 void
11596 x_unfocus_frame (f)
11597 struct frame *f;
11598 {
11599 #if 0
11600 /* Look at the remarks in x_focus_on_frame. */
11601 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
11602 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
11603 RevertToPointerRoot, CurrentTime);
11604 #endif /* ! 0 */
11605 }
11606
11607 /* Raise frame F. */
11608
11609 void
11610 x_raise_frame (f)
11611 struct frame *f;
11612 {
11613 if (f->async_visible)
11614 {
11615 BLOCK_INPUT;
11616 #ifdef USE_X_TOOLKIT
11617 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11618 #else /* not USE_X_TOOLKIT */
11619 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11620 #endif /* not USE_X_TOOLKIT */
11621 XFlush (FRAME_X_DISPLAY (f));
11622 UNBLOCK_INPUT;
11623 }
11624 }
11625
11626 /* Lower frame F. */
11627
11628 void
11629 x_lower_frame (f)
11630 struct frame *f;
11631 {
11632 if (f->async_visible)
11633 {
11634 BLOCK_INPUT;
11635 #ifdef USE_X_TOOLKIT
11636 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
11637 #else /* not USE_X_TOOLKIT */
11638 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11639 #endif /* not USE_X_TOOLKIT */
11640 XFlush (FRAME_X_DISPLAY (f));
11641 UNBLOCK_INPUT;
11642 }
11643 }
11644
11645 static void
11646 XTframe_raise_lower (f, raise_flag)
11647 FRAME_PTR f;
11648 int raise_flag;
11649 {
11650 if (raise_flag)
11651 x_raise_frame (f);
11652 else
11653 x_lower_frame (f);
11654 }
11655 \f
11656 /* Change of visibility. */
11657
11658 /* This tries to wait until the frame is really visible.
11659 However, if the window manager asks the user where to position
11660 the frame, this will return before the user finishes doing that.
11661 The frame will not actually be visible at that time,
11662 but it will become visible later when the window manager
11663 finishes with it. */
11664
11665 void
11666 x_make_frame_visible (f)
11667 struct frame *f;
11668 {
11669 Lisp_Object type;
11670 int original_top, original_left;
11671
11672 BLOCK_INPUT;
11673
11674 type = x_icon_type (f);
11675 if (!NILP (type))
11676 x_bitmap_icon (f, type);
11677
11678 if (! FRAME_VISIBLE_P (f))
11679 {
11680 /* We test FRAME_GARBAGED_P here to make sure we don't
11681 call x_set_offset a second time
11682 if we get to x_make_frame_visible a second time
11683 before the window gets really visible. */
11684 if (! FRAME_ICONIFIED_P (f)
11685 && ! f->output_data.x->asked_for_visible)
11686 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11687
11688 f->output_data.x->asked_for_visible = 1;
11689
11690 if (! EQ (Vx_no_window_manager, Qt))
11691 x_wm_set_window_state (f, NormalState);
11692 #ifdef USE_X_TOOLKIT
11693 /* This was XtPopup, but that did nothing for an iconified frame. */
11694 XtMapWidget (f->output_data.x->widget);
11695 #else /* not USE_X_TOOLKIT */
11696 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11697 #endif /* not USE_X_TOOLKIT */
11698 #if 0 /* This seems to bring back scroll bars in the wrong places
11699 if the window configuration has changed. They seem
11700 to come back ok without this. */
11701 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
11702 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11703 #endif
11704 }
11705
11706 XFlush (FRAME_X_DISPLAY (f));
11707
11708 /* Synchronize to ensure Emacs knows the frame is visible
11709 before we do anything else. We do this loop with input not blocked
11710 so that incoming events are handled. */
11711 {
11712 Lisp_Object frame;
11713 int count;
11714 /* This must be before UNBLOCK_INPUT
11715 since events that arrive in response to the actions above
11716 will set it when they are handled. */
11717 int previously_visible = f->output_data.x->has_been_visible;
11718
11719 original_left = f->output_data.x->left_pos;
11720 original_top = f->output_data.x->top_pos;
11721
11722 /* This must come after we set COUNT. */
11723 UNBLOCK_INPUT;
11724
11725 /* We unblock here so that arriving X events are processed. */
11726
11727 /* Now move the window back to where it was "supposed to be".
11728 But don't do it if the gravity is negative.
11729 When the gravity is negative, this uses a position
11730 that is 3 pixels too low. Perhaps that's really the border width.
11731
11732 Don't do this if the window has never been visible before,
11733 because the window manager may choose the position
11734 and we don't want to override it. */
11735
11736 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
11737 && f->output_data.x->win_gravity == NorthWestGravity
11738 && previously_visible)
11739 {
11740 Drawable rootw;
11741 int x, y;
11742 unsigned int width, height, border, depth;
11743
11744 BLOCK_INPUT;
11745
11746 /* On some window managers (such as FVWM) moving an existing
11747 window, even to the same place, causes the window manager
11748 to introduce an offset. This can cause the window to move
11749 to an unexpected location. Check the geometry (a little
11750 slow here) and then verify that the window is in the right
11751 place. If the window is not in the right place, move it
11752 there, and take the potential window manager hit. */
11753 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11754 &rootw, &x, &y, &width, &height, &border, &depth);
11755
11756 if (original_left != x || original_top != y)
11757 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11758 original_left, original_top);
11759
11760 UNBLOCK_INPUT;
11761 }
11762
11763 XSETFRAME (frame, f);
11764
11765 /* Wait until the frame is visible. Process X events until a
11766 MapNotify event has been seen, or until we think we won't get a
11767 MapNotify at all.. */
11768 for (count = input_signal_count + 10;
11769 input_signal_count < count && !FRAME_VISIBLE_P (f);)
11770 {
11771 /* Force processing of queued events. */
11772 x_sync (f);
11773
11774 /* Machines that do polling rather than SIGIO have been
11775 observed to go into a busy-wait here. So we'll fake an
11776 alarm signal to let the handler know that there's something
11777 to be read. We used to raise a real alarm, but it seems
11778 that the handler isn't always enabled here. This is
11779 probably a bug. */
11780 if (input_polling_used ())
11781 {
11782 /* It could be confusing if a real alarm arrives while
11783 processing the fake one. Turn it off and let the
11784 handler reset it. */
11785 extern void poll_for_input_1 P_ ((void));
11786 int old_poll_suppress_count = poll_suppress_count;
11787 poll_suppress_count = 1;
11788 poll_for_input_1 ();
11789 poll_suppress_count = old_poll_suppress_count;
11790 }
11791
11792 /* See if a MapNotify event has been processed. */
11793 FRAME_SAMPLE_VISIBILITY (f);
11794 }
11795 }
11796 }
11797
11798 /* Change from mapped state to withdrawn state. */
11799
11800 /* Make the frame visible (mapped and not iconified). */
11801
11802 void
11803 x_make_frame_invisible (f)
11804 struct frame *f;
11805 {
11806 Window window;
11807
11808 #ifdef USE_X_TOOLKIT
11809 /* Use the frame's outermost window, not the one we normally draw on. */
11810 window = XtWindow (f->output_data.x->widget);
11811 #else /* not USE_X_TOOLKIT */
11812 window = FRAME_X_WINDOW (f);
11813 #endif /* not USE_X_TOOLKIT */
11814
11815 /* Don't keep the highlight on an invisible frame. */
11816 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11817 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11818
11819 #if 0/* This might add unreliability; I don't trust it -- rms. */
11820 if (! f->async_visible && ! f->async_iconified)
11821 return;
11822 #endif
11823
11824 BLOCK_INPUT;
11825
11826 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11827 that the current position of the window is user-specified, rather than
11828 program-specified, so that when the window is mapped again, it will be
11829 placed at the same location, without forcing the user to position it
11830 by hand again (they have already done that once for this window.) */
11831 x_wm_set_size_hint (f, (long) 0, 1);
11832
11833 #ifdef HAVE_X11R4
11834
11835 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11836 DefaultScreen (FRAME_X_DISPLAY (f))))
11837 {
11838 UNBLOCK_INPUT_RESIGNAL;
11839 error ("Can't notify window manager of window withdrawal");
11840 }
11841 #else /* ! defined (HAVE_X11R4) */
11842
11843 /* Tell the window manager what we're going to do. */
11844 if (! EQ (Vx_no_window_manager, Qt))
11845 {
11846 XEvent unmap;
11847
11848 unmap.xunmap.type = UnmapNotify;
11849 unmap.xunmap.window = window;
11850 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
11851 unmap.xunmap.from_configure = False;
11852 if (! XSendEvent (FRAME_X_DISPLAY (f),
11853 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11854 False,
11855 SubstructureRedirectMaskSubstructureNotifyMask,
11856 &unmap))
11857 {
11858 UNBLOCK_INPUT_RESIGNAL;
11859 error ("Can't notify window manager of withdrawal");
11860 }
11861 }
11862
11863 /* Unmap the window ourselves. Cheeky! */
11864 XUnmapWindow (FRAME_X_DISPLAY (f), window);
11865 #endif /* ! defined (HAVE_X11R4) */
11866
11867 /* We can't distinguish this from iconification
11868 just by the event that we get from the server.
11869 So we can't win using the usual strategy of letting
11870 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11871 and synchronize with the server to make sure we agree. */
11872 f->visible = 0;
11873 FRAME_ICONIFIED_P (f) = 0;
11874 f->async_visible = 0;
11875 f->async_iconified = 0;
11876
11877 x_sync (f);
11878
11879 UNBLOCK_INPUT;
11880 }
11881
11882 /* Change window state from mapped to iconified. */
11883
11884 void
11885 x_iconify_frame (f)
11886 struct frame *f;
11887 {
11888 int result;
11889 Lisp_Object type;
11890
11891 /* Don't keep the highlight on an invisible frame. */
11892 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11893 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
11894
11895 if (f->async_iconified)
11896 return;
11897
11898 BLOCK_INPUT;
11899
11900 FRAME_SAMPLE_VISIBILITY (f);
11901
11902 type = x_icon_type (f);
11903 if (!NILP (type))
11904 x_bitmap_icon (f, type);
11905
11906 #ifdef USE_X_TOOLKIT
11907
11908 if (! FRAME_VISIBLE_P (f))
11909 {
11910 if (! EQ (Vx_no_window_manager, Qt))
11911 x_wm_set_window_state (f, IconicState);
11912 /* This was XtPopup, but that did nothing for an iconified frame. */
11913 XtMapWidget (f->output_data.x->widget);
11914 /* The server won't give us any event to indicate
11915 that an invisible frame was changed to an icon,
11916 so we have to record it here. */
11917 f->iconified = 1;
11918 f->visible = 1;
11919 f->async_iconified = 1;
11920 f->async_visible = 0;
11921 UNBLOCK_INPUT;
11922 return;
11923 }
11924
11925 result = XIconifyWindow (FRAME_X_DISPLAY (f),
11926 XtWindow (f->output_data.x->widget),
11927 DefaultScreen (FRAME_X_DISPLAY (f)));
11928 UNBLOCK_INPUT;
11929
11930 if (!result)
11931 error ("Can't notify window manager of iconification");
11932
11933 f->async_iconified = 1;
11934 f->async_visible = 0;
11935
11936
11937 BLOCK_INPUT;
11938 XFlush (FRAME_X_DISPLAY (f));
11939 UNBLOCK_INPUT;
11940 #else /* not USE_X_TOOLKIT */
11941
11942 /* Make sure the X server knows where the window should be positioned,
11943 in case the user deiconifies with the window manager. */
11944 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
11945 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11946
11947 /* Since we don't know which revision of X we're running, we'll use both
11948 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11949
11950 /* X11R4: send a ClientMessage to the window manager using the
11951 WM_CHANGE_STATE type. */
11952 {
11953 XEvent message;
11954
11955 message.xclient.window = FRAME_X_WINDOW (f);
11956 message.xclient.type = ClientMessage;
11957 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
11958 message.xclient.format = 32;
11959 message.xclient.data.l[0] = IconicState;
11960
11961 if (! XSendEvent (FRAME_X_DISPLAY (f),
11962 DefaultRootWindow (FRAME_X_DISPLAY (f)),
11963 False,
11964 SubstructureRedirectMask | SubstructureNotifyMask,
11965 &message))
11966 {
11967 UNBLOCK_INPUT_RESIGNAL;
11968 error ("Can't notify window manager of iconification");
11969 }
11970 }
11971
11972 /* X11R3: set the initial_state field of the window manager hints to
11973 IconicState. */
11974 x_wm_set_window_state (f, IconicState);
11975
11976 if (!FRAME_VISIBLE_P (f))
11977 {
11978 /* If the frame was withdrawn, before, we must map it. */
11979 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11980 }
11981
11982 f->async_iconified = 1;
11983 f->async_visible = 0;
11984
11985 XFlush (FRAME_X_DISPLAY (f));
11986 UNBLOCK_INPUT;
11987 #endif /* not USE_X_TOOLKIT */
11988 }
11989 \f
11990 /* Destroy the X window of frame F. */
11991
11992 void
11993 x_destroy_window (f)
11994 struct frame *f;
11995 {
11996 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11997
11998 BLOCK_INPUT;
11999
12000 /* If a display connection is dead, don't try sending more
12001 commands to the X server. */
12002 if (dpyinfo->display != 0)
12003 {
12004 if (f->output_data.x->icon_desc != 0)
12005 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
12006 #ifdef HAVE_X_I18N
12007 if (FRAME_XIC (f))
12008 free_frame_xic (f);
12009 #endif
12010 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
12011 #ifdef USE_X_TOOLKIT
12012 if (f->output_data.x->widget)
12013 XtDestroyWidget (f->output_data.x->widget);
12014 free_frame_menubar (f);
12015 #endif /* USE_X_TOOLKIT */
12016
12017 unload_color (f, f->output_data.x->foreground_pixel);
12018 unload_color (f, f->output_data.x->background_pixel);
12019 unload_color (f, f->output_data.x->cursor_pixel);
12020 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12021 unload_color (f, f->output_data.x->border_pixel);
12022 unload_color (f, f->output_data.x->mouse_pixel);
12023 if (f->output_data.x->scroll_bar_background_pixel != -1)
12024 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12025 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12026 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12027 if (f->output_data.x->white_relief.allocated_p)
12028 unload_color (f, f->output_data.x->white_relief.pixel);
12029 if (f->output_data.x->black_relief.allocated_p)
12030 unload_color (f, f->output_data.x->black_relief.pixel);
12031
12032 free_frame_faces (f);
12033 XFlush (FRAME_X_DISPLAY (f));
12034 }
12035
12036 if (f->output_data.x->saved_menu_event)
12037 xfree (f->output_data.x->saved_menu_event);
12038
12039 xfree (f->output_data.x);
12040 f->output_data.x = 0;
12041 if (f == dpyinfo->x_focus_frame)
12042 dpyinfo->x_focus_frame = 0;
12043 if (f == dpyinfo->x_focus_event_frame)
12044 dpyinfo->x_focus_event_frame = 0;
12045 if (f == dpyinfo->x_highlight_frame)
12046 dpyinfo->x_highlight_frame = 0;
12047
12048 dpyinfo->reference_count--;
12049
12050 if (f == dpyinfo->mouse_face_mouse_frame)
12051 {
12052 dpyinfo->mouse_face_beg_row
12053 = dpyinfo->mouse_face_beg_col = -1;
12054 dpyinfo->mouse_face_end_row
12055 = dpyinfo->mouse_face_end_col = -1;
12056 dpyinfo->mouse_face_window = Qnil;
12057 dpyinfo->mouse_face_deferred_gc = 0;
12058 dpyinfo->mouse_face_mouse_frame = 0;
12059 }
12060
12061 UNBLOCK_INPUT;
12062 }
12063 \f
12064 /* Setting window manager hints. */
12065
12066 /* Set the normal size hints for the window manager, for frame F.
12067 FLAGS is the flags word to use--or 0 meaning preserve the flags
12068 that the window now has.
12069 If USER_POSITION is nonzero, we set the USPosition
12070 flag (this is useful when FLAGS is 0). */
12071
12072 void
12073 x_wm_set_size_hint (f, flags, user_position)
12074 struct frame *f;
12075 long flags;
12076 int user_position;
12077 {
12078 XSizeHints size_hints;
12079
12080 #ifdef USE_X_TOOLKIT
12081 Arg al[2];
12082 int ac = 0;
12083 Dimension widget_width, widget_height;
12084 Window window = XtWindow (f->output_data.x->widget);
12085 #else /* not USE_X_TOOLKIT */
12086 Window window = FRAME_X_WINDOW (f);
12087 #endif /* not USE_X_TOOLKIT */
12088
12089 /* Setting PMaxSize caused various problems. */
12090 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
12091
12092 size_hints.x = f->output_data.x->left_pos;
12093 size_hints.y = f->output_data.x->top_pos;
12094
12095 #ifdef USE_X_TOOLKIT
12096 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12097 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
12098 XtGetValues (f->output_data.x->widget, al, ac);
12099 size_hints.height = widget_height;
12100 size_hints.width = widget_width;
12101 #else /* not USE_X_TOOLKIT */
12102 size_hints.height = PIXEL_HEIGHT (f);
12103 size_hints.width = PIXEL_WIDTH (f);
12104 #endif /* not USE_X_TOOLKIT */
12105
12106 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12107 size_hints.height_inc = f->output_data.x->line_height;
12108 size_hints.max_width
12109 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12110 size_hints.max_height
12111 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
12112
12113 /* Calculate the base and minimum sizes.
12114
12115 (When we use the X toolkit, we don't do it here.
12116 Instead we copy the values that the widgets are using, below.) */
12117 #ifndef USE_X_TOOLKIT
12118 {
12119 int base_width, base_height;
12120 int min_rows = 0, min_cols = 0;
12121
12122 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12123 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
12124
12125 check_frame_size (f, &min_rows, &min_cols);
12126
12127 /* The window manager uses the base width hints to calculate the
12128 current number of rows and columns in the frame while
12129 resizing; min_width and min_height aren't useful for this
12130 purpose, since they might not give the dimensions for a
12131 zero-row, zero-column frame.
12132
12133 We use the base_width and base_height members if we have
12134 them; otherwise, we set the min_width and min_height members
12135 to the size for a zero x zero frame. */
12136
12137 #ifdef HAVE_X11R4
12138 size_hints.flags |= PBaseSize;
12139 size_hints.base_width = base_width;
12140 size_hints.base_height = base_height;
12141 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12142 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
12143 #else
12144 size_hints.min_width = base_width;
12145 size_hints.min_height = base_height;
12146 #endif
12147 }
12148
12149 /* If we don't need the old flags, we don't need the old hint at all. */
12150 if (flags)
12151 {
12152 size_hints.flags |= flags;
12153 goto no_read;
12154 }
12155 #endif /* not USE_X_TOOLKIT */
12156
12157 {
12158 XSizeHints hints; /* Sometimes I hate X Windows... */
12159 long supplied_return;
12160 int value;
12161
12162 #ifdef HAVE_X11R4
12163 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12164 &supplied_return);
12165 #else
12166 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
12167 #endif
12168
12169 #ifdef USE_X_TOOLKIT
12170 size_hints.base_height = hints.base_height;
12171 size_hints.base_width = hints.base_width;
12172 size_hints.min_height = hints.min_height;
12173 size_hints.min_width = hints.min_width;
12174 #endif
12175
12176 if (flags)
12177 size_hints.flags |= flags;
12178 else
12179 {
12180 if (value == 0)
12181 hints.flags = 0;
12182 if (hints.flags & PSize)
12183 size_hints.flags |= PSize;
12184 if (hints.flags & PPosition)
12185 size_hints.flags |= PPosition;
12186 if (hints.flags & USPosition)
12187 size_hints.flags |= USPosition;
12188 if (hints.flags & USSize)
12189 size_hints.flags |= USSize;
12190 }
12191 }
12192
12193 #ifndef USE_X_TOOLKIT
12194 no_read:
12195 #endif
12196
12197 #ifdef PWinGravity
12198 size_hints.win_gravity = f->output_data.x->win_gravity;
12199 size_hints.flags |= PWinGravity;
12200
12201 if (user_position)
12202 {
12203 size_hints.flags &= ~ PPosition;
12204 size_hints.flags |= USPosition;
12205 }
12206 #endif /* PWinGravity */
12207
12208 #ifdef HAVE_X11R4
12209 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12210 #else
12211 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
12212 #endif
12213 }
12214
12215 /* Used for IconicState or NormalState */
12216
12217 void
12218 x_wm_set_window_state (f, state)
12219 struct frame *f;
12220 int state;
12221 {
12222 #ifdef USE_X_TOOLKIT
12223 Arg al[1];
12224
12225 XtSetArg (al[0], XtNinitialState, state);
12226 XtSetValues (f->output_data.x->widget, al, 1);
12227 #else /* not USE_X_TOOLKIT */
12228 Window window = FRAME_X_WINDOW (f);
12229
12230 f->output_data.x->wm_hints.flags |= StateHint;
12231 f->output_data.x->wm_hints.initial_state = state;
12232
12233 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12234 #endif /* not USE_X_TOOLKIT */
12235 }
12236
12237 void
12238 x_wm_set_icon_pixmap (f, pixmap_id)
12239 struct frame *f;
12240 int pixmap_id;
12241 {
12242 Pixmap icon_pixmap;
12243
12244 #ifndef USE_X_TOOLKIT
12245 Window window = FRAME_X_WINDOW (f);
12246 #endif
12247
12248 if (pixmap_id > 0)
12249 {
12250 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
12251 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
12252 }
12253 else
12254 {
12255 /* It seems there is no way to turn off use of an icon pixmap.
12256 The following line does it, only if no icon has yet been created,
12257 for some window managers. But with mwm it crashes.
12258 Some people say it should clear the IconPixmapHint bit in this case,
12259 but that doesn't work, and the X consortium said it isn't the
12260 right thing at all. Since there is no way to win,
12261 best to explicitly give up. */
12262 #if 0
12263 f->output_data.x->wm_hints.icon_pixmap = None;
12264 #else
12265 return;
12266 #endif
12267 }
12268
12269 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12270
12271 {
12272 Arg al[1];
12273 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12274 XtSetValues (f->output_data.x->widget, al, 1);
12275 }
12276
12277 #else /* not USE_X_TOOLKIT */
12278
12279 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12280 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12281
12282 #endif /* not USE_X_TOOLKIT */
12283 }
12284
12285 void
12286 x_wm_set_icon_position (f, icon_x, icon_y)
12287 struct frame *f;
12288 int icon_x, icon_y;
12289 {
12290 #ifdef USE_X_TOOLKIT
12291 Window window = XtWindow (f->output_data.x->widget);
12292 #else
12293 Window window = FRAME_X_WINDOW (f);
12294 #endif
12295
12296 f->output_data.x->wm_hints.flags |= IconPositionHint;
12297 f->output_data.x->wm_hints.icon_x = icon_x;
12298 f->output_data.x->wm_hints.icon_y = icon_y;
12299
12300 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
12301 }
12302
12303 \f
12304 /***********************************************************************
12305 Fonts
12306 ***********************************************************************/
12307
12308 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
12309
12310 struct font_info *
12311 x_get_font_info (f, font_idx)
12312 FRAME_PTR f;
12313 int font_idx;
12314 {
12315 return (FRAME_X_FONT_TABLE (f) + font_idx);
12316 }
12317
12318
12319 /* Return a list of names of available fonts matching PATTERN on frame
12320 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12321 to be listed. Frame F NULL means we have not yet created any
12322 frame on X, and consult the first display in x_display_list.
12323 MAXNAMES sets a limit on how many fonts to match. */
12324
12325 Lisp_Object
12326 x_list_fonts (f, pattern, size, maxnames)
12327 FRAME_PTR f;
12328 Lisp_Object pattern;
12329 int size;
12330 int maxnames;
12331 {
12332 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12333 Lisp_Object tem, second_best;
12334 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
12335 int try_XLoadQueryFont = 0;
12336 int count;
12337
12338 patterns = Fassoc (pattern, Valternate_fontname_alist);
12339 if (NILP (patterns))
12340 patterns = Fcons (pattern, Qnil);
12341
12342 if (maxnames == 1 && !size)
12343 /* We can return any single font matching PATTERN. */
12344 try_XLoadQueryFont = 1;
12345
12346 for (; CONSP (patterns); patterns = XCDR (patterns))
12347 {
12348 int num_fonts;
12349 char **names = NULL;
12350
12351 pattern = XCAR (patterns);
12352 /* See if we cached the result for this particular query.
12353 The cache is an alist of the form:
12354 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12355 */
12356 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
12357 key = Fcons (pattern, make_number (maxnames)),
12358 !NILP (list = Fassoc (key, tem))))
12359 {
12360 list = Fcdr_safe (list);
12361 /* We have a cashed list. Don't have to get the list again. */
12362 goto label_cached;
12363 }
12364
12365 /* At first, put PATTERN in the cache. */
12366
12367 BLOCK_INPUT;
12368 count = x_catch_errors (dpy);
12369
12370 if (try_XLoadQueryFont)
12371 {
12372 XFontStruct *font;
12373 unsigned long value;
12374
12375 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
12376 if (x_had_errors_p (dpy))
12377 {
12378 /* This error is perhaps due to insufficient memory on X
12379 server. Let's just ignore it. */
12380 font = NULL;
12381 x_clear_errors (dpy);
12382 }
12383
12384 if (font
12385 && XGetFontProperty (font, XA_FONT, &value))
12386 {
12387 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12388 int len = strlen (name);
12389 char *tmp;
12390
12391 /* If DXPC (a Differential X Protocol Compressor)
12392 Ver.3.7 is running, XGetAtomName will return null
12393 string. We must avoid such a name. */
12394 if (len == 0)
12395 try_XLoadQueryFont = 0;
12396 else
12397 {
12398 num_fonts = 1;
12399 names = (char **) alloca (sizeof (char *));
12400 /* Some systems only allow alloca assigned to a
12401 simple var. */
12402 tmp = (char *) alloca (len + 1); names[0] = tmp;
12403 bcopy (name, names[0], len + 1);
12404 XFree (name);
12405 }
12406 }
12407 else
12408 try_XLoadQueryFont = 0;
12409
12410 if (font)
12411 XFreeFont (dpy, font);
12412 }
12413
12414 if (!try_XLoadQueryFont)
12415 {
12416 /* We try at least 10 fonts because XListFonts will return
12417 auto-scaled fonts at the head. */
12418 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12419 &num_fonts);
12420 if (x_had_errors_p (dpy))
12421 {
12422 /* This error is perhaps due to insufficient memory on X
12423 server. Let's just ignore it. */
12424 names = NULL;
12425 x_clear_errors (dpy);
12426 }
12427 }
12428
12429 x_uncatch_errors (dpy, count);
12430 UNBLOCK_INPUT;
12431
12432 if (names)
12433 {
12434 int i;
12435
12436 /* Make a list of all the fonts we got back.
12437 Store that in the font cache for the display. */
12438 for (i = 0; i < num_fonts; i++)
12439 {
12440 int width = 0;
12441 char *p = names[i];
12442 int average_width = -1, dashes = 0;
12443
12444 /* Count the number of dashes in NAMES[I]. If there are
12445 14 dashes, and the field value following 12th dash
12446 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12447 is usually too ugly to be used for editing. Let's
12448 ignore it. */
12449 while (*p)
12450 if (*p++ == '-')
12451 {
12452 dashes++;
12453 if (dashes == 7) /* PIXEL_SIZE field */
12454 width = atoi (p);
12455 else if (dashes == 12) /* AVERAGE_WIDTH field */
12456 average_width = atoi (p);
12457 }
12458 if (dashes < 14 || average_width != 0)
12459 {
12460 tem = build_string (names[i]);
12461 if (NILP (Fassoc (tem, list)))
12462 {
12463 if (STRINGP (Vx_pixel_size_width_font_regexp)
12464 && ((fast_c_string_match_ignore_case
12465 (Vx_pixel_size_width_font_regexp, names[i]))
12466 >= 0))
12467 /* We can set the value of PIXEL_SIZE to the
12468 width of this font. */
12469 list = Fcons (Fcons (tem, make_number (width)), list);
12470 else
12471 /* For the moment, width is not known. */
12472 list = Fcons (Fcons (tem, Qnil), list);
12473 }
12474 }
12475 }
12476 if (!try_XLoadQueryFont)
12477 XFreeFontNames (names);
12478 }
12479
12480 /* Now store the result in the cache. */
12481 if (f != NULL)
12482 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
12483 = Fcons (Fcons (key, list),
12484 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
12485
12486 label_cached:
12487 if (NILP (list)) continue; /* Try the remaining alternatives. */
12488
12489 newlist = second_best = Qnil;
12490 /* Make a list of the fonts that have the right width. */
12491 for (; CONSP (list); list = XCDR (list))
12492 {
12493 int found_size;
12494
12495 tem = XCAR (list);
12496
12497 if (!CONSP (tem) || NILP (XCAR (tem)))
12498 continue;
12499 if (!size)
12500 {
12501 newlist = Fcons (XCAR (tem), newlist);
12502 continue;
12503 }
12504
12505 if (!INTEGERP (XCDR (tem)))
12506 {
12507 /* Since we have not yet known the size of this font, we
12508 must try slow function call XLoadQueryFont. */
12509 XFontStruct *thisinfo;
12510
12511 BLOCK_INPUT;
12512 count = x_catch_errors (dpy);
12513 thisinfo = XLoadQueryFont (dpy,
12514 XSTRING (XCAR (tem))->data);
12515 if (x_had_errors_p (dpy))
12516 {
12517 /* This error is perhaps due to insufficient memory on X
12518 server. Let's just ignore it. */
12519 thisinfo = NULL;
12520 x_clear_errors (dpy);
12521 }
12522 x_uncatch_errors (dpy, count);
12523 UNBLOCK_INPUT;
12524
12525 if (thisinfo)
12526 {
12527 XCDR (tem)
12528 = (thisinfo->min_bounds.width == 0
12529 ? make_number (0)
12530 : make_number (thisinfo->max_bounds.width));
12531 XFreeFont (dpy, thisinfo);
12532 }
12533 else
12534 /* For unknown reason, the previous call of XListFont had
12535 returned a font which can't be opened. Record the size
12536 as 0 not to try to open it again. */
12537 XCDR (tem) = make_number (0);
12538 }
12539
12540 found_size = XINT (XCDR (tem));
12541 if (found_size == size)
12542 newlist = Fcons (XCAR (tem), newlist);
12543 else if (found_size > 0)
12544 {
12545 if (NILP (second_best))
12546 second_best = tem;
12547 else if (found_size < size)
12548 {
12549 if (XINT (XCDR (second_best)) > size
12550 || XINT (XCDR (second_best)) < found_size)
12551 second_best = tem;
12552 }
12553 else
12554 {
12555 if (XINT (XCDR (second_best)) > size
12556 && XINT (XCDR (second_best)) > found_size)
12557 second_best = tem;
12558 }
12559 }
12560 }
12561 if (!NILP (newlist))
12562 break;
12563 else if (!NILP (second_best))
12564 {
12565 newlist = Fcons (XCAR (second_best), Qnil);
12566 break;
12567 }
12568 }
12569
12570 return newlist;
12571 }
12572
12573
12574 #if GLYPH_DEBUG
12575
12576 /* Check that FONT is valid on frame F. It is if it can be found in F's
12577 font table. */
12578
12579 static void
12580 x_check_font (f, font)
12581 struct frame *f;
12582 XFontStruct *font;
12583 {
12584 int i;
12585 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12586
12587 xassert (font != NULL);
12588
12589 for (i = 0; i < dpyinfo->n_fonts; i++)
12590 if (dpyinfo->font_table[i].name
12591 && font == dpyinfo->font_table[i].font)
12592 break;
12593
12594 xassert (i < dpyinfo->n_fonts);
12595 }
12596
12597 #endif /* GLYPH_DEBUG != 0 */
12598
12599 /* Set *W to the minimum width, *H to the minimum font height of FONT.
12600 Note: There are (broken) X fonts out there with invalid XFontStruct
12601 min_bounds contents. For example, handa@etl.go.jp reports that
12602 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12603 have font->min_bounds.width == 0. */
12604
12605 static INLINE void
12606 x_font_min_bounds (font, w, h)
12607 XFontStruct *font;
12608 int *w, *h;
12609 {
12610 *h = FONT_HEIGHT (font);
12611 *w = font->min_bounds.width;
12612
12613 /* Try to handle the case where FONT->min_bounds has invalid
12614 contents. Since the only font known to have invalid min_bounds
12615 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12616 if (*w <= 0)
12617 *w = font->max_bounds.width;
12618 }
12619
12620
12621 /* Compute the smallest character width and smallest font height over
12622 all fonts available on frame F. Set the members smallest_char_width
12623 and smallest_font_height in F's x_display_info structure to
12624 the values computed. Value is non-zero if smallest_font_height or
12625 smallest_char_width become smaller than they were before. */
12626
12627 static int
12628 x_compute_min_glyph_bounds (f)
12629 struct frame *f;
12630 {
12631 int i;
12632 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12633 XFontStruct *font;
12634 int old_width = dpyinfo->smallest_char_width;
12635 int old_height = dpyinfo->smallest_font_height;
12636
12637 dpyinfo->smallest_font_height = 100000;
12638 dpyinfo->smallest_char_width = 100000;
12639
12640 for (i = 0; i < dpyinfo->n_fonts; ++i)
12641 if (dpyinfo->font_table[i].name)
12642 {
12643 struct font_info *fontp = dpyinfo->font_table + i;
12644 int w, h;
12645
12646 font = (XFontStruct *) fontp->font;
12647 xassert (font != (XFontStruct *) ~0);
12648 x_font_min_bounds (font, &w, &h);
12649
12650 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12651 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12652 }
12653
12654 xassert (dpyinfo->smallest_char_width > 0
12655 && dpyinfo->smallest_font_height > 0);
12656
12657 return (dpyinfo->n_fonts == 1
12658 || dpyinfo->smallest_char_width < old_width
12659 || dpyinfo->smallest_font_height < old_height);
12660 }
12661
12662
12663 /* Load font named FONTNAME of the size SIZE for frame F, and return a
12664 pointer to the structure font_info while allocating it dynamically.
12665 If SIZE is 0, load any size of font.
12666 If loading is failed, return NULL. */
12667
12668 struct font_info *
12669 x_load_font (f, fontname, size)
12670 struct frame *f;
12671 register char *fontname;
12672 int size;
12673 {
12674 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12675 Lisp_Object font_names;
12676 int count;
12677
12678 /* Get a list of all the fonts that match this name. Once we
12679 have a list of matching fonts, we compare them against the fonts
12680 we already have by comparing names. */
12681 font_names = x_list_fonts (f, build_string (fontname), size, 1);
12682
12683 if (!NILP (font_names))
12684 {
12685 Lisp_Object tail;
12686 int i;
12687
12688 for (i = 0; i < dpyinfo->n_fonts; i++)
12689 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
12690 if (dpyinfo->font_table[i].name
12691 && (!strcmp (dpyinfo->font_table[i].name,
12692 XSTRING (XCAR (tail))->data)
12693 || !strcmp (dpyinfo->font_table[i].full_name,
12694 XSTRING (XCAR (tail))->data)))
12695 return (dpyinfo->font_table + i);
12696 }
12697
12698 /* Load the font and add it to the table. */
12699 {
12700 char *full_name;
12701 XFontStruct *font;
12702 struct font_info *fontp;
12703 unsigned long value;
12704 int i;
12705
12706 /* If we have found fonts by x_list_font, load one of them. If
12707 not, we still try to load a font by the name given as FONTNAME
12708 because XListFonts (called in x_list_font) of some X server has
12709 a bug of not finding a font even if the font surely exists and
12710 is loadable by XLoadQueryFont. */
12711 if (size > 0 && !NILP (font_names))
12712 fontname = (char *) XSTRING (XCAR (font_names))->data;
12713
12714 BLOCK_INPUT;
12715 count = x_catch_errors (FRAME_X_DISPLAY (f));
12716 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
12717 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12718 {
12719 /* This error is perhaps due to insufficient memory on X
12720 server. Let's just ignore it. */
12721 font = NULL;
12722 x_clear_errors (FRAME_X_DISPLAY (f));
12723 }
12724 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
12725 UNBLOCK_INPUT;
12726 if (!font)
12727 return NULL;
12728
12729 /* Find a free slot in the font table. */
12730 for (i = 0; i < dpyinfo->n_fonts; ++i)
12731 if (dpyinfo->font_table[i].name == NULL)
12732 break;
12733
12734 /* If no free slot found, maybe enlarge the font table. */
12735 if (i == dpyinfo->n_fonts
12736 && dpyinfo->n_fonts == dpyinfo->font_table_size)
12737 {
12738 int sz;
12739 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12740 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
12741 dpyinfo->font_table
12742 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
12743 }
12744
12745 fontp = dpyinfo->font_table + i;
12746 if (i == dpyinfo->n_fonts)
12747 ++dpyinfo->n_fonts;
12748
12749 /* Now fill in the slots of *FONTP. */
12750 BLOCK_INPUT;
12751 fontp->font = font;
12752 fontp->font_idx = i;
12753 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12754 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12755
12756 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12757 full_name = 0;
12758 if (XGetFontProperty (font, XA_FONT, &value))
12759 {
12760 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12761 char *p = name;
12762 int dashes = 0;
12763
12764 /* Count the number of dashes in the "full name".
12765 If it is too few, this isn't really the font's full name,
12766 so don't use it.
12767 In X11R4, the fonts did not come with their canonical names
12768 stored in them. */
12769 while (*p)
12770 {
12771 if (*p == '-')
12772 dashes++;
12773 p++;
12774 }
12775
12776 if (dashes >= 13)
12777 {
12778 full_name = (char *) xmalloc (p - name + 1);
12779 bcopy (name, full_name, p - name + 1);
12780 }
12781
12782 XFree (name);
12783 }
12784
12785 if (full_name != 0)
12786 fontp->full_name = full_name;
12787 else
12788 fontp->full_name = fontp->name;
12789
12790 fontp->size = font->max_bounds.width;
12791 fontp->height = FONT_HEIGHT (font);
12792 {
12793 /* For some font, ascent and descent in max_bounds field is
12794 larger than the above value. */
12795 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12796 if (max_height > fontp->height)
12797 fontp->height = max_height;
12798 }
12799
12800 if (NILP (font_names))
12801 {
12802 /* We come here because of a bug of XListFonts mentioned at
12803 the head of this block. Let's store this information in
12804 the cache for x_list_fonts. */
12805 Lisp_Object lispy_name = build_string (fontname);
12806 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12807
12808 XCDR (dpyinfo->name_list_element)
12809 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12810 Fcons (Fcons (lispy_full_name,
12811 make_number (fontp->size)),
12812 Qnil)),
12813 XCDR (dpyinfo->name_list_element));
12814 if (full_name)
12815 XCDR (dpyinfo->name_list_element)
12816 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12817 Fcons (Fcons (lispy_full_name,
12818 make_number (fontp->size)),
12819 Qnil)),
12820 XCDR (dpyinfo->name_list_element));
12821 }
12822
12823 /* The slot `encoding' specifies how to map a character
12824 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
12825 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12826 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
12827 2:0xA020..0xFF7F). For the moment, we don't know which charset
12828 uses this font. So, we set information in fontp->encoding[1]
12829 which is never used by any charset. If mapping can't be
12830 decided, set FONT_ENCODING_NOT_DECIDED. */
12831 fontp->encoding[1]
12832 = (font->max_byte1 == 0
12833 /* 1-byte font */
12834 ? (font->min_char_or_byte2 < 0x80
12835 ? (font->max_char_or_byte2 < 0x80
12836 ? 0 /* 0x20..0x7F */
12837 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
12838 : 1) /* 0xA0..0xFF */
12839 /* 2-byte font */
12840 : (font->min_byte1 < 0x80
12841 ? (font->max_byte1 < 0x80
12842 ? (font->min_char_or_byte2 < 0x80
12843 ? (font->max_char_or_byte2 < 0x80
12844 ? 0 /* 0x2020..0x7F7F */
12845 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
12846 : 3) /* 0x20A0..0x7FFF */
12847 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
12848 : (font->min_char_or_byte2 < 0x80
12849 ? (font->max_char_or_byte2 < 0x80
12850 ? 2 /* 0xA020..0xFF7F */
12851 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
12852 : 1))); /* 0xA0A0..0xFFFF */
12853
12854 fontp->baseline_offset
12855 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12856 ? (long) value : 0);
12857 fontp->relative_compose
12858 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12859 ? (long) value : 0);
12860 fontp->default_ascent
12861 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12862 ? (long) value : 0);
12863
12864 /* Set global flag fonts_changed_p to non-zero if the font loaded
12865 has a character with a smaller width than any other character
12866 before, or if the font loaded has a smalle>r height than any
12867 other font loaded before. If this happens, it will make a
12868 glyph matrix reallocation necessary. */
12869 fonts_changed_p = x_compute_min_glyph_bounds (f);
12870 UNBLOCK_INPUT;
12871 return fontp;
12872 }
12873 }
12874
12875
12876 /* Return a pointer to struct font_info of a font named FONTNAME for
12877 frame F. If no such font is loaded, return NULL. */
12878
12879 struct font_info *
12880 x_query_font (f, fontname)
12881 struct frame *f;
12882 register char *fontname;
12883 {
12884 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12885 int i;
12886
12887 for (i = 0; i < dpyinfo->n_fonts; i++)
12888 if (dpyinfo->font_table[i].name
12889 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12890 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
12891 return (dpyinfo->font_table + i);
12892 return NULL;
12893 }
12894
12895
12896 /* Find a CCL program for a font specified by FONTP, and set the member
12897 `encoder' of the structure. */
12898
12899 void
12900 x_find_ccl_program (fontp)
12901 struct font_info *fontp;
12902 {
12903 Lisp_Object list, elt;
12904
12905 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
12906 {
12907 elt = XCAR (list);
12908 if (CONSP (elt)
12909 && STRINGP (XCAR (elt))
12910 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
12911 >= 0))
12912 break;
12913 }
12914 if (! NILP (list))
12915 {
12916 struct ccl_program *ccl
12917 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
12918
12919 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
12920 xfree (ccl);
12921 else
12922 fontp->font_encoder = ccl;
12923 }
12924 }
12925
12926
12927 \f
12928 /***********************************************************************
12929 Initialization
12930 ***********************************************************************/
12931
12932 #ifdef USE_X_TOOLKIT
12933 static XrmOptionDescRec emacs_options[] = {
12934 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12935 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12936
12937 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12938 XrmoptionSepArg, NULL},
12939 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12940
12941 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12942 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12943 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12944 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12945 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12946 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12947 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12948 };
12949 #endif /* USE_X_TOOLKIT */
12950
12951 static int x_initialized;
12952
12953 #ifdef MULTI_KBOARD
12954 /* Test whether two display-name strings agree up to the dot that separates
12955 the screen number from the server number. */
12956 static int
12957 same_x_server (name1, name2)
12958 char *name1, *name2;
12959 {
12960 int seen_colon = 0;
12961 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12962 int system_name_length = strlen (system_name);
12963 int length_until_period = 0;
12964
12965 while (system_name[length_until_period] != 0
12966 && system_name[length_until_period] != '.')
12967 length_until_period++;
12968
12969 /* Treat `unix' like an empty host name. */
12970 if (! strncmp (name1, "unix:", 5))
12971 name1 += 4;
12972 if (! strncmp (name2, "unix:", 5))
12973 name2 += 4;
12974 /* Treat this host's name like an empty host name. */
12975 if (! strncmp (name1, system_name, system_name_length)
12976 && name1[system_name_length] == ':')
12977 name1 += system_name_length;
12978 if (! strncmp (name2, system_name, system_name_length)
12979 && name2[system_name_length] == ':')
12980 name2 += system_name_length;
12981 /* Treat this host's domainless name like an empty host name. */
12982 if (! strncmp (name1, system_name, length_until_period)
12983 && name1[length_until_period] == ':')
12984 name1 += length_until_period;
12985 if (! strncmp (name2, system_name, length_until_period)
12986 && name2[length_until_period] == ':')
12987 name2 += length_until_period;
12988
12989 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12990 {
12991 if (*name1 == ':')
12992 seen_colon++;
12993 if (seen_colon && *name1 == '.')
12994 return 1;
12995 }
12996 return (seen_colon
12997 && (*name1 == '.' || *name1 == '\0')
12998 && (*name2 == '.' || *name2 == '\0'));
12999 }
13000 #endif
13001
13002 struct x_display_info *
13003 x_term_init (display_name, xrm_option, resource_name)
13004 Lisp_Object display_name;
13005 char *xrm_option;
13006 char *resource_name;
13007 {
13008 int connection;
13009 Display *dpy;
13010 struct x_display_info *dpyinfo;
13011 XrmDatabase xrdb;
13012
13013 BLOCK_INPUT;
13014
13015 if (!x_initialized)
13016 {
13017 x_initialize ();
13018 x_initialized = 1;
13019 }
13020
13021 #ifdef USE_X_TOOLKIT
13022 /* weiner@footloose.sps.mot.com reports that this causes
13023 errors with X11R5:
13024 X protocol error: BadAtom (invalid Atom parameter)
13025 on protocol request 18skiloaf.
13026 So let's not use it until R6. */
13027 #ifdef HAVE_X11XTR6
13028 XtSetLanguageProc (NULL, NULL, NULL);
13029 #endif
13030
13031 {
13032 int argc = 0;
13033 char *argv[3];
13034
13035 argv[0] = "";
13036 argc = 1;
13037 if (xrm_option)
13038 {
13039 argv[argc++] = "-xrm";
13040 argv[argc++] = xrm_option;
13041 }
13042 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13043 resource_name, EMACS_CLASS,
13044 emacs_options, XtNumber (emacs_options),
13045 &argc, argv);
13046
13047 #ifdef HAVE_X11XTR6
13048 /* I think this is to compensate for XtSetLanguageProc. */
13049 fixup_locale ();
13050 #endif
13051 }
13052
13053 #else /* not USE_X_TOOLKIT */
13054 #ifdef HAVE_X11R5
13055 XSetLocaleModifiers ("");
13056 #endif
13057 dpy = XOpenDisplay (XSTRING (display_name)->data);
13058 #endif /* not USE_X_TOOLKIT */
13059
13060 /* Detect failure. */
13061 if (dpy == 0)
13062 {
13063 UNBLOCK_INPUT;
13064 return 0;
13065 }
13066
13067 /* We have definitely succeeded. Record the new connection. */
13068
13069 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13070
13071 #ifdef MULTI_KBOARD
13072 {
13073 struct x_display_info *share;
13074 Lisp_Object tail;
13075
13076 for (share = x_display_list, tail = x_display_name_list; share;
13077 share = share->next, tail = XCDR (tail))
13078 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
13079 XSTRING (display_name)->data))
13080 break;
13081 if (share)
13082 dpyinfo->kboard = share->kboard;
13083 else
13084 {
13085 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13086 init_kboard (dpyinfo->kboard);
13087 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13088 {
13089 char *vendor = ServerVendor (dpy);
13090 UNBLOCK_INPUT;
13091 dpyinfo->kboard->Vsystem_key_alist
13092 = call1 (Qvendor_specific_keysyms,
13093 build_string (vendor ? vendor : ""));
13094 BLOCK_INPUT;
13095 }
13096
13097 dpyinfo->kboard->next_kboard = all_kboards;
13098 all_kboards = dpyinfo->kboard;
13099 /* Don't let the initial kboard remain current longer than necessary.
13100 That would cause problems if a file loaded on startup tries to
13101 prompt in the mini-buffer. */
13102 if (current_kboard == initial_kboard)
13103 current_kboard = dpyinfo->kboard;
13104 }
13105 dpyinfo->kboard->reference_count++;
13106 }
13107 #endif
13108
13109 /* Put this display on the chain. */
13110 dpyinfo->next = x_display_list;
13111 x_display_list = dpyinfo;
13112
13113 /* Put it on x_display_name_list as well, to keep them parallel. */
13114 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13115 x_display_name_list);
13116 dpyinfo->name_list_element = XCAR (x_display_name_list);
13117
13118 dpyinfo->display = dpy;
13119
13120 #if 0
13121 XSetAfterFunction (x_current_display, x_trace_wire);
13122 #endif /* ! 0 */
13123
13124 dpyinfo->x_id_name
13125 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13126 + STRING_BYTES (XSTRING (Vsystem_name))
13127 + 2);
13128 sprintf (dpyinfo->x_id_name, "%s@%s",
13129 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
13130
13131 /* Figure out which modifier bits mean what. */
13132 x_find_modifier_meanings (dpyinfo);
13133
13134 /* Get the scroll bar cursor. */
13135 dpyinfo->vertical_scroll_bar_cursor
13136 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
13137
13138 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13139 resource_name, EMACS_CLASS);
13140 #ifdef HAVE_XRMSETDATABASE
13141 XrmSetDatabase (dpyinfo->display, xrdb);
13142 #else
13143 dpyinfo->display->db = xrdb;
13144 #endif
13145 /* Put the rdb where we can find it in a way that works on
13146 all versions. */
13147 dpyinfo->xrdb = xrdb;
13148
13149 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13150 DefaultScreen (dpyinfo->display));
13151 select_visual (dpyinfo);
13152 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
13153 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13154 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13155 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13156 dpyinfo->grabbed = 0;
13157 dpyinfo->reference_count = 0;
13158 dpyinfo->icon_bitmap_id = -1;
13159 dpyinfo->font_table = NULL;
13160 dpyinfo->n_fonts = 0;
13161 dpyinfo->font_table_size = 0;
13162 dpyinfo->bitmaps = 0;
13163 dpyinfo->bitmaps_size = 0;
13164 dpyinfo->bitmaps_last = 0;
13165 dpyinfo->scratch_cursor_gc = 0;
13166 dpyinfo->mouse_face_mouse_frame = 0;
13167 dpyinfo->mouse_face_deferred_gc = 0;
13168 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13169 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
13170 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
13171 dpyinfo->mouse_face_window = Qnil;
13172 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13173 dpyinfo->mouse_face_defer = 0;
13174 dpyinfo->x_focus_frame = 0;
13175 dpyinfo->x_focus_event_frame = 0;
13176 dpyinfo->x_highlight_frame = 0;
13177 dpyinfo->image_cache = make_image_cache ();
13178
13179 /* See if a private colormap is requested. */
13180 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13181 {
13182 if (dpyinfo->visual->class == PseudoColor)
13183 {
13184 Lisp_Object value;
13185 value = display_x_get_resource (dpyinfo,
13186 build_string ("privateColormap"),
13187 build_string ("PrivateColormap"),
13188 Qnil, Qnil);
13189 if (STRINGP (value)
13190 && (!strcmp (XSTRING (value)->data, "true")
13191 || !strcmp (XSTRING (value)->data, "on")))
13192 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13193 }
13194 }
13195 else
13196 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13197 dpyinfo->visual, AllocNone);
13198
13199 {
13200 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13201 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13202 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13203 dpyinfo->resy = pixels * 25.4 / mm;
13204 pixels = DisplayWidth (dpyinfo->display, screen_number);
13205 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13206 dpyinfo->resx = pixels * 25.4 / mm;
13207 }
13208
13209 dpyinfo->Xatom_wm_protocols
13210 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13211 dpyinfo->Xatom_wm_take_focus
13212 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13213 dpyinfo->Xatom_wm_save_yourself
13214 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13215 dpyinfo->Xatom_wm_delete_window
13216 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13217 dpyinfo->Xatom_wm_change_state
13218 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13219 dpyinfo->Xatom_wm_configure_denied
13220 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13221 dpyinfo->Xatom_wm_window_moved
13222 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13223 dpyinfo->Xatom_editres
13224 = XInternAtom (dpyinfo->display, "Editres", False);
13225 dpyinfo->Xatom_CLIPBOARD
13226 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13227 dpyinfo->Xatom_TIMESTAMP
13228 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13229 dpyinfo->Xatom_TEXT
13230 = XInternAtom (dpyinfo->display, "TEXT", False);
13231 dpyinfo->Xatom_COMPOUND_TEXT
13232 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
13233 dpyinfo->Xatom_DELETE
13234 = XInternAtom (dpyinfo->display, "DELETE", False);
13235 dpyinfo->Xatom_MULTIPLE
13236 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13237 dpyinfo->Xatom_INCR
13238 = XInternAtom (dpyinfo->display, "INCR", False);
13239 dpyinfo->Xatom_EMACS_TMP
13240 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13241 dpyinfo->Xatom_TARGETS
13242 = XInternAtom (dpyinfo->display, "TARGETS", False);
13243 dpyinfo->Xatom_NULL
13244 = XInternAtom (dpyinfo->display, "NULL", False);
13245 dpyinfo->Xatom_ATOM_PAIR
13246 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
13247 /* For properties of font. */
13248 dpyinfo->Xatom_PIXEL_SIZE
13249 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13250 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13251 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13252 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13253 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
13254 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13255 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
13256
13257 /* Ghostscript support. */
13258 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13259 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13260
13261 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13262 False);
13263
13264 dpyinfo->cut_buffers_initialized = 0;
13265
13266 connection = ConnectionNumber (dpyinfo->display);
13267 dpyinfo->connection = connection;
13268
13269 {
13270 char null_bits[1];
13271
13272 null_bits[0] = 0x00;
13273
13274 dpyinfo->null_pixel
13275 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13276 null_bits, 1, 1, (long) 0, (long) 0,
13277 1);
13278 }
13279
13280 {
13281 extern int gray_bitmap_width, gray_bitmap_height;
13282 extern unsigned char *gray_bitmap_bits;
13283 dpyinfo->gray
13284 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13285 gray_bitmap_bits,
13286 gray_bitmap_width, gray_bitmap_height,
13287 (unsigned long) 1, (unsigned long) 0, 1);
13288 }
13289
13290 #ifdef HAVE_X_I18N
13291 xim_initialize (dpyinfo, resource_name);
13292 #endif
13293
13294 #ifdef subprocesses
13295 /* This is only needed for distinguishing keyboard and process input. */
13296 if (connection != 0)
13297 add_keyboard_wait_descriptor (connection);
13298 #endif
13299
13300 #ifndef F_SETOWN_BUG
13301 #ifdef F_SETOWN
13302 #ifdef F_SETOWN_SOCK_NEG
13303 /* stdin is a socket here */
13304 fcntl (connection, F_SETOWN, -getpid ());
13305 #else /* ! defined (F_SETOWN_SOCK_NEG) */
13306 fcntl (connection, F_SETOWN, getpid ());
13307 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
13308 #endif /* ! defined (F_SETOWN) */
13309 #endif /* F_SETOWN_BUG */
13310
13311 #ifdef SIGIO
13312 if (interrupt_input)
13313 init_sigio (connection);
13314 #endif /* ! defined (SIGIO) */
13315
13316 #ifdef USE_LUCID
13317 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
13318 /* Make sure that we have a valid font for dialog boxes
13319 so that Xt does not crash. */
13320 {
13321 Display *dpy = dpyinfo->display;
13322 XrmValue d, fr, to;
13323 Font font;
13324 int count;
13325
13326 d.addr = (XPointer)&dpy;
13327 d.size = sizeof (Display *);
13328 fr.addr = XtDefaultFont;
13329 fr.size = sizeof (XtDefaultFont);
13330 to.size = sizeof (Font *);
13331 to.addr = (XPointer)&font;
13332 count = x_catch_errors (dpy);
13333 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13334 abort ();
13335 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13336 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
13337 x_uncatch_errors (dpy, count);
13338 }
13339 #endif
13340 #endif
13341
13342 /* See if we should run in synchronous mode. This is useful
13343 for debugging X code. */
13344 {
13345 Lisp_Object value;
13346 value = display_x_get_resource (dpyinfo,
13347 build_string ("synchronous"),
13348 build_string ("Synchronous"),
13349 Qnil, Qnil);
13350 if (STRINGP (value)
13351 && (!strcmp (XSTRING (value)->data, "true")
13352 || !strcmp (XSTRING (value)->data, "on")))
13353 XSynchronize (dpyinfo->display, True);
13354 }
13355
13356 UNBLOCK_INPUT;
13357
13358 return dpyinfo;
13359 }
13360 \f
13361 /* Get rid of display DPYINFO, assuming all frames are already gone,
13362 and without sending any more commands to the X server. */
13363
13364 void
13365 x_delete_display (dpyinfo)
13366 struct x_display_info *dpyinfo;
13367 {
13368 delete_keyboard_wait_descriptor (dpyinfo->connection);
13369
13370 /* Discard this display from x_display_name_list and x_display_list.
13371 We can't use Fdelq because that can quit. */
13372 if (! NILP (x_display_name_list)
13373 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13374 x_display_name_list = XCDR (x_display_name_list);
13375 else
13376 {
13377 Lisp_Object tail;
13378
13379 tail = x_display_name_list;
13380 while (CONSP (tail) && CONSP (XCDR (tail)))
13381 {
13382 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
13383 {
13384 XCDR (tail) = XCDR (XCDR (tail));
13385 break;
13386 }
13387 tail = XCDR (tail);
13388 }
13389 }
13390
13391 if (next_noop_dpyinfo == dpyinfo)
13392 next_noop_dpyinfo = dpyinfo->next;
13393
13394 if (x_display_list == dpyinfo)
13395 x_display_list = dpyinfo->next;
13396 else
13397 {
13398 struct x_display_info *tail;
13399
13400 for (tail = x_display_list; tail; tail = tail->next)
13401 if (tail->next == dpyinfo)
13402 tail->next = tail->next->next;
13403 }
13404
13405 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13406 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
13407 XrmDestroyDatabase (dpyinfo->xrdb);
13408 #endif
13409 #endif
13410 #ifdef MULTI_KBOARD
13411 if (--dpyinfo->kboard->reference_count == 0)
13412 delete_kboard (dpyinfo->kboard);
13413 #endif
13414 #ifdef HAVE_X_I18N
13415 if (dpyinfo->xim)
13416 xim_close_dpy (dpyinfo);
13417 #endif
13418
13419 xfree (dpyinfo->font_table);
13420 xfree (dpyinfo->x_id_name);
13421 xfree (dpyinfo);
13422 }
13423 \f
13424 /* Set up use of X before we make the first connection. */
13425
13426 static struct redisplay_interface x_redisplay_interface =
13427 {
13428 x_produce_glyphs,
13429 x_write_glyphs,
13430 x_insert_glyphs,
13431 x_clear_end_of_line,
13432 x_scroll_run,
13433 x_after_update_window_line,
13434 x_update_window_begin,
13435 x_update_window_end,
13436 XTcursor_to,
13437 x_flush,
13438 x_get_glyph_overhangs,
13439 x_fix_overlapping_area
13440 };
13441
13442 void
13443 x_initialize ()
13444 {
13445 rif = &x_redisplay_interface;
13446
13447 clear_frame_hook = x_clear_frame;
13448 ins_del_lines_hook = x_ins_del_lines;
13449 change_line_highlight_hook = x_change_line_highlight;
13450 delete_glyphs_hook = x_delete_glyphs;
13451 ring_bell_hook = XTring_bell;
13452 reset_terminal_modes_hook = XTreset_terminal_modes;
13453 set_terminal_modes_hook = XTset_terminal_modes;
13454 update_begin_hook = x_update_begin;
13455 update_end_hook = x_update_end;
13456 set_terminal_window_hook = XTset_terminal_window;
13457 read_socket_hook = XTread_socket;
13458 frame_up_to_date_hook = XTframe_up_to_date;
13459 reassert_line_highlight_hook = XTreassert_line_highlight;
13460 mouse_position_hook = XTmouse_position;
13461 frame_rehighlight_hook = XTframe_rehighlight;
13462 frame_raise_lower_hook = XTframe_raise_lower;
13463 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13464 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13465 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13466 judge_scroll_bars_hook = XTjudge_scroll_bars;
13467 estimate_mode_line_height_hook = x_estimate_mode_line_height;
13468
13469 scroll_region_ok = 1; /* we'll scroll partial frames */
13470 char_ins_del_ok = 0; /* just as fast to write the line */
13471 line_ins_del_ok = 1; /* we'll just blt 'em */
13472 fast_clear_end_of_line = 1; /* X does this well */
13473 memory_below_frame = 0; /* we don't remember what scrolls
13474 off the bottom */
13475 baud_rate = 19200;
13476
13477 x_noop_count = 0;
13478 last_tool_bar_item = -1;
13479 any_help_event_p = 0;
13480
13481 /* Try to use interrupt input; if we can't, then start polling. */
13482 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13483
13484 #ifdef USE_X_TOOLKIT
13485 XtToolkitInitialize ();
13486 Xt_app_con = XtCreateApplicationContext ();
13487 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
13488
13489 /* Install an asynchronous timer that processes Xt timeout events
13490 every 0.1s. This is necessary because some widget sets use
13491 timeouts internally, for example the LessTif menu bar, or the
13492 Xaw3d scroll bar. When Xt timouts aren't processed, these
13493 widgets don't behave normally. */
13494 {
13495 EMACS_TIME interval;
13496 EMACS_SET_SECS_USECS (interval, 0, 100000);
13497 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13498 }
13499 #endif
13500
13501 #if USE_TOOLKIT_SCROLL_BARS
13502 xaw3d_arrow_scroll = False;
13503 xaw3d_pick_top = True;
13504 #endif
13505
13506 /* Note that there is no real way portable across R3/R4 to get the
13507 original error handler. */
13508 XSetErrorHandler (x_error_handler);
13509 XSetIOErrorHandler (x_io_error_quitter);
13510
13511 /* Disable Window Change signals; they are handled by X events. */
13512 #ifdef SIGWINCH
13513 signal (SIGWINCH, SIG_DFL);
13514 #endif /* ! defined (SIGWINCH) */
13515
13516 signal (SIGPIPE, x_connection_signal);
13517 }
13518
13519
13520 void
13521 syms_of_xterm ()
13522 {
13523 staticpro (&x_error_message_string);
13524 x_error_message_string = Qnil;
13525
13526 staticpro (&x_display_name_list);
13527 x_display_name_list = Qnil;
13528
13529 staticpro (&last_mouse_scroll_bar);
13530 last_mouse_scroll_bar = Qnil;
13531
13532 staticpro (&Qvendor_specific_keysyms);
13533 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
13534
13535 staticpro (&last_mouse_press_frame);
13536 last_mouse_press_frame = Qnil;
13537
13538 staticpro (&help_echo);
13539 help_echo = Qnil;
13540 staticpro (&previous_help_echo);
13541 previous_help_echo = Qnil;
13542
13543 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13544 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13545 For example, if a block cursor is over a tab, it will be drawn as\n\
13546 wide as that tab on the display.");
13547 x_stretch_cursor_p = 0;
13548
13549 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13550 "If not nil, Emacs uses toolkit scroll bars.");
13551 #if USE_TOOLKIT_SCROLL_BARS
13552 x_toolkit_scroll_bars_p = 1;
13553 #else
13554 x_toolkit_scroll_bars_p = 0;
13555 #endif
13556
13557 staticpro (&last_mouse_motion_frame);
13558 last_mouse_motion_frame = Qnil;
13559 }
13560
13561 #endif /* not HAVE_X_WINDOWS */
13562