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