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