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