Merged in changes from CVS trunk.
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 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_output 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 = XCAR (old_val);
7612 Display *dpy = XSAVE_VALUE (first)->pointer;
7613
7614 /* The display may have been closed before this function is called.
7615 Check if it is still open before calling XSync. */
7616 if (x_display_info_for_display (dpy) != 0)
7617 XSync (dpy, False);
7618
7619 x_error_message_string = XCDR (old_val);
7620 return Qnil;
7621 }
7622
7623 /* If any X protocol errors have arrived since the last call to
7624 x_catch_errors or x_check_errors, signal an Emacs error using
7625 sprintf (a buffer, FORMAT, the x error message text) as the text. */
7626
7627 void
7628 x_check_errors (dpy, format)
7629 Display *dpy;
7630 char *format;
7631 {
7632 /* Make sure to catch any errors incurred so far. */
7633 XSync (dpy, False);
7634
7635 if (SREF (x_error_message_string, 0))
7636 error (format, SDATA (x_error_message_string));
7637 }
7638
7639 /* Nonzero if we had any X protocol errors
7640 since we did x_catch_errors on DPY. */
7641
7642 int
7643 x_had_errors_p (dpy)
7644 Display *dpy;
7645 {
7646 /* Make sure to catch any errors incurred so far. */
7647 XSync (dpy, False);
7648
7649 return SREF (x_error_message_string, 0) != 0;
7650 }
7651
7652 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
7653
7654 void
7655 x_clear_errors (dpy)
7656 Display *dpy;
7657 {
7658 SSET (x_error_message_string, 0, 0);
7659 }
7660
7661 /* Stop catching X protocol errors and let them make Emacs die.
7662 DPY should be the display that was passed to x_catch_errors.
7663 COUNT should be the value that was returned by
7664 the corresponding call to x_catch_errors. */
7665
7666 void
7667 x_uncatch_errors (dpy, count)
7668 Display *dpy;
7669 int count;
7670 {
7671 unbind_to (count, Qnil);
7672 }
7673
7674 #if 0
7675 static unsigned int x_wire_count;
7676 x_trace_wire ()
7677 {
7678 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
7679 }
7680 #endif /* ! 0 */
7681
7682 \f
7683 /* Handle SIGPIPE, which can happen when the connection to a server
7684 simply goes away. SIGPIPE is handled by x_connection_signal.
7685 Don't need to do anything, because the write which caused the
7686 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7687 which will do the appropriate cleanup for us. */
7688
7689 static SIGTYPE
7690 x_connection_signal (signalnum) /* If we don't have an argument, */
7691 int signalnum; /* some compilers complain in signal calls. */
7692 {
7693 #ifdef USG
7694 /* USG systems forget handlers when they are used;
7695 must reestablish each time */
7696 signal (signalnum, x_connection_signal);
7697 #endif /* USG */
7698 }
7699
7700 \f
7701 /************************************************************************
7702 Handling X errors
7703 ************************************************************************/
7704
7705 /* Error message passed to x_connection_closed. */
7706
7707 static char *error_msg;
7708
7709 /* Function installed as fatal_error_signal_hook in
7710 x_connection_closed. Print the X error message, and exit normally,
7711 instead of dumping core when XtCloseDisplay fails. */
7712
7713 static void
7714 x_fatal_error_signal ()
7715 {
7716 fprintf (stderr, "%s\n", error_msg);
7717 exit (70);
7718 }
7719
7720 /* Handle the loss of connection to display DPY. ERROR_MESSAGE is
7721 the text of an error message that lead to the connection loss. */
7722
7723 static SIGTYPE
7724 x_connection_closed (dpy, error_message)
7725 Display *dpy;
7726 char *error_message;
7727 {
7728 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7729 Lisp_Object frame, tail;
7730 int count;
7731 int index = SPECPDL_INDEX ();
7732
7733 error_msg = (char *) alloca (strlen (error_message) + 1);
7734 strcpy (error_msg, error_message);
7735 handling_signal = 0;
7736
7737 /* Prevent being called recursively because of an error condition
7738 below. Otherwise, we might end up with printing ``can't find per
7739 display information'' in the recursive call instead of printing
7740 the original message here. */
7741 count = x_catch_errors (dpy);
7742
7743 /* We have to close the display to inform Xt that it doesn't
7744 exist anymore. If we don't, Xt will continue to wait for
7745 events from the display. As a consequence, a sequence of
7746
7747 M-x make-frame-on-display RET :1 RET
7748 ...kill the new frame, so that we get an IO error...
7749 M-x make-frame-on-display RET :1 RET
7750
7751 will indefinitely wait in Xt for events for display `:1', opened
7752 in the first class to make-frame-on-display.
7753
7754 Closing the display is reported to lead to a bus error on
7755 OpenWindows in certain situations. I suspect that is a bug
7756 in OpenWindows. I don't know how to cicumvent it here. */
7757
7758 #ifdef USE_X_TOOLKIT
7759 /* If DPYINFO is null, this means we didn't open the display
7760 in the first place, so don't try to close it. */
7761 if (dpyinfo)
7762 {
7763 extern void (*fatal_error_signal_hook) P_ ((void));
7764 fatal_error_signal_hook = x_fatal_error_signal;
7765 XtCloseDisplay (dpy);
7766 fatal_error_signal_hook = NULL;
7767 }
7768 #endif
7769
7770 #ifdef USE_GTK
7771 if (dpyinfo)
7772 xg_display_close (dpyinfo->display);
7773 #endif
7774
7775 /* Indicate that this display is dead. */
7776 if (dpyinfo)
7777 dpyinfo->display = 0;
7778
7779 /* Inhibit redisplay while frames are being deleted. */
7780 specbind (Qinhibit_redisplay, Qt);
7781
7782 /* First delete frames whose mini-buffers are on frames
7783 that are on the dead display. */
7784 FOR_EACH_FRAME (tail, frame)
7785 {
7786 Lisp_Object minibuf_frame;
7787 minibuf_frame
7788 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
7789 if (FRAME_X_P (XFRAME (frame))
7790 && FRAME_X_P (XFRAME (minibuf_frame))
7791 && ! EQ (frame, minibuf_frame)
7792 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7793 Fdelete_frame (frame, Qt);
7794 }
7795
7796 /* Now delete all remaining frames on the dead display.
7797 We are now sure none of these is used as the mini-buffer
7798 for another frame that we need to delete. */
7799 FOR_EACH_FRAME (tail, frame)
7800 if (FRAME_X_P (XFRAME (frame))
7801 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
7802 {
7803 /* Set this to t so that Fdelete_frame won't get confused
7804 trying to find a replacement. */
7805 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
7806 Fdelete_frame (frame, Qt);
7807 }
7808
7809 if (dpyinfo)
7810 x_delete_display (dpyinfo);
7811
7812 x_uncatch_errors (dpy, count);
7813
7814 if (display_list == 0)
7815 {
7816 fprintf (stderr, "%s\n", error_msg);
7817 shut_down_emacs (0, 0, Qnil);
7818 exit (70);
7819 }
7820
7821 /* Ordinary stack unwind doesn't deal with these. */
7822 #ifdef SIGIO
7823 sigunblock (sigmask (SIGIO));
7824 #endif
7825 sigunblock (sigmask (SIGALRM));
7826 TOTALLY_UNBLOCK_INPUT;
7827
7828 unbind_to (index, Qnil);
7829 clear_waiting_for_input ();
7830 error ("%s", error_msg);
7831 }
7832
7833
7834 /* This is the usual handler for X protocol errors.
7835 It kills all frames on the display that we got the error for.
7836 If that was the only one, it prints an error message and kills Emacs. */
7837
7838 static void
7839 x_error_quitter (display, error)
7840 Display *display;
7841 XErrorEvent *error;
7842 {
7843 char buf[256], buf1[356];
7844
7845 /* Note that there is no real way portable across R3/R4 to get the
7846 original error handler. */
7847
7848 XGetErrorText (display, error->error_code, buf, sizeof (buf));
7849 sprintf (buf1, "X protocol error: %s on protocol request %d",
7850 buf, error->request_code);
7851 x_connection_closed (display, buf1);
7852 }
7853
7854
7855 /* This is the first-level handler for X protocol errors.
7856 It calls x_error_quitter or x_error_catcher. */
7857
7858 static int
7859 x_error_handler (display, error)
7860 Display *display;
7861 XErrorEvent *error;
7862 {
7863 if (! NILP (x_error_message_string))
7864 x_error_catcher (display, error);
7865 else
7866 x_error_quitter (display, error);
7867 return 0;
7868 }
7869
7870 /* This is the handler for X IO errors, always.
7871 It kills all frames on the display that we lost touch with.
7872 If that was the only one, it prints an error message and kills Emacs. */
7873
7874 static int
7875 x_io_error_quitter (display)
7876 Display *display;
7877 {
7878 char buf[256];
7879
7880 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
7881 x_connection_closed (display, buf);
7882 return 0;
7883 }
7884 \f
7885 /* Changing the font of the frame. */
7886
7887 /* Give frame F the font named FONTNAME as its default font, and
7888 return the full name of that font. FONTNAME may be a wildcard
7889 pattern; in that case, we choose some font that fits the pattern.
7890 The return value shows which font we chose. */
7891
7892 Lisp_Object
7893 x_new_font (f, fontname)
7894 struct frame *f;
7895 register char *fontname;
7896 {
7897 struct font_info *fontp
7898 = FS_LOAD_FONT (f, 0, fontname, -1);
7899
7900 if (!fontp)
7901 return Qnil;
7902
7903 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
7904 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
7905 FRAME_FONTSET (f) = -1;
7906
7907 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
7908 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
7909
7910 compute_fringe_widths (f, 1);
7911
7912 /* Compute the scroll bar width in character columns. */
7913 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
7914 {
7915 int wid = FRAME_COLUMN_WIDTH (f);
7916 FRAME_CONFIG_SCROLL_BAR_COLS (f)
7917 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
7918 }
7919 else
7920 {
7921 int wid = FRAME_COLUMN_WIDTH (f);
7922 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
7923 }
7924
7925 /* Now make the frame display the given font. */
7926 if (FRAME_X_WINDOW (f) != 0)
7927 {
7928 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
7929 FRAME_FONT (f)->fid);
7930 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
7931 FRAME_FONT (f)->fid);
7932 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
7933 FRAME_FONT (f)->fid);
7934
7935 /* Don't change the size of a tip frame; there's no point in
7936 doing it because it's done in Fx_show_tip, and it leads to
7937 problems because the tip frame has no widget. */
7938 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
7939 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
7940 }
7941
7942 return build_string (fontp->full_name);
7943 }
7944
7945 /* Give frame F the fontset named FONTSETNAME as its default font, and
7946 return the full name of that fontset. FONTSETNAME may be a wildcard
7947 pattern; in that case, we choose some fontset that fits the pattern.
7948 The return value shows which fontset we chose. */
7949
7950 Lisp_Object
7951 x_new_fontset (f, fontsetname)
7952 struct frame *f;
7953 char *fontsetname;
7954 {
7955 int fontset = fs_query_fontset (build_string (fontsetname), 0);
7956 Lisp_Object result;
7957
7958 if (fontset < 0)
7959 return Qnil;
7960
7961 if (FRAME_FONTSET (f) == fontset)
7962 /* This fontset is already set in frame F. There's nothing more
7963 to do. */
7964 return fontset_name (fontset);
7965
7966 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
7967
7968 if (!STRINGP (result))
7969 /* Can't load ASCII font. */
7970 return Qnil;
7971
7972 /* Since x_new_font doesn't update any fontset information, do it now. */
7973 FRAME_FONTSET (f) = fontset;
7974
7975 #ifdef HAVE_X_I18N
7976 if (FRAME_XIC (f)
7977 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
7978 xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
7979 #endif
7980
7981 return build_string (fontsetname);
7982 }
7983
7984 \f
7985 /***********************************************************************
7986 X Input Methods
7987 ***********************************************************************/
7988
7989 #ifdef HAVE_X_I18N
7990
7991 #ifdef HAVE_X11R6
7992
7993 /* XIM destroy callback function, which is called whenever the
7994 connection to input method XIM dies. CLIENT_DATA contains a
7995 pointer to the x_display_info structure corresponding to XIM. */
7996
7997 static void
7998 xim_destroy_callback (xim, client_data, call_data)
7999 XIM xim;
8000 XPointer client_data;
8001 XPointer call_data;
8002 {
8003 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
8004 Lisp_Object frame, tail;
8005
8006 BLOCK_INPUT;
8007
8008 /* No need to call XDestroyIC.. */
8009 FOR_EACH_FRAME (tail, frame)
8010 {
8011 struct frame *f = XFRAME (frame);
8012 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
8013 {
8014 FRAME_XIC (f) = NULL;
8015 if (FRAME_XIC_FONTSET (f))
8016 {
8017 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
8018 FRAME_XIC_FONTSET (f) = NULL;
8019 }
8020 }
8021 }
8022
8023 /* No need to call XCloseIM. */
8024 dpyinfo->xim = NULL;
8025 XFree (dpyinfo->xim_styles);
8026 UNBLOCK_INPUT;
8027 }
8028
8029 #endif /* HAVE_X11R6 */
8030
8031 #ifdef HAVE_X11R6
8032 /* This isn't prototyped in OSF 5.0 or 5.1a. */
8033 extern char *XSetIMValues P_ ((XIM, ...));
8034 #endif
8035
8036 /* Open the connection to the XIM server on display DPYINFO.
8037 RESOURCE_NAME is the resource name Emacs uses. */
8038
8039 static void
8040 xim_open_dpy (dpyinfo, resource_name)
8041 struct x_display_info *dpyinfo;
8042 char *resource_name;
8043 {
8044 XIM xim;
8045
8046 #ifdef HAVE_XIM
8047 if (use_xim)
8048 {
8049 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
8050 EMACS_CLASS);
8051 dpyinfo->xim = xim;
8052
8053 if (xim)
8054 {
8055 #ifdef HAVE_X11R6
8056 XIMCallback destroy;
8057 #endif
8058
8059 /* Get supported styles and XIM values. */
8060 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
8061
8062 #ifdef HAVE_X11R6
8063 destroy.callback = xim_destroy_callback;
8064 destroy.client_data = (XPointer)dpyinfo;
8065 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
8066 #endif
8067 }
8068 }
8069
8070 else
8071 #endif /* HAVE_XIM */
8072 dpyinfo->xim = NULL;
8073 }
8074
8075
8076 #ifdef HAVE_X11R6_XIM
8077
8078 struct xim_inst_t
8079 {
8080 struct x_display_info *dpyinfo;
8081 char *resource_name;
8082 };
8083
8084 /* XIM instantiate callback function, which is called whenever an XIM
8085 server is available. DISPLAY is the display of the XIM.
8086 CLIENT_DATA contains a pointer to an xim_inst_t structure created
8087 when the callback was registered. */
8088
8089 static void
8090 xim_instantiate_callback (display, client_data, call_data)
8091 Display *display;
8092 XPointer client_data;
8093 XPointer call_data;
8094 {
8095 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
8096 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
8097
8098 /* We don't support multiple XIM connections. */
8099 if (dpyinfo->xim)
8100 return;
8101
8102 xim_open_dpy (dpyinfo, xim_inst->resource_name);
8103
8104 /* Create XIC for the existing frames on the same display, as long
8105 as they have no XIC. */
8106 if (dpyinfo->xim && dpyinfo->reference_count > 0)
8107 {
8108 Lisp_Object tail, frame;
8109
8110 BLOCK_INPUT;
8111 FOR_EACH_FRAME (tail, frame)
8112 {
8113 struct frame *f = XFRAME (frame);
8114
8115 if (FRAME_X_P (f)
8116 && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
8117 if (FRAME_XIC (f) == NULL)
8118 {
8119 create_frame_xic (f);
8120 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
8121 xic_set_statusarea (f);
8122 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
8123 {
8124 struct window *w = XWINDOW (f->selected_window);
8125 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
8126 }
8127 }
8128 }
8129
8130 UNBLOCK_INPUT;
8131 }
8132 }
8133
8134 #endif /* HAVE_X11R6_XIM */
8135
8136
8137 /* Open a connection to the XIM server on display DPYINFO.
8138 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
8139 connection only at the first time. On X11R6, open the connection
8140 in the XIM instantiate callback function. */
8141
8142 static void
8143 xim_initialize (dpyinfo, resource_name)
8144 struct x_display_info *dpyinfo;
8145 char *resource_name;
8146 {
8147 #ifdef HAVE_XIM
8148 if (use_xim)
8149 {
8150 #ifdef HAVE_X11R6_XIM
8151 struct xim_inst_t *xim_inst;
8152 int len;
8153
8154 dpyinfo->xim = NULL;
8155 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
8156 xim_inst->dpyinfo = dpyinfo;
8157 len = strlen (resource_name);
8158 xim_inst->resource_name = (char *) xmalloc (len + 1);
8159 bcopy (resource_name, xim_inst->resource_name, len + 1);
8160 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8161 resource_name, EMACS_CLASS,
8162 xim_instantiate_callback,
8163 /* This is XPointer in XFree86
8164 but (XPointer *) on Tru64, at
8165 least, hence the configure test. */
8166 (XRegisterIMInstantiateCallback_arg6) xim_inst);
8167 #else /* not HAVE_X11R6_XIM */
8168 dpyinfo->xim = NULL;
8169 xim_open_dpy (dpyinfo, resource_name);
8170 #endif /* not HAVE_X11R6_XIM */
8171
8172 }
8173 else
8174 #endif /* HAVE_XIM */
8175 dpyinfo->xim = NULL;
8176 }
8177
8178
8179 /* Close the connection to the XIM server on display DPYINFO. */
8180
8181 static void
8182 xim_close_dpy (dpyinfo)
8183 struct x_display_info *dpyinfo;
8184 {
8185 #ifdef HAVE_XIM
8186 if (use_xim)
8187 {
8188 #ifdef HAVE_X11R6_XIM
8189 if (dpyinfo->display)
8190 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
8191 NULL, EMACS_CLASS,
8192 xim_instantiate_callback, NULL);
8193 #endif /* not HAVE_X11R6_XIM */
8194 if (dpyinfo->display)
8195 XCloseIM (dpyinfo->xim);
8196 dpyinfo->xim = NULL;
8197 XFree (dpyinfo->xim_styles);
8198 }
8199 #endif /* HAVE_XIM */
8200 }
8201
8202 #endif /* not HAVE_X11R6_XIM */
8203
8204
8205 \f
8206 /* Calculate the absolute position in frame F
8207 from its current recorded position values and gravity. */
8208
8209 void
8210 x_calc_absolute_position (f)
8211 struct frame *f;
8212 {
8213 int win_x = 0, win_y = 0;
8214 int flags = f->size_hint_flags;
8215
8216 /* We have nothing to do if the current position
8217 is already for the top-left corner. */
8218 if (! ((flags & XNegative) || (flags & YNegative)))
8219 return;
8220
8221 /* Find the offsets of the outside upper-left corner of
8222 the inner window, with respect to the outer window.
8223 But do this only if we will need the results. */
8224 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
8225 /* This is to get *_pixels_outer_diff. */
8226 x_real_positions (f, &win_x, &win_y);
8227
8228 /* Treat negative positions as relative to the leftmost bottommost
8229 position that fits on the screen. */
8230 if (flags & XNegative)
8231 f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
8232 - 2 * FRAME_X_OUTPUT (f)->x_pixels_outer_diff
8233 - FRAME_PIXEL_WIDTH (f)
8234 + f->left_pos);
8235
8236 {
8237 int height = FRAME_PIXEL_HEIGHT (f);
8238
8239 #if defined USE_X_TOOLKIT && defined USE_MOTIF
8240 /* Something is fishy here. When using Motif, starting Emacs with
8241 `-g -0-0', the frame appears too low by a few pixels.
8242
8243 This seems to be so because initially, while Emacs is starting,
8244 the column widget's height and the frame's pixel height are
8245 different. The column widget's height is the right one. In
8246 later invocations, when Emacs is up, the frame's pixel height
8247 is right, though.
8248
8249 It's not obvious where the initial small difference comes from.
8250 2000-12-01, gerd. */
8251
8252 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
8253 #endif
8254
8255 if (flags & YNegative)
8256 f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
8257 - FRAME_X_OUTPUT (f)->y_pixels_outer_diff
8258
8259 /* Assume the window manager decorations are the same size on
8260 three sides, i.e. left, right and bottom. This is to
8261 compensate for the bottom part. */
8262 - FRAME_X_OUTPUT (f)->x_pixels_outer_diff
8263 - height
8264 + f->top_pos);
8265 }
8266
8267 /* The left_pos and top_pos
8268 are now relative to the top and left screen edges,
8269 so the flags should correspond. */
8270 f->size_hint_flags &= ~ (XNegative | YNegative);
8271 }
8272
8273 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8274 to really change the position, and 0 when calling from
8275 x_make_frame_visible (in that case, XOFF and YOFF are the current
8276 position values). It is -1 when calling from x_set_frame_parameters,
8277 which means, do adjust for borders but don't change the gravity. */
8278
8279 void
8280 x_set_offset (f, xoff, yoff, change_gravity)
8281 struct frame *f;
8282 register int xoff, yoff;
8283 int change_gravity;
8284 {
8285 int modified_top, modified_left;
8286
8287 if (change_gravity > 0)
8288 {
8289 f->top_pos = yoff;
8290 f->left_pos = xoff;
8291 f->size_hint_flags &= ~ (XNegative | YNegative);
8292 if (xoff < 0)
8293 f->size_hint_flags |= XNegative;
8294 if (yoff < 0)
8295 f->size_hint_flags |= YNegative;
8296 f->win_gravity = NorthWestGravity;
8297 }
8298 x_calc_absolute_position (f);
8299
8300 BLOCK_INPUT;
8301 x_wm_set_size_hint (f, (long) 0, 0);
8302
8303 modified_left = f->left_pos;
8304 modified_top = f->top_pos;
8305
8306 if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
8307 {
8308 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8309 than the WM decorations. So we use the calculated offset instead
8310 of the WM decoration sizes here (x/y_pixels_outer_diff). */
8311 modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
8312 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
8313 }
8314
8315 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8316 modified_left, modified_top);
8317
8318 if (FRAME_VISIBLE_P (f)
8319 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
8320 {
8321 FRAME_X_OUTPUT (f)->check_expected_move = 1;
8322 FRAME_X_OUTPUT (f)->expected_top = f->top_pos;
8323 FRAME_X_OUTPUT (f)->expected_left = f->left_pos;
8324 }
8325
8326 UNBLOCK_INPUT;
8327 }
8328
8329 /* Check if we need to resize the frame due to a fullscreen request.
8330 If so needed, resize the frame. */
8331 static void
8332 x_check_fullscreen (f)
8333 struct frame *f;
8334 {
8335 if (f->want_fullscreen & FULLSCREEN_BOTH)
8336 {
8337 int width, height, ign;
8338
8339 x_real_positions (f, &f->left_pos, &f->top_pos);
8340
8341 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
8342
8343 /* We do not need to move the window, it shall be taken care of
8344 when setting WM manager hints.
8345 If the frame is visible already, the position is checked by
8346 x_check_expected_move. */
8347 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
8348 {
8349 change_frame_size (f, height, width, 0, 1, 0);
8350 SET_FRAME_GARBAGED (f);
8351 cancel_mouse_face (f);
8352
8353 /* Wait for the change of frame size to occur */
8354 f->want_fullscreen |= FULLSCREEN_WAIT;
8355 }
8356 }
8357 }
8358
8359 /* If frame parameters are set after the frame is mapped, we need to move
8360 the window.
8361 Some window managers moves the window to the right position, some
8362 moves the outer window manager window to the specified position.
8363 Here we check that we are in the right spot. If not, make a second
8364 move, assuming we are dealing with the second kind of window manager. */
8365 static void
8366 x_check_expected_move (f)
8367 struct frame *f;
8368 {
8369 if (FRAME_X_OUTPUT (f)->check_expected_move)
8370 {
8371 int expect_top = FRAME_X_OUTPUT (f)->expected_top;
8372 int expect_left = FRAME_X_OUTPUT (f)->expected_left;
8373
8374 if (expect_top != f->top_pos || expect_left != f->left_pos)
8375 {
8376 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
8377 FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
8378 FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
8379
8380 x_set_offset (f, expect_left, expect_top, 1);
8381 }
8382 else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
8383 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
8384
8385 /* Just do this once */
8386 FRAME_X_OUTPUT (f)->check_expected_move = 0;
8387 }
8388 }
8389
8390
8391 /* Change the size of frame F's X window to COLS/ROWS in the case F
8392 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
8393 top-left-corner window gravity for this size change and subsequent
8394 size changes. Otherwise we leave the window gravity unchanged. */
8395
8396 static void
8397 x_set_window_size_1 (f, change_gravity, cols, rows)
8398 struct frame *f;
8399 int change_gravity;
8400 int cols, rows;
8401 {
8402 int pixelwidth, pixelheight;
8403
8404 check_frame_size (f, &rows, &cols);
8405 f->scroll_bar_actual_width
8406 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
8407 ? 0
8408 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
8409 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
8410 : (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)));
8411
8412 compute_fringe_widths (f, 0);
8413
8414 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
8415 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
8416
8417 f->win_gravity = NorthWestGravity;
8418 x_wm_set_size_hint (f, (long) 0, 0);
8419
8420 XSync (FRAME_X_DISPLAY (f), False);
8421 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8422 pixelwidth, pixelheight);
8423
8424 /* Now, strictly speaking, we can't be sure that this is accurate,
8425 but the window manager will get around to dealing with the size
8426 change request eventually, and we'll hear how it went when the
8427 ConfigureNotify event gets here.
8428
8429 We could just not bother storing any of this information here,
8430 and let the ConfigureNotify event set everything up, but that
8431 might be kind of confusing to the Lisp code, since size changes
8432 wouldn't be reported in the frame parameters until some random
8433 point in the future when the ConfigureNotify event arrives.
8434
8435 We pass 1 for DELAY since we can't run Lisp code inside of
8436 a BLOCK_INPUT. */
8437 change_frame_size (f, rows, cols, 0, 1, 0);
8438 FRAME_PIXEL_WIDTH (f) = pixelwidth;
8439 FRAME_PIXEL_HEIGHT (f) = pixelheight;
8440
8441 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8442 receive in the ConfigureNotify event; if we get what we asked
8443 for, then the event won't cause the screen to become garbaged, so
8444 we have to make sure to do it here. */
8445 SET_FRAME_GARBAGED (f);
8446
8447 XFlush (FRAME_X_DISPLAY (f));
8448 }
8449
8450
8451 /* Call this to change the size of frame F's x-window.
8452 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8453 for this size change and subsequent size changes.
8454 Otherwise we leave the window gravity unchanged. */
8455
8456 void
8457 x_set_window_size (f, change_gravity, cols, rows)
8458 struct frame *f;
8459 int change_gravity;
8460 int cols, rows;
8461 {
8462 BLOCK_INPUT;
8463
8464 #ifdef USE_GTK
8465 if (FRAME_GTK_WIDGET (f))
8466 xg_frame_set_char_size (f, cols, rows);
8467 else
8468 x_set_window_size_1 (f, change_gravity, cols, rows);
8469 #elif USE_X_TOOLKIT
8470
8471 if (f->output_data.x->widget != NULL)
8472 {
8473 /* The x and y position of the widget is clobbered by the
8474 call to XtSetValues within EmacsFrameSetCharSize.
8475 This is a real kludge, but I don't understand Xt so I can't
8476 figure out a correct fix. Can anyone else tell me? -- rms. */
8477 int xpos = f->output_data.x->widget->core.x;
8478 int ypos = f->output_data.x->widget->core.y;
8479 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
8480 f->output_data.x->widget->core.x = xpos;
8481 f->output_data.x->widget->core.y = ypos;
8482 }
8483 else
8484 x_set_window_size_1 (f, change_gravity, cols, rows);
8485
8486 #else /* not USE_X_TOOLKIT */
8487
8488 x_set_window_size_1 (f, change_gravity, cols, rows);
8489
8490 #endif /* not USE_X_TOOLKIT */
8491
8492 /* If cursor was outside the new size, mark it as off. */
8493 mark_window_cursors_off (XWINDOW (f->root_window));
8494
8495 /* Clear out any recollection of where the mouse highlighting was,
8496 since it might be in a place that's outside the new frame size.
8497 Actually checking whether it is outside is a pain in the neck,
8498 so don't try--just let the highlighting be done afresh with new size. */
8499 cancel_mouse_face (f);
8500
8501 UNBLOCK_INPUT;
8502 }
8503 \f
8504 /* Mouse warping. */
8505
8506 void
8507 x_set_mouse_position (f, x, y)
8508 struct frame *f;
8509 int x, y;
8510 {
8511 int pix_x, pix_y;
8512
8513 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
8514 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
8515
8516 if (pix_x < 0) pix_x = 0;
8517 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
8518
8519 if (pix_y < 0) pix_y = 0;
8520 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
8521
8522 BLOCK_INPUT;
8523
8524 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8525 0, 0, 0, 0, pix_x, pix_y);
8526 UNBLOCK_INPUT;
8527 }
8528
8529 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
8530
8531 void
8532 x_set_mouse_pixel_position (f, pix_x, pix_y)
8533 struct frame *f;
8534 int pix_x, pix_y;
8535 {
8536 BLOCK_INPUT;
8537
8538 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
8539 0, 0, 0, 0, pix_x, pix_y);
8540 UNBLOCK_INPUT;
8541 }
8542 \f
8543 /* focus shifting, raising and lowering. */
8544
8545 void
8546 x_focus_on_frame (f)
8547 struct frame *f;
8548 {
8549 #if 0 /* This proves to be unpleasant. */
8550 x_raise_frame (f);
8551 #endif
8552 #if 0
8553 /* I don't think that the ICCCM allows programs to do things like this
8554 without the interaction of the window manager. Whatever you end up
8555 doing with this code, do it to x_unfocus_frame too. */
8556 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8557 RevertToPointerRoot, CurrentTime);
8558 #endif /* ! 0 */
8559 }
8560
8561 void
8562 x_unfocus_frame (f)
8563 struct frame *f;
8564 {
8565 #if 0
8566 /* Look at the remarks in x_focus_on_frame. */
8567 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
8568 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
8569 RevertToPointerRoot, CurrentTime);
8570 #endif /* ! 0 */
8571 }
8572
8573 /* Raise frame F. */
8574
8575 void
8576 x_raise_frame (f)
8577 struct frame *f;
8578 {
8579 if (f->async_visible)
8580 {
8581 BLOCK_INPUT;
8582 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8583 XFlush (FRAME_X_DISPLAY (f));
8584 UNBLOCK_INPUT;
8585 }
8586 }
8587
8588 /* Lower frame F. */
8589
8590 void
8591 x_lower_frame (f)
8592 struct frame *f;
8593 {
8594 if (f->async_visible)
8595 {
8596 BLOCK_INPUT;
8597 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8598 XFlush (FRAME_X_DISPLAY (f));
8599 UNBLOCK_INPUT;
8600 }
8601 }
8602
8603 static void
8604 XTframe_raise_lower (f, raise_flag)
8605 FRAME_PTR f;
8606 int raise_flag;
8607 {
8608 if (raise_flag)
8609 x_raise_frame (f);
8610 else
8611 x_lower_frame (f);
8612 }
8613 \f
8614 /* Change of visibility. */
8615
8616 /* This tries to wait until the frame is really visible.
8617 However, if the window manager asks the user where to position
8618 the frame, this will return before the user finishes doing that.
8619 The frame will not actually be visible at that time,
8620 but it will become visible later when the window manager
8621 finishes with it. */
8622
8623 void
8624 x_make_frame_visible (f)
8625 struct frame *f;
8626 {
8627 Lisp_Object type;
8628 int original_top, original_left;
8629 int retry_count = 2;
8630
8631 retry:
8632
8633 BLOCK_INPUT;
8634
8635 type = x_icon_type (f);
8636 if (!NILP (type))
8637 x_bitmap_icon (f, type);
8638
8639 if (! FRAME_VISIBLE_P (f))
8640 {
8641 /* We test FRAME_GARBAGED_P here to make sure we don't
8642 call x_set_offset a second time
8643 if we get to x_make_frame_visible a second time
8644 before the window gets really visible. */
8645 if (! FRAME_ICONIFIED_P (f)
8646 && ! f->output_data.x->asked_for_visible)
8647 x_set_offset (f, f->left_pos, f->top_pos, 0);
8648
8649 f->output_data.x->asked_for_visible = 1;
8650
8651 if (! EQ (Vx_no_window_manager, Qt))
8652 x_wm_set_window_state (f, NormalState);
8653 #ifdef USE_X_TOOLKIT
8654 /* This was XtPopup, but that did nothing for an iconified frame. */
8655 XtMapWidget (f->output_data.x->widget);
8656 #else /* not USE_X_TOOLKIT */
8657 #ifdef USE_GTK
8658 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
8659 gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
8660 #else
8661 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
8662 #endif /* not USE_GTK */
8663 #endif /* not USE_X_TOOLKIT */
8664 #if 0 /* This seems to bring back scroll bars in the wrong places
8665 if the window configuration has changed. They seem
8666 to come back ok without this. */
8667 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8668 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
8669 #endif
8670 }
8671
8672 XFlush (FRAME_X_DISPLAY (f));
8673
8674 /* Synchronize to ensure Emacs knows the frame is visible
8675 before we do anything else. We do this loop with input not blocked
8676 so that incoming events are handled. */
8677 {
8678 Lisp_Object frame;
8679 int count;
8680 /* This must be before UNBLOCK_INPUT
8681 since events that arrive in response to the actions above
8682 will set it when they are handled. */
8683 int previously_visible = f->output_data.x->has_been_visible;
8684
8685 original_left = f->left_pos;
8686 original_top = f->top_pos;
8687
8688 /* This must come after we set COUNT. */
8689 UNBLOCK_INPUT;
8690
8691 /* We unblock here so that arriving X events are processed. */
8692
8693 /* Now move the window back to where it was "supposed to be".
8694 But don't do it if the gravity is negative.
8695 When the gravity is negative, this uses a position
8696 that is 3 pixels too low. Perhaps that's really the border width.
8697
8698 Don't do this if the window has never been visible before,
8699 because the window manager may choose the position
8700 and we don't want to override it. */
8701
8702 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
8703 && f->win_gravity == NorthWestGravity
8704 && previously_visible)
8705 {
8706 Drawable rootw;
8707 int x, y;
8708 unsigned int width, height, border, depth;
8709
8710 BLOCK_INPUT;
8711
8712 /* On some window managers (such as FVWM) moving an existing
8713 window, even to the same place, causes the window manager
8714 to introduce an offset. This can cause the window to move
8715 to an unexpected location. Check the geometry (a little
8716 slow here) and then verify that the window is in the right
8717 place. If the window is not in the right place, move it
8718 there, and take the potential window manager hit. */
8719 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8720 &rootw, &x, &y, &width, &height, &border, &depth);
8721
8722 if (original_left != x || original_top != y)
8723 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8724 original_left, original_top);
8725
8726 UNBLOCK_INPUT;
8727 }
8728
8729 XSETFRAME (frame, f);
8730
8731 /* Wait until the frame is visible. Process X events until a
8732 MapNotify event has been seen, or until we think we won't get a
8733 MapNotify at all.. */
8734 for (count = input_signal_count + 10;
8735 input_signal_count < count && !FRAME_VISIBLE_P (f);)
8736 {
8737 /* Force processing of queued events. */
8738 x_sync (f);
8739
8740 /* Machines that do polling rather than SIGIO have been
8741 observed to go into a busy-wait here. So we'll fake an
8742 alarm signal to let the handler know that there's something
8743 to be read. We used to raise a real alarm, but it seems
8744 that the handler isn't always enabled here. This is
8745 probably a bug. */
8746 if (input_polling_used ())
8747 {
8748 /* It could be confusing if a real alarm arrives while
8749 processing the fake one. Turn it off and let the
8750 handler reset it. */
8751 extern void poll_for_input_1 P_ ((void));
8752 int old_poll_suppress_count = poll_suppress_count;
8753 poll_suppress_count = 1;
8754 poll_for_input_1 ();
8755 poll_suppress_count = old_poll_suppress_count;
8756 }
8757
8758 /* See if a MapNotify event has been processed. */
8759 FRAME_SAMPLE_VISIBILITY (f);
8760 }
8761
8762 /* 2000-09-28: In
8763
8764 (let ((f (selected-frame)))
8765 (iconify-frame f)
8766 (raise-frame f))
8767
8768 the frame is not raised with various window managers on
8769 FreeBSD, GNU/Linux and Solaris. It turns out that, for some
8770 unknown reason, the call to XtMapWidget is completely ignored.
8771 Mapping the widget a second time works. */
8772
8773 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
8774 goto retry;
8775 }
8776 }
8777
8778 /* Change from mapped state to withdrawn state. */
8779
8780 /* Make the frame visible (mapped and not iconified). */
8781
8782 void
8783 x_make_frame_invisible (f)
8784 struct frame *f;
8785 {
8786 Window window;
8787
8788 /* Use the frame's outermost window, not the one we normally draw on. */
8789 window = FRAME_OUTER_WINDOW (f);
8790
8791 /* Don't keep the highlight on an invisible frame. */
8792 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
8793 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
8794
8795 #if 0/* This might add unreliability; I don't trust it -- rms. */
8796 if (! f->async_visible && ! f->async_iconified)
8797 return;
8798 #endif
8799
8800 BLOCK_INPUT;
8801
8802 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
8803 that the current position of the window is user-specified, rather than
8804 program-specified, so that when the window is mapped again, it will be
8805 placed at the same location, without forcing the user to position it
8806 by hand again (they have already done that once for this window.) */
8807 x_wm_set_size_hint (f, (long) 0, 1);
8808
8809 #ifdef USE_GTK
8810 if (FRAME_GTK_OUTER_WIDGET (f))
8811 gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
8812 else
8813 #endif
8814 {
8815 #ifdef HAVE_X11R4
8816
8817 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
8818 DefaultScreen (FRAME_X_DISPLAY (f))))
8819 {
8820 UNBLOCK_INPUT_RESIGNAL;
8821 error ("Can't notify window manager of window withdrawal");
8822 }
8823 #else /* ! defined (HAVE_X11R4) */
8824
8825 /* Tell the window manager what we're going to do. */
8826 if (! EQ (Vx_no_window_manager, Qt))
8827 {
8828 XEvent unmap;
8829
8830 unmap.xunmap.type = UnmapNotify;
8831 unmap.xunmap.window = window;
8832 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
8833 unmap.xunmap.from_configure = False;
8834 if (! XSendEvent (FRAME_X_DISPLAY (f),
8835 DefaultRootWindow (FRAME_X_DISPLAY (f)),
8836 False,
8837 SubstructureRedirectMaskSubstructureNotifyMask,
8838 &unmap))
8839 {
8840 UNBLOCK_INPUT_RESIGNAL;
8841 error ("Can't notify window manager of withdrawal");
8842 }
8843 }
8844
8845 /* Unmap the window ourselves. Cheeky! */
8846 XUnmapWindow (FRAME_X_DISPLAY (f), window);
8847 #endif /* ! defined (HAVE_X11R4) */
8848 }
8849
8850 /* We can't distinguish this from iconification
8851 just by the event that we get from the server.
8852 So we can't win using the usual strategy of letting
8853 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
8854 and synchronize with the server to make sure we agree. */
8855 f->visible = 0;
8856 FRAME_ICONIFIED_P (f) = 0;
8857 f->async_visible = 0;
8858 f->async_iconified = 0;
8859
8860 x_sync (f);
8861
8862 UNBLOCK_INPUT;
8863 }
8864
8865 /* Change window state from mapped to iconified. */
8866
8867 void
8868 x_iconify_frame (f)
8869 struct frame *f;
8870 {
8871 int result;
8872 Lisp_Object type;
8873
8874 /* Don't keep the highlight on an invisible frame. */
8875 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
8876 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
8877
8878 if (f->async_iconified)
8879 return;
8880
8881 BLOCK_INPUT;
8882
8883 FRAME_SAMPLE_VISIBILITY (f);
8884
8885 type = x_icon_type (f);
8886 if (!NILP (type))
8887 x_bitmap_icon (f, type);
8888
8889 #ifdef USE_GTK
8890 if (FRAME_GTK_OUTER_WIDGET (f))
8891 {
8892 if (! FRAME_VISIBLE_P (f))
8893 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
8894
8895 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
8896 f->iconified = 1;
8897 f->visible = 1;
8898 f->async_iconified = 1;
8899 f->async_visible = 0;
8900 UNBLOCK_INPUT;
8901 return;
8902 }
8903 #endif
8904
8905 #ifdef USE_X_TOOLKIT
8906
8907 if (! FRAME_VISIBLE_P (f))
8908 {
8909 if (! EQ (Vx_no_window_manager, Qt))
8910 x_wm_set_window_state (f, IconicState);
8911 /* This was XtPopup, but that did nothing for an iconified frame. */
8912 XtMapWidget (f->output_data.x->widget);
8913 /* The server won't give us any event to indicate
8914 that an invisible frame was changed to an icon,
8915 so we have to record it here. */
8916 f->iconified = 1;
8917 f->visible = 1;
8918 f->async_iconified = 1;
8919 f->async_visible = 0;
8920 UNBLOCK_INPUT;
8921 return;
8922 }
8923
8924 result = XIconifyWindow (FRAME_X_DISPLAY (f),
8925 XtWindow (f->output_data.x->widget),
8926 DefaultScreen (FRAME_X_DISPLAY (f)));
8927 UNBLOCK_INPUT;
8928
8929 if (!result)
8930 error ("Can't notify window manager of iconification");
8931
8932 f->async_iconified = 1;
8933 f->async_visible = 0;
8934
8935
8936 BLOCK_INPUT;
8937 XFlush (FRAME_X_DISPLAY (f));
8938 UNBLOCK_INPUT;
8939 #else /* not USE_X_TOOLKIT */
8940
8941 /* Make sure the X server knows where the window should be positioned,
8942 in case the user deiconifies with the window manager. */
8943 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
8944 x_set_offset (f, f->left_pos, f->top_pos, 0);
8945
8946 /* Since we don't know which revision of X we're running, we'll use both
8947 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
8948
8949 /* X11R4: send a ClientMessage to the window manager using the
8950 WM_CHANGE_STATE type. */
8951 {
8952 XEvent message;
8953
8954 message.xclient.window = FRAME_X_WINDOW (f);
8955 message.xclient.type = ClientMessage;
8956 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
8957 message.xclient.format = 32;
8958 message.xclient.data.l[0] = IconicState;
8959
8960 if (! XSendEvent (FRAME_X_DISPLAY (f),
8961 DefaultRootWindow (FRAME_X_DISPLAY (f)),
8962 False,
8963 SubstructureRedirectMask | SubstructureNotifyMask,
8964 &message))
8965 {
8966 UNBLOCK_INPUT_RESIGNAL;
8967 error ("Can't notify window manager of iconification");
8968 }
8969 }
8970
8971 /* X11R3: set the initial_state field of the window manager hints to
8972 IconicState. */
8973 x_wm_set_window_state (f, IconicState);
8974
8975 if (!FRAME_VISIBLE_P (f))
8976 {
8977 /* If the frame was withdrawn, before, we must map it. */
8978 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
8979 }
8980
8981 f->async_iconified = 1;
8982 f->async_visible = 0;
8983
8984 XFlush (FRAME_X_DISPLAY (f));
8985 UNBLOCK_INPUT;
8986 #endif /* not USE_X_TOOLKIT */
8987 }
8988
8989 \f
8990 /* Free X resources of frame F. */
8991
8992 void
8993 x_free_frame_resources (f)
8994 struct frame *f;
8995 {
8996 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8997 Lisp_Object bar;
8998 struct scroll_bar *b;
8999
9000 BLOCK_INPUT;
9001
9002 /* If a display connection is dead, don't try sending more
9003 commands to the X server. */
9004 if (dpyinfo->display)
9005 {
9006 if (f->output_data.x->icon_desc)
9007 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
9008
9009 #ifdef USE_X_TOOLKIT
9010 /* Explicitly destroy the scroll bars of the frame. Without
9011 this, we get "BadDrawable" errors from the toolkit later on,
9012 presumably from expose events generated for the disappearing
9013 toolkit scroll bars. */
9014 for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
9015 {
9016 b = XSCROLL_BAR (bar);
9017 x_scroll_bar_remove (b);
9018 }
9019 #endif
9020
9021 #ifdef HAVE_X_I18N
9022 if (FRAME_XIC (f))
9023 free_frame_xic (f);
9024 #endif
9025
9026 #ifdef USE_X_TOOLKIT
9027 if (f->output_data.x->widget)
9028 {
9029 XtDestroyWidget (f->output_data.x->widget);
9030 f->output_data.x->widget = NULL;
9031 }
9032 /* Tooltips don't have widgets, only a simple X window, even if
9033 we are using a toolkit. */
9034 else if (FRAME_X_WINDOW (f))
9035 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9036
9037 free_frame_menubar (f);
9038 #else /* !USE_X_TOOLKIT */
9039
9040 #ifdef USE_GTK
9041 /* In the GTK version, tooltips are normal X
9042 frames. We must check and free both types. */
9043 if (FRAME_GTK_OUTER_WIDGET (f))
9044 {
9045 gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
9046 FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
9047 FRAME_GTK_OUTER_WIDGET (f) = 0;
9048 }
9049 #endif /* USE_GTK */
9050
9051 if (FRAME_X_WINDOW (f))
9052 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9053 #endif /* !USE_X_TOOLKIT */
9054
9055 unload_color (f, f->output_data.x->foreground_pixel);
9056 unload_color (f, f->output_data.x->background_pixel);
9057 unload_color (f, f->output_data.x->cursor_pixel);
9058 unload_color (f, f->output_data.x->cursor_foreground_pixel);
9059 unload_color (f, f->output_data.x->border_pixel);
9060 unload_color (f, f->output_data.x->mouse_pixel);
9061
9062 if (f->output_data.x->scroll_bar_background_pixel != -1)
9063 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
9064 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9065 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
9066 #ifdef USE_TOOLKIT_SCROLL_BARS
9067 /* Scrollbar shadow colors. */
9068 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
9069 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
9070 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
9071 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
9072 #endif /* USE_TOOLKIT_SCROLL_BARS */
9073 if (f->output_data.x->white_relief.allocated_p)
9074 unload_color (f, f->output_data.x->white_relief.pixel);
9075 if (f->output_data.x->black_relief.allocated_p)
9076 unload_color (f, f->output_data.x->black_relief.pixel);
9077
9078 if (FRAME_FACE_CACHE (f))
9079 free_frame_faces (f);
9080
9081 x_free_gcs (f);
9082 XFlush (FRAME_X_DISPLAY (f));
9083 }
9084
9085 if (f->output_data.x->saved_menu_event)
9086 xfree (f->output_data.x->saved_menu_event);
9087
9088 xfree (f->output_data.x);
9089 f->output_data.x = NULL;
9090
9091 if (f == dpyinfo->x_focus_frame)
9092 dpyinfo->x_focus_frame = 0;
9093 if (f == dpyinfo->x_focus_event_frame)
9094 dpyinfo->x_focus_event_frame = 0;
9095 if (f == dpyinfo->x_highlight_frame)
9096 dpyinfo->x_highlight_frame = 0;
9097
9098 if (f == dpyinfo->mouse_face_mouse_frame)
9099 {
9100 dpyinfo->mouse_face_beg_row
9101 = dpyinfo->mouse_face_beg_col = -1;
9102 dpyinfo->mouse_face_end_row
9103 = dpyinfo->mouse_face_end_col = -1;
9104 dpyinfo->mouse_face_window = Qnil;
9105 dpyinfo->mouse_face_deferred_gc = 0;
9106 dpyinfo->mouse_face_mouse_frame = 0;
9107 }
9108
9109 UNBLOCK_INPUT;
9110 }
9111
9112
9113 /* Destroy the X window of frame F. */
9114
9115 void
9116 x_destroy_window (f)
9117 struct frame *f;
9118 {
9119 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9120
9121 /* If a display connection is dead, don't try sending more
9122 commands to the X server. */
9123 if (dpyinfo->display != 0)
9124 x_free_frame_resources (f);
9125
9126 dpyinfo->reference_count--;
9127 }
9128
9129 \f
9130 /* Setting window manager hints. */
9131
9132 /* Set the normal size hints for the window manager, for frame F.
9133 FLAGS is the flags word to use--or 0 meaning preserve the flags
9134 that the window now has.
9135 If USER_POSITION is nonzero, we set the USPosition
9136 flag (this is useful when FLAGS is 0).
9137 The GTK version is in gtkutils.c */
9138
9139 #ifndef USE_GTK
9140 void
9141 x_wm_set_size_hint (f, flags, user_position)
9142 struct frame *f;
9143 long flags;
9144 int user_position;
9145 {
9146 XSizeHints size_hints;
9147
9148 #ifdef USE_X_TOOLKIT
9149 Arg al[2];
9150 int ac = 0;
9151 Dimension widget_width, widget_height;
9152 #endif
9153
9154 Window window = FRAME_OUTER_WINDOW (f);
9155
9156 /* Setting PMaxSize caused various problems. */
9157 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
9158
9159 size_hints.x = f->left_pos;
9160 size_hints.y = f->top_pos;
9161
9162 #ifdef USE_X_TOOLKIT
9163 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
9164 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
9165 XtGetValues (f->output_data.x->widget, al, ac);
9166 size_hints.height = widget_height;
9167 size_hints.width = widget_width;
9168 #else /* not USE_X_TOOLKIT */
9169 size_hints.height = FRAME_PIXEL_HEIGHT (f);
9170 size_hints.width = FRAME_PIXEL_WIDTH (f);
9171 #endif /* not USE_X_TOOLKIT */
9172
9173 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
9174 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
9175 size_hints.max_width
9176 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9177 size_hints.max_height
9178 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9179
9180 /* Calculate the base and minimum sizes.
9181
9182 (When we use the X toolkit, we don't do it here.
9183 Instead we copy the values that the widgets are using, below.) */
9184 #ifndef USE_X_TOOLKIT
9185 {
9186 int base_width, base_height;
9187 int min_rows = 0, min_cols = 0;
9188
9189 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
9190 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
9191
9192 check_frame_size (f, &min_rows, &min_cols);
9193
9194 /* The window manager uses the base width hints to calculate the
9195 current number of rows and columns in the frame while
9196 resizing; min_width and min_height aren't useful for this
9197 purpose, since they might not give the dimensions for a
9198 zero-row, zero-column frame.
9199
9200 We use the base_width and base_height members if we have
9201 them; otherwise, we set the min_width and min_height members
9202 to the size for a zero x zero frame. */
9203
9204 #ifdef HAVE_X11R4
9205 size_hints.flags |= PBaseSize;
9206 size_hints.base_width = base_width;
9207 size_hints.base_height = base_height;
9208 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
9209 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
9210 #else
9211 size_hints.min_width = base_width;
9212 size_hints.min_height = base_height;
9213 #endif
9214 }
9215
9216 /* If we don't need the old flags, we don't need the old hint at all. */
9217 if (flags)
9218 {
9219 size_hints.flags |= flags;
9220 goto no_read;
9221 }
9222 #endif /* not USE_X_TOOLKIT */
9223
9224 {
9225 XSizeHints hints; /* Sometimes I hate X Windows... */
9226 long supplied_return;
9227 int value;
9228
9229 #ifdef HAVE_X11R4
9230 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
9231 &supplied_return);
9232 #else
9233 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
9234 #endif
9235
9236 #ifdef USE_X_TOOLKIT
9237 size_hints.base_height = hints.base_height;
9238 size_hints.base_width = hints.base_width;
9239 size_hints.min_height = hints.min_height;
9240 size_hints.min_width = hints.min_width;
9241 #endif
9242
9243 if (flags)
9244 size_hints.flags |= flags;
9245 else
9246 {
9247 if (value == 0)
9248 hints.flags = 0;
9249 if (hints.flags & PSize)
9250 size_hints.flags |= PSize;
9251 if (hints.flags & PPosition)
9252 size_hints.flags |= PPosition;
9253 if (hints.flags & USPosition)
9254 size_hints.flags |= USPosition;
9255 if (hints.flags & USSize)
9256 size_hints.flags |= USSize;
9257 }
9258 }
9259
9260 #ifndef USE_X_TOOLKIT
9261 no_read:
9262 #endif
9263
9264 #ifdef PWinGravity
9265 size_hints.win_gravity = f->win_gravity;
9266 size_hints.flags |= PWinGravity;
9267
9268 if (user_position)
9269 {
9270 size_hints.flags &= ~ PPosition;
9271 size_hints.flags |= USPosition;
9272 }
9273 #endif /* PWinGravity */
9274
9275 #ifdef HAVE_X11R4
9276 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9277 #else
9278 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9279 #endif
9280 }
9281 #endif /* not USE_GTK */
9282
9283 /* Used for IconicState or NormalState */
9284
9285 void
9286 x_wm_set_window_state (f, state)
9287 struct frame *f;
9288 int state;
9289 {
9290 #ifdef USE_X_TOOLKIT
9291 Arg al[1];
9292
9293 XtSetArg (al[0], XtNinitialState, state);
9294 XtSetValues (f->output_data.x->widget, al, 1);
9295 #else /* not USE_X_TOOLKIT */
9296 Window window = FRAME_X_WINDOW (f);
9297
9298 f->output_data.x->wm_hints.flags |= StateHint;
9299 f->output_data.x->wm_hints.initial_state = state;
9300
9301 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9302 #endif /* not USE_X_TOOLKIT */
9303 }
9304
9305 void
9306 x_wm_set_icon_pixmap (f, pixmap_id)
9307 struct frame *f;
9308 int pixmap_id;
9309 {
9310 Pixmap icon_pixmap, icon_mask;
9311
9312 #ifndef USE_X_TOOLKIT
9313 Window window = FRAME_OUTER_WINDOW (f);
9314 #endif
9315
9316 if (pixmap_id > 0)
9317 {
9318 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
9319 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
9320 icon_mask = x_bitmap_mask (f, pixmap_id);
9321 f->output_data.x->wm_hints.icon_mask = icon_mask;
9322 }
9323 else
9324 {
9325 /* It seems there is no way to turn off use of an icon pixmap.
9326 The following line does it, only if no icon has yet been created,
9327 for some window managers. But with mwm it crashes.
9328 Some people say it should clear the IconPixmapHint bit in this case,
9329 but that doesn't work, and the X consortium said it isn't the
9330 right thing at all. Since there is no way to win,
9331 best to explicitly give up. */
9332 #if 0
9333 f->output_data.x->wm_hints.icon_pixmap = None;
9334 f->output_data.x->wm_hints.icon_mask = None;
9335 #else
9336 return;
9337 #endif
9338 }
9339
9340 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
9341
9342 {
9343 Arg al[1];
9344 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
9345 XtSetValues (f->output_data.x->widget, al, 1);
9346 XtSetArg (al[0], XtNiconMask, icon_mask);
9347 XtSetValues (f->output_data.x->widget, al, 1);
9348 }
9349
9350 #else /* not USE_X_TOOLKIT */
9351
9352 f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
9353 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9354
9355 #endif /* not USE_X_TOOLKIT */
9356 }
9357
9358 void
9359 x_wm_set_icon_position (f, icon_x, icon_y)
9360 struct frame *f;
9361 int icon_x, icon_y;
9362 {
9363 Window window = FRAME_OUTER_WINDOW (f);
9364
9365 f->output_data.x->wm_hints.flags |= IconPositionHint;
9366 f->output_data.x->wm_hints.icon_x = icon_x;
9367 f->output_data.x->wm_hints.icon_y = icon_y;
9368
9369 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9370 }
9371
9372 \f
9373 /***********************************************************************
9374 Fonts
9375 ***********************************************************************/
9376
9377 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
9378
9379 struct font_info *
9380 x_get_font_info (f, font_idx)
9381 FRAME_PTR f;
9382 int font_idx;
9383 {
9384 return (FRAME_X_FONT_TABLE (f) + font_idx);
9385 }
9386
9387
9388 /* Return a list of names of available fonts matching PATTERN on frame F.
9389
9390 If SIZE is > 0, it is the size (maximum bounds width) of fonts
9391 to be listed.
9392
9393 SIZE < 0 means include scalable fonts.
9394
9395 Frame F null means we have not yet created any frame on X, and
9396 consult the first display in x_display_list. MAXNAMES sets a limit
9397 on how many fonts to match. */
9398
9399 Lisp_Object
9400 x_list_fonts (f, pattern, size, maxnames)
9401 struct frame *f;
9402 Lisp_Object pattern;
9403 int size;
9404 int maxnames;
9405 {
9406 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
9407 Lisp_Object tem, second_best;
9408 struct x_display_info *dpyinfo
9409 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
9410 Display *dpy = dpyinfo->display;
9411 int try_XLoadQueryFont = 0;
9412 int count;
9413 int allow_auto_scaled_font = 0;
9414
9415 if (size < 0)
9416 {
9417 allow_auto_scaled_font = 1;
9418 size = 0;
9419 }
9420
9421 patterns = Fassoc (pattern, Valternate_fontname_alist);
9422 if (NILP (patterns))
9423 patterns = Fcons (pattern, Qnil);
9424
9425 if (maxnames == 1 && !size)
9426 /* We can return any single font matching PATTERN. */
9427 try_XLoadQueryFont = 1;
9428
9429 for (; CONSP (patterns); patterns = XCDR (patterns))
9430 {
9431 int num_fonts;
9432 char **names = NULL;
9433
9434 pattern = XCAR (patterns);
9435 /* See if we cached the result for this particular query.
9436 The cache is an alist of the form:
9437 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
9438 tem = XCDR (dpyinfo->name_list_element);
9439 key = Fcons (Fcons (pattern, make_number (maxnames)),
9440 allow_auto_scaled_font ? Qt : Qnil);
9441 list = Fassoc (key, tem);
9442 if (!NILP (list))
9443 {
9444 list = Fcdr_safe (list);
9445 /* We have a cashed list. Don't have to get the list again. */
9446 goto label_cached;
9447 }
9448
9449 /* At first, put PATTERN in the cache. */
9450
9451 BLOCK_INPUT;
9452 count = x_catch_errors (dpy);
9453
9454 if (try_XLoadQueryFont)
9455 {
9456 XFontStruct *font;
9457 unsigned long value;
9458
9459 font = XLoadQueryFont (dpy, SDATA (pattern));
9460 if (x_had_errors_p (dpy))
9461 {
9462 /* This error is perhaps due to insufficient memory on X
9463 server. Let's just ignore it. */
9464 font = NULL;
9465 x_clear_errors (dpy);
9466 }
9467
9468 if (font
9469 && XGetFontProperty (font, XA_FONT, &value))
9470 {
9471 char *name = (char *) XGetAtomName (dpy, (Atom) value);
9472 int len = strlen (name);
9473 char *tmp;
9474
9475 /* If DXPC (a Differential X Protocol Compressor)
9476 Ver.3.7 is running, XGetAtomName will return null
9477 string. We must avoid such a name. */
9478 if (len == 0)
9479 try_XLoadQueryFont = 0;
9480 else
9481 {
9482 num_fonts = 1;
9483 names = (char **) alloca (sizeof (char *));
9484 /* Some systems only allow alloca assigned to a
9485 simple var. */
9486 tmp = (char *) alloca (len + 1); names[0] = tmp;
9487 bcopy (name, names[0], len + 1);
9488 XFree (name);
9489 }
9490 }
9491 else
9492 try_XLoadQueryFont = 0;
9493
9494 if (font)
9495 XFreeFont (dpy, font);
9496 }
9497
9498 if (!try_XLoadQueryFont)
9499 {
9500 /* We try at least 10 fonts because XListFonts will return
9501 auto-scaled fonts at the head. */
9502 if (maxnames < 0)
9503 {
9504 int limit;
9505
9506 for (limit = 500;;)
9507 {
9508 names = XListFonts (dpy, SDATA (pattern), limit, &num_fonts);
9509 if (num_fonts == limit)
9510 {
9511 BLOCK_INPUT;
9512 XFreeFontNames (names);
9513 UNBLOCK_INPUT;
9514 limit *= 2;
9515 }
9516 else
9517 break;
9518 }
9519 }
9520 else
9521 names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
9522 &num_fonts);
9523
9524 if (x_had_errors_p (dpy))
9525 {
9526 /* This error is perhaps due to insufficient memory on X
9527 server. Let's just ignore it. */
9528 names = NULL;
9529 x_clear_errors (dpy);
9530 }
9531 }
9532
9533 x_uncatch_errors (dpy, count);
9534 UNBLOCK_INPUT;
9535
9536 if (names)
9537 {
9538 int i;
9539
9540 /* Make a list of all the fonts we got back.
9541 Store that in the font cache for the display. */
9542 for (i = 0; i < num_fonts; i++)
9543 {
9544 int width = 0;
9545 char *p = names[i];
9546 int average_width = -1, resx = 0, dashes = 0;
9547
9548 /* Count the number of dashes in NAMES[I]. If there are
9549 14 dashes, the field value following 9th dash
9550 (RESOLUTION_X) is nonzero, and the field value
9551 following 12th dash (AVERAGE_WIDTH) is 0, this is a
9552 auto-scaled font which is usually too ugly to be used
9553 for editing. Let's ignore it. */
9554 while (*p)
9555 if (*p++ == '-')
9556 {
9557 dashes++;
9558 if (dashes == 7) /* PIXEL_SIZE field */
9559 width = atoi (p);
9560 else if (dashes == 9)
9561 resx = atoi (p);
9562 else if (dashes == 12) /* AVERAGE_WIDTH field */
9563 average_width = atoi (p);
9564 }
9565
9566 if (allow_auto_scaled_font
9567 || dashes < 14 || average_width != 0 || resx == 0)
9568 {
9569 tem = build_string (names[i]);
9570 if (NILP (Fassoc (tem, list)))
9571 {
9572 if (STRINGP (Vx_pixel_size_width_font_regexp)
9573 && ((fast_c_string_match_ignore_case
9574 (Vx_pixel_size_width_font_regexp, names[i]))
9575 >= 0))
9576 /* We can set the value of PIXEL_SIZE to the
9577 width of this font. */
9578 list = Fcons (Fcons (tem, make_number (width)), list);
9579 else
9580 /* For the moment, width is not known. */
9581 list = Fcons (Fcons (tem, Qnil), list);
9582 }
9583 }
9584 }
9585
9586 if (!try_XLoadQueryFont)
9587 {
9588 BLOCK_INPUT;
9589 XFreeFontNames (names);
9590 UNBLOCK_INPUT;
9591 }
9592 }
9593
9594 /* Now store the result in the cache. */
9595 XSETCDR (dpyinfo->name_list_element,
9596 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
9597
9598 label_cached:
9599 if (NILP (list)) continue; /* Try the remaining alternatives. */
9600
9601 newlist = second_best = Qnil;
9602 /* Make a list of the fonts that have the right width. */
9603 for (; CONSP (list); list = XCDR (list))
9604 {
9605 int found_size;
9606
9607 tem = XCAR (list);
9608
9609 if (!CONSP (tem) || NILP (XCAR (tem)))
9610 continue;
9611 if (!size)
9612 {
9613 newlist = Fcons (XCAR (tem), newlist);
9614 continue;
9615 }
9616
9617 if (!INTEGERP (XCDR (tem)))
9618 {
9619 /* Since we have not yet known the size of this font, we
9620 must try slow function call XLoadQueryFont. */
9621 XFontStruct *thisinfo;
9622
9623 BLOCK_INPUT;
9624 count = x_catch_errors (dpy);
9625 thisinfo = XLoadQueryFont (dpy,
9626 SDATA (XCAR (tem)));
9627 if (x_had_errors_p (dpy))
9628 {
9629 /* This error is perhaps due to insufficient memory on X
9630 server. Let's just ignore it. */
9631 thisinfo = NULL;
9632 x_clear_errors (dpy);
9633 }
9634 x_uncatch_errors (dpy, count);
9635 UNBLOCK_INPUT;
9636
9637 if (thisinfo)
9638 {
9639 XSETCDR (tem,
9640 (thisinfo->min_bounds.width == 0
9641 ? make_number (0)
9642 : make_number (thisinfo->max_bounds.width)));
9643 BLOCK_INPUT;
9644 XFreeFont (dpy, thisinfo);
9645 UNBLOCK_INPUT;
9646 }
9647 else
9648 /* For unknown reason, the previous call of XListFont had
9649 returned a font which can't be opened. Record the size
9650 as 0 not to try to open it again. */
9651 XSETCDR (tem, make_number (0));
9652 }
9653
9654 found_size = XINT (XCDR (tem));
9655 if (found_size == size)
9656 newlist = Fcons (XCAR (tem), newlist);
9657 else if (found_size > 0)
9658 {
9659 if (NILP (second_best))
9660 second_best = tem;
9661 else if (found_size < size)
9662 {
9663 if (XINT (XCDR (second_best)) > size
9664 || XINT (XCDR (second_best)) < found_size)
9665 second_best = tem;
9666 }
9667 else
9668 {
9669 if (XINT (XCDR (second_best)) > size
9670 && XINT (XCDR (second_best)) > found_size)
9671 second_best = tem;
9672 }
9673 }
9674 }
9675 if (!NILP (newlist))
9676 break;
9677 else if (!NILP (second_best))
9678 {
9679 newlist = Fcons (XCAR (second_best), Qnil);
9680 break;
9681 }
9682 }
9683
9684 return newlist;
9685 }
9686
9687
9688 #if GLYPH_DEBUG
9689
9690 /* Check that FONT is valid on frame F. It is if it can be found in F's
9691 font table. */
9692
9693 static void
9694 x_check_font (f, font)
9695 struct frame *f;
9696 XFontStruct *font;
9697 {
9698 int i;
9699 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9700
9701 xassert (font != NULL);
9702
9703 for (i = 0; i < dpyinfo->n_fonts; i++)
9704 if (dpyinfo->font_table[i].name
9705 && font == dpyinfo->font_table[i].font)
9706 break;
9707
9708 xassert (i < dpyinfo->n_fonts);
9709 }
9710
9711 #endif /* GLYPH_DEBUG != 0 */
9712
9713 /* Set *W to the minimum width, *H to the minimum font height of FONT.
9714 Note: There are (broken) X fonts out there with invalid XFontStruct
9715 min_bounds contents. For example, handa@etl.go.jp reports that
9716 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
9717 have font->min_bounds.width == 0. */
9718
9719 static INLINE void
9720 x_font_min_bounds (font, w, h)
9721 XFontStruct *font;
9722 int *w, *h;
9723 {
9724 *h = FONT_HEIGHT (font);
9725 *w = font->min_bounds.width;
9726
9727 /* Try to handle the case where FONT->min_bounds has invalid
9728 contents. Since the only font known to have invalid min_bounds
9729 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
9730 if (*w <= 0)
9731 *w = font->max_bounds.width;
9732 }
9733
9734
9735 /* Compute the smallest character width and smallest font height over
9736 all fonts available on frame F. Set the members smallest_char_width
9737 and smallest_font_height in F's x_display_info structure to
9738 the values computed. Value is non-zero if smallest_font_height or
9739 smallest_char_width become smaller than they were before. */
9740
9741 static int
9742 x_compute_min_glyph_bounds (f)
9743 struct frame *f;
9744 {
9745 int i;
9746 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9747 XFontStruct *font;
9748 int old_width = dpyinfo->smallest_char_width;
9749 int old_height = dpyinfo->smallest_font_height;
9750
9751 dpyinfo->smallest_font_height = 100000;
9752 dpyinfo->smallest_char_width = 100000;
9753
9754 for (i = 0; i < dpyinfo->n_fonts; ++i)
9755 if (dpyinfo->font_table[i].name)
9756 {
9757 struct font_info *fontp = dpyinfo->font_table + i;
9758 int w, h;
9759
9760 font = (XFontStruct *) fontp->font;
9761 xassert (font != (XFontStruct *) ~0);
9762 x_font_min_bounds (font, &w, &h);
9763
9764 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
9765 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
9766 }
9767
9768 xassert (dpyinfo->smallest_char_width > 0
9769 && dpyinfo->smallest_font_height > 0);
9770
9771 return (dpyinfo->n_fonts == 1
9772 || dpyinfo->smallest_char_width < old_width
9773 || dpyinfo->smallest_font_height < old_height);
9774 }
9775
9776
9777 /* Load font named FONTNAME of the size SIZE for frame F, and return a
9778 pointer to the structure font_info while allocating it dynamically.
9779 If SIZE is 0, load any size of font.
9780 If loading is failed, return NULL. */
9781
9782 struct font_info *
9783 x_load_font (f, fontname, size)
9784 struct frame *f;
9785 register char *fontname;
9786 int size;
9787 {
9788 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9789 Lisp_Object font_names;
9790 int count;
9791
9792 /* Get a list of all the fonts that match this name. Once we
9793 have a list of matching fonts, we compare them against the fonts
9794 we already have by comparing names. */
9795 font_names = x_list_fonts (f, build_string (fontname), size, 1);
9796
9797 if (!NILP (font_names))
9798 {
9799 Lisp_Object tail;
9800 int i;
9801
9802 for (i = 0; i < dpyinfo->n_fonts; i++)
9803 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
9804 if (dpyinfo->font_table[i].name
9805 && (!strcmp (dpyinfo->font_table[i].name,
9806 SDATA (XCAR (tail)))
9807 || !strcmp (dpyinfo->font_table[i].full_name,
9808 SDATA (XCAR (tail)))))
9809 return (dpyinfo->font_table + i);
9810 }
9811
9812 /* Load the font and add it to the table. */
9813 {
9814 char *full_name;
9815 XFontStruct *font;
9816 struct font_info *fontp;
9817 unsigned long value;
9818 int i;
9819
9820 /* If we have found fonts by x_list_font, load one of them. If
9821 not, we still try to load a font by the name given as FONTNAME
9822 because XListFonts (called in x_list_font) of some X server has
9823 a bug of not finding a font even if the font surely exists and
9824 is loadable by XLoadQueryFont. */
9825 if (size > 0 && !NILP (font_names))
9826 fontname = (char *) SDATA (XCAR (font_names));
9827
9828 BLOCK_INPUT;
9829 count = x_catch_errors (FRAME_X_DISPLAY (f));
9830 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
9831 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
9832 {
9833 /* This error is perhaps due to insufficient memory on X
9834 server. Let's just ignore it. */
9835 font = NULL;
9836 x_clear_errors (FRAME_X_DISPLAY (f));
9837 }
9838 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
9839 UNBLOCK_INPUT;
9840 if (!font)
9841 return NULL;
9842
9843 /* Find a free slot in the font table. */
9844 for (i = 0; i < dpyinfo->n_fonts; ++i)
9845 if (dpyinfo->font_table[i].name == NULL)
9846 break;
9847
9848 /* If no free slot found, maybe enlarge the font table. */
9849 if (i == dpyinfo->n_fonts
9850 && dpyinfo->n_fonts == dpyinfo->font_table_size)
9851 {
9852 int sz;
9853 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
9854 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
9855 dpyinfo->font_table
9856 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
9857 }
9858
9859 fontp = dpyinfo->font_table + i;
9860 if (i == dpyinfo->n_fonts)
9861 ++dpyinfo->n_fonts;
9862
9863 /* Now fill in the slots of *FONTP. */
9864 BLOCK_INPUT;
9865 bzero (fontp, sizeof (*fontp));
9866 fontp->font = font;
9867 fontp->font_idx = i;
9868 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
9869 bcopy (fontname, fontp->name, strlen (fontname) + 1);
9870
9871 /* Try to get the full name of FONT. Put it in FULL_NAME. */
9872 full_name = 0;
9873 if (XGetFontProperty (font, XA_FONT, &value))
9874 {
9875 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
9876 char *p = name;
9877 int dashes = 0;
9878
9879 /* Count the number of dashes in the "full name".
9880 If it is too few, this isn't really the font's full name,
9881 so don't use it.
9882 In X11R4, the fonts did not come with their canonical names
9883 stored in them. */
9884 while (*p)
9885 {
9886 if (*p == '-')
9887 dashes++;
9888 p++;
9889 }
9890
9891 if (dashes >= 13)
9892 {
9893 full_name = (char *) xmalloc (p - name + 1);
9894 bcopy (name, full_name, p - name + 1);
9895 }
9896
9897 XFree (name);
9898 }
9899
9900 if (full_name != 0)
9901 fontp->full_name = full_name;
9902 else
9903 fontp->full_name = fontp->name;
9904
9905 fontp->size = font->max_bounds.width;
9906 fontp->height = FONT_HEIGHT (font);
9907
9908 if (NILP (font_names))
9909 {
9910 /* We come here because of a bug of XListFonts mentioned at
9911 the head of this block. Let's store this information in
9912 the cache for x_list_fonts. */
9913 Lisp_Object lispy_name = build_string (fontname);
9914 Lisp_Object lispy_full_name = build_string (fontp->full_name);
9915 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
9916 Qnil);
9917
9918 XSETCDR (dpyinfo->name_list_element,
9919 Fcons (Fcons (key,
9920 Fcons (Fcons (lispy_full_name,
9921 make_number (fontp->size)),
9922 Qnil)),
9923 XCDR (dpyinfo->name_list_element)));
9924 if (full_name)
9925 {
9926 key = Fcons (Fcons (lispy_full_name, make_number (256)),
9927 Qnil);
9928 XSETCDR (dpyinfo->name_list_element,
9929 Fcons (Fcons (key,
9930 Fcons (Fcons (lispy_full_name,
9931 make_number (fontp->size)),
9932 Qnil)),
9933 XCDR (dpyinfo->name_list_element)));
9934 }
9935 }
9936
9937 /* The slot `encoding' specifies how to map a character
9938 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
9939 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
9940 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
9941 2:0xA020..0xFF7F). For the moment, we don't know which charset
9942 uses this font. So, we set information in fontp->encoding[1]
9943 which is never used by any charset. If mapping can't be
9944 decided, set FONT_ENCODING_NOT_DECIDED. */
9945 fontp->encoding[1]
9946 = (font->max_byte1 == 0
9947 /* 1-byte font */
9948 ? (font->min_char_or_byte2 < 0x80
9949 ? (font->max_char_or_byte2 < 0x80
9950 ? 0 /* 0x20..0x7F */
9951 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
9952 : 1) /* 0xA0..0xFF */
9953 /* 2-byte font */
9954 : (font->min_byte1 < 0x80
9955 ? (font->max_byte1 < 0x80
9956 ? (font->min_char_or_byte2 < 0x80
9957 ? (font->max_char_or_byte2 < 0x80
9958 ? 0 /* 0x2020..0x7F7F */
9959 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
9960 : 3) /* 0x20A0..0x7FFF */
9961 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
9962 : (font->min_char_or_byte2 < 0x80
9963 ? (font->max_char_or_byte2 < 0x80
9964 ? 2 /* 0xA020..0xFF7F */
9965 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
9966 : 1))); /* 0xA0A0..0xFFFF */
9967
9968 fontp->baseline_offset
9969 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
9970 ? (long) value : 0);
9971 fontp->relative_compose
9972 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
9973 ? (long) value : 0);
9974 fontp->default_ascent
9975 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
9976 ? (long) value : 0);
9977
9978 /* Set global flag fonts_changed_p to non-zero if the font loaded
9979 has a character with a smaller width than any other character
9980 before, or if the font loaded has a smaller height than any
9981 other font loaded before. If this happens, it will make a
9982 glyph matrix reallocation necessary. */
9983 fonts_changed_p |= x_compute_min_glyph_bounds (f);
9984 UNBLOCK_INPUT;
9985 return fontp;
9986 }
9987 }
9988
9989
9990 /* Return a pointer to struct font_info of a font named FONTNAME for
9991 frame F. If no such font is loaded, return NULL. */
9992
9993 struct font_info *
9994 x_query_font (f, fontname)
9995 struct frame *f;
9996 register char *fontname;
9997 {
9998 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9999 int i;
10000
10001 for (i = 0; i < dpyinfo->n_fonts; i++)
10002 if (dpyinfo->font_table[i].name
10003 && (!strcmp (dpyinfo->font_table[i].name, fontname)
10004 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
10005 return (dpyinfo->font_table + i);
10006 return NULL;
10007 }
10008
10009
10010 /* Find a CCL program for a font specified by FONTP, and set the member
10011 `encoder' of the structure. */
10012
10013 void
10014 x_find_ccl_program (fontp)
10015 struct font_info *fontp;
10016 {
10017 Lisp_Object list, elt;
10018
10019 elt = Qnil;
10020 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
10021 {
10022 elt = XCAR (list);
10023 if (CONSP (elt)
10024 && STRINGP (XCAR (elt))
10025 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
10026 >= 0)
10027 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
10028 >= 0)))
10029 break;
10030 }
10031
10032 if (! NILP (list))
10033 {
10034 struct ccl_program *ccl
10035 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
10036
10037 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
10038 xfree (ccl);
10039 else
10040 fontp->font_encoder = ccl;
10041 }
10042 }
10043
10044
10045 \f
10046 /***********************************************************************
10047 Initialization
10048 ***********************************************************************/
10049
10050 #ifdef USE_X_TOOLKIT
10051 static XrmOptionDescRec emacs_options[] = {
10052 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
10053 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
10054
10055 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
10056 XrmoptionSepArg, NULL},
10057 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
10058
10059 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
10060 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
10061 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
10062 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
10063 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
10064 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
10065 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
10066 };
10067 #endif /* USE_X_TOOLKIT */
10068
10069 static int x_initialized;
10070
10071 #ifdef MULTI_KBOARD
10072 /* Test whether two display-name strings agree up to the dot that separates
10073 the screen number from the server number. */
10074 static int
10075 same_x_server (name1, name2)
10076 const char *name1, *name2;
10077 {
10078 int seen_colon = 0;
10079 const unsigned char *system_name = SDATA (Vsystem_name);
10080 int system_name_length = strlen (system_name);
10081 int length_until_period = 0;
10082
10083 while (system_name[length_until_period] != 0
10084 && system_name[length_until_period] != '.')
10085 length_until_period++;
10086
10087 /* Treat `unix' like an empty host name. */
10088 if (! strncmp (name1, "unix:", 5))
10089 name1 += 4;
10090 if (! strncmp (name2, "unix:", 5))
10091 name2 += 4;
10092 /* Treat this host's name like an empty host name. */
10093 if (! strncmp (name1, system_name, system_name_length)
10094 && name1[system_name_length] == ':')
10095 name1 += system_name_length;
10096 if (! strncmp (name2, system_name, system_name_length)
10097 && name2[system_name_length] == ':')
10098 name2 += system_name_length;
10099 /* Treat this host's domainless name like an empty host name. */
10100 if (! strncmp (name1, system_name, length_until_period)
10101 && name1[length_until_period] == ':')
10102 name1 += length_until_period;
10103 if (! strncmp (name2, system_name, length_until_period)
10104 && name2[length_until_period] == ':')
10105 name2 += length_until_period;
10106
10107 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
10108 {
10109 if (*name1 == ':')
10110 seen_colon++;
10111 if (seen_colon && *name1 == '.')
10112 return 1;
10113 }
10114 return (seen_colon
10115 && (*name1 == '.' || *name1 == '\0')
10116 && (*name2 == '.' || *name2 == '\0'));
10117 }
10118 #endif
10119
10120 /* Count number of set bits in mask and number of bits to shift to
10121 get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
10122 to 5. */
10123 static void
10124 get_bits_and_offset (mask, bits, offset)
10125 unsigned long mask;
10126 int *bits;
10127 int *offset;
10128 {
10129 int nr = 0;
10130 int off = 0;
10131
10132 while (!(mask & 1))
10133 {
10134 off++;
10135 mask >>= 1;
10136 }
10137
10138 while (mask & 1)
10139 {
10140 nr++;
10141 mask >>= 1;
10142 }
10143
10144 *offset = off;
10145 *bits = nr;
10146 }
10147
10148 struct x_display_info *
10149 x_term_init (display_name, xrm_option, resource_name)
10150 Lisp_Object display_name;
10151 char *xrm_option;
10152 char *resource_name;
10153 {
10154 int connection;
10155 Display *dpy;
10156 struct display *display;
10157 struct x_display_info *dpyinfo;
10158 XrmDatabase xrdb;
10159
10160 BLOCK_INPUT;
10161
10162 if (!x_initialized)
10163 {
10164 x_initialize ();
10165 ++x_initialized;
10166 }
10167
10168 #ifdef USE_GTK
10169 {
10170 #define NUM_ARGV 10
10171 int argc;
10172 char *argv[NUM_ARGV];
10173 char **argv2 = argv;
10174 GdkAtom atom;
10175
10176 if (x_initialized++ > 1)
10177 {
10178 /* Opening another display. If xg_display_open returns less
10179 than zero, we are probably on GTK 2.0, which can only handle
10180 one display. GTK 2.2 or later can handle more than one. */
10181 if (xg_display_open (SDATA (display_name), &dpy) < 0)
10182 error ("Sorry, this version of GTK can only handle one display");
10183 }
10184 else
10185 {
10186 for (argc = 0; argc < NUM_ARGV; ++argc)
10187 argv[argc] = 0;
10188
10189 argc = 0;
10190 argv[argc++] = initial_argv[0];
10191
10192 if (! NILP (display_name))
10193 {
10194 argv[argc++] = "--display";
10195 argv[argc++] = SDATA (display_name);
10196 }
10197
10198 argv[argc++] = "--name";
10199 argv[argc++] = resource_name;
10200
10201 #ifdef HAVE_X11R5
10202 XSetLocaleModifiers ("");
10203 #endif
10204
10205 gtk_init (&argc, &argv2);
10206
10207 /* gtk_init does set_locale. We must fix locale after calling it. */
10208 fixup_locale ();
10209 xg_initialize ();
10210
10211 dpy = GDK_DISPLAY ();
10212
10213 /* NULL window -> events for all windows go to our function */
10214 gdk_window_add_filter (NULL, event_handler_gdk, NULL);
10215
10216 /* Load our own gtkrc if it exists. */
10217 {
10218 struct gcpro gcpro1, gcpro2;
10219 char *file = "~/.emacs.d/gtkrc";
10220 Lisp_Object s, abs_file;
10221
10222 GCPRO2 (s, abs_file);
10223 s = make_string (file, strlen (file));
10224 abs_file = Fexpand_file_name (s, Qnil);
10225
10226 if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
10227 gtk_rc_parse (SDATA (abs_file));
10228
10229 UNGCPRO;
10230 }
10231
10232 XSetErrorHandler (x_error_handler);
10233 XSetIOErrorHandler (x_io_error_quitter);
10234 }
10235 }
10236 #else /* not USE_GTK */
10237 #ifdef USE_X_TOOLKIT
10238 /* weiner@footloose.sps.mot.com reports that this causes
10239 errors with X11R5:
10240 X protocol error: BadAtom (invalid Atom parameter)
10241 on protocol request 18skiloaf.
10242 So let's not use it until R6. */
10243 #ifdef HAVE_X11XTR6
10244 XtSetLanguageProc (NULL, NULL, NULL);
10245 #endif
10246
10247 {
10248 int argc = 0;
10249 char *argv[3];
10250
10251 argv[0] = "";
10252 argc = 1;
10253 if (xrm_option)
10254 {
10255 argv[argc++] = "-xrm";
10256 argv[argc++] = xrm_option;
10257 }
10258 turn_on_atimers (0);
10259 dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
10260 resource_name, EMACS_CLASS,
10261 emacs_options, XtNumber (emacs_options),
10262 &argc, argv);
10263 turn_on_atimers (1);
10264
10265 #ifdef HAVE_X11XTR6
10266 /* I think this is to compensate for XtSetLanguageProc. */
10267 fixup_locale ();
10268 #endif
10269 }
10270
10271 #else /* not USE_X_TOOLKIT */
10272 #ifdef HAVE_X11R5
10273 XSetLocaleModifiers ("");
10274 #endif
10275 dpy = XOpenDisplay (SDATA (display_name));
10276 #endif /* not USE_X_TOOLKIT */
10277 #endif /* not USE_GTK*/
10278
10279 /* Detect failure. */
10280 if (dpy == 0)
10281 {
10282 UNBLOCK_INPUT;
10283 return 0;
10284 }
10285
10286 /* We have definitely succeeded. Record the new connection. */
10287
10288 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
10289 bzero (dpyinfo, sizeof *dpyinfo);
10290
10291 display = x_create_frame_display (dpyinfo);
10292
10293 #ifdef MULTI_KBOARD
10294 {
10295 struct x_display_info *share;
10296 Lisp_Object tail;
10297
10298 for (share = x_display_list, tail = x_display_name_list; share;
10299 share = share->next, tail = XCDR (tail))
10300 if (same_x_server (SDATA (XCAR (XCAR (tail))),
10301 SDATA (display_name)))
10302 break;
10303 if (share)
10304 dpyinfo->kboard = share->kboard;
10305 else
10306 {
10307 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
10308 init_kboard (dpyinfo->kboard);
10309 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
10310 {
10311 char *vendor = ServerVendor (dpy);
10312 UNBLOCK_INPUT;
10313 dpyinfo->kboard->Vsystem_key_alist
10314 = call1 (Qvendor_specific_keysyms,
10315 build_string (vendor ? vendor : ""));
10316 BLOCK_INPUT;
10317 }
10318
10319 dpyinfo->kboard->next_kboard = all_kboards;
10320 all_kboards = dpyinfo->kboard;
10321 /* Don't let the initial kboard remain current longer than necessary.
10322 That would cause problems if a file loaded on startup tries to
10323 prompt in the mini-buffer. */
10324 if (current_kboard == initial_kboard)
10325 current_kboard = dpyinfo->kboard;
10326 }
10327 dpyinfo->kboard->reference_count++;
10328 }
10329 #endif
10330
10331 /* Put this display on the chain. */
10332 dpyinfo->next = x_display_list;
10333 x_display_list = dpyinfo;
10334
10335 /* Put it on x_display_name_list as well, to keep them parallel. */
10336 x_display_name_list = Fcons (Fcons (display_name, Qnil),
10337 x_display_name_list);
10338 dpyinfo->name_list_element = XCAR (x_display_name_list);
10339
10340 dpyinfo->display = dpy;
10341
10342 /* Set the name of the display. */
10343 display->name = (char *) xmalloc (SBYTES (display_name) + 1);
10344 strncpy (display->name, SDATA (display_name), SBYTES (display_name));
10345 display->name[SBYTES (display_name)] = 0;
10346
10347 #if 0
10348 XSetAfterFunction (x_current_display, x_trace_wire);
10349 #endif /* ! 0 */
10350
10351 dpyinfo->x_id_name
10352 = (char *) xmalloc (SBYTES (Vinvocation_name)
10353 + SBYTES (Vsystem_name)
10354 + 2);
10355 sprintf (dpyinfo->x_id_name, "%s@%s",
10356 SDATA (Vinvocation_name), SDATA (Vsystem_name));
10357
10358 /* Figure out which modifier bits mean what. */
10359 x_find_modifier_meanings (dpyinfo);
10360
10361 /* Get the scroll bar cursor. */
10362 #ifdef USE_GTK
10363 /* We must create a GTK cursor, it is required for GTK widgets. */
10364 dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
10365 #endif /* USE_GTK */
10366
10367 dpyinfo->vertical_scroll_bar_cursor
10368 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
10369
10370 xrdb = x_load_resources (dpyinfo->display, xrm_option,
10371 resource_name, EMACS_CLASS);
10372 #ifdef HAVE_XRMSETDATABASE
10373 XrmSetDatabase (dpyinfo->display, xrdb);
10374 #else
10375 dpyinfo->display->db = xrdb;
10376 #endif
10377 /* Put the rdb where we can find it in a way that works on
10378 all versions. */
10379 dpyinfo->xrdb = xrdb;
10380
10381 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
10382 DefaultScreen (dpyinfo->display));
10383 select_visual (dpyinfo);
10384 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
10385 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
10386 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
10387 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
10388 dpyinfo->client_leader_window = 0;
10389 dpyinfo->grabbed = 0;
10390 dpyinfo->reference_count = 0;
10391 dpyinfo->icon_bitmap_id = -1;
10392 dpyinfo->font_table = NULL;
10393 dpyinfo->n_fonts = 0;
10394 dpyinfo->font_table_size = 0;
10395 dpyinfo->bitmaps = 0;
10396 dpyinfo->bitmaps_size = 0;
10397 dpyinfo->bitmaps_last = 0;
10398 dpyinfo->scratch_cursor_gc = 0;
10399 dpyinfo->mouse_face_mouse_frame = 0;
10400 dpyinfo->mouse_face_deferred_gc = 0;
10401 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
10402 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10403 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10404 dpyinfo->mouse_face_window = Qnil;
10405 dpyinfo->mouse_face_overlay = Qnil;
10406 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
10407 dpyinfo->mouse_face_defer = 0;
10408 dpyinfo->mouse_face_hidden = 0;
10409 dpyinfo->x_focus_frame = 0;
10410 dpyinfo->x_focus_event_frame = 0;
10411 dpyinfo->x_highlight_frame = 0;
10412 dpyinfo->image_cache = make_image_cache ();
10413 dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
10414
10415 /* See if we can construct pixel values from RGB values. */
10416 dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0;
10417 dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0;
10418
10419 if (dpyinfo->visual->class == TrueColor)
10420 {
10421 get_bits_and_offset (dpyinfo->visual->red_mask,
10422 &dpyinfo->red_bits, &dpyinfo->red_offset);
10423 get_bits_and_offset (dpyinfo->visual->blue_mask,
10424 &dpyinfo->blue_bits, &dpyinfo->blue_offset);
10425 get_bits_and_offset (dpyinfo->visual->green_mask,
10426 &dpyinfo->green_bits, &dpyinfo->green_offset);
10427 }
10428
10429 /* See if a private colormap is requested. */
10430 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
10431 {
10432 if (dpyinfo->visual->class == PseudoColor)
10433 {
10434 Lisp_Object value;
10435 value = display_x_get_resource (dpyinfo,
10436 build_string ("privateColormap"),
10437 build_string ("PrivateColormap"),
10438 Qnil, Qnil);
10439 if (STRINGP (value)
10440 && (!strcmp (SDATA (value), "true")
10441 || !strcmp (SDATA (value), "on")))
10442 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
10443 }
10444 }
10445 else
10446 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
10447 dpyinfo->visual, AllocNone);
10448
10449 {
10450 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
10451 double pixels = DisplayHeight (dpyinfo->display, screen_number);
10452 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
10453 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10454 dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
10455 pixels = DisplayWidth (dpyinfo->display, screen_number);
10456 /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
10457 mm = DisplayWidthMM (dpyinfo->display, screen_number);
10458 dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
10459 }
10460
10461 dpyinfo->Xatom_wm_protocols
10462 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
10463 dpyinfo->Xatom_wm_take_focus
10464 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
10465 dpyinfo->Xatom_wm_save_yourself
10466 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
10467 dpyinfo->Xatom_wm_delete_window
10468 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
10469 dpyinfo->Xatom_wm_change_state
10470 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
10471 dpyinfo->Xatom_wm_configure_denied
10472 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
10473 dpyinfo->Xatom_wm_window_moved
10474 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
10475 dpyinfo->Xatom_wm_client_leader
10476 = XInternAtom (dpyinfo->display, "WM_CLIENT_LEADER", False);
10477 dpyinfo->Xatom_editres
10478 = XInternAtom (dpyinfo->display, "Editres", False);
10479 dpyinfo->Xatom_CLIPBOARD
10480 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
10481 dpyinfo->Xatom_TIMESTAMP
10482 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
10483 dpyinfo->Xatom_TEXT
10484 = XInternAtom (dpyinfo->display, "TEXT", False);
10485 dpyinfo->Xatom_COMPOUND_TEXT
10486 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
10487 dpyinfo->Xatom_UTF8_STRING
10488 = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
10489 dpyinfo->Xatom_DELETE
10490 = XInternAtom (dpyinfo->display, "DELETE", False);
10491 dpyinfo->Xatom_MULTIPLE
10492 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
10493 dpyinfo->Xatom_INCR
10494 = XInternAtom (dpyinfo->display, "INCR", False);
10495 dpyinfo->Xatom_EMACS_TMP
10496 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
10497 dpyinfo->Xatom_TARGETS
10498 = XInternAtom (dpyinfo->display, "TARGETS", False);
10499 dpyinfo->Xatom_NULL
10500 = XInternAtom (dpyinfo->display, "NULL", False);
10501 dpyinfo->Xatom_ATOM_PAIR
10502 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
10503 /* For properties of font. */
10504 dpyinfo->Xatom_PIXEL_SIZE
10505 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
10506 dpyinfo->Xatom_MULE_BASELINE_OFFSET
10507 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
10508 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
10509 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
10510 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
10511 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
10512
10513 /* Ghostscript support. */
10514 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
10515 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
10516
10517 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
10518 False);
10519
10520 dpyinfo->cut_buffers_initialized = 0;
10521
10522 connection = ConnectionNumber (dpyinfo->display);
10523 dpyinfo->connection = connection;
10524
10525 {
10526 char null_bits[1];
10527
10528 null_bits[0] = 0x00;
10529
10530 dpyinfo->null_pixel
10531 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10532 null_bits, 1, 1, (long) 0, (long) 0,
10533 1);
10534 }
10535
10536 {
10537 extern int gray_bitmap_width, gray_bitmap_height;
10538 extern char *gray_bitmap_bits;
10539 dpyinfo->gray
10540 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10541 gray_bitmap_bits,
10542 gray_bitmap_width, gray_bitmap_height,
10543 (unsigned long) 1, (unsigned long) 0, 1);
10544 }
10545
10546 #ifdef HAVE_X_I18N
10547 xim_initialize (dpyinfo, resource_name);
10548 #endif
10549
10550 #ifdef subprocesses
10551 /* This is only needed for distinguishing keyboard and process input. */
10552 if (connection != 0)
10553 add_keyboard_wait_descriptor (connection);
10554 #endif
10555
10556 #ifndef F_SETOWN_BUG
10557 #ifdef F_SETOWN
10558 #ifdef F_SETOWN_SOCK_NEG
10559 /* stdin is a socket here */
10560 fcntl (connection, F_SETOWN, -getpid ());
10561 #else /* ! defined (F_SETOWN_SOCK_NEG) */
10562 fcntl (connection, F_SETOWN, getpid ());
10563 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
10564 #endif /* ! defined (F_SETOWN) */
10565 #endif /* F_SETOWN_BUG */
10566
10567 #ifdef SIGIO
10568 if (interrupt_input)
10569 init_sigio (connection);
10570 #endif /* ! defined (SIGIO) */
10571
10572 #ifdef USE_LUCID
10573 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
10574 /* Make sure that we have a valid font for dialog boxes
10575 so that Xt does not crash. */
10576 {
10577 Display *dpy = dpyinfo->display;
10578 XrmValue d, fr, to;
10579 Font font;
10580 int count;
10581
10582 d.addr = (XPointer)&dpy;
10583 d.size = sizeof (Display *);
10584 fr.addr = XtDefaultFont;
10585 fr.size = sizeof (XtDefaultFont);
10586 to.size = sizeof (Font *);
10587 to.addr = (XPointer)&font;
10588 count = x_catch_errors (dpy);
10589 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
10590 abort ();
10591 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
10592 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
10593 x_uncatch_errors (dpy, count);
10594 }
10595 #endif
10596 #endif
10597
10598 /* See if we should run in synchronous mode. This is useful
10599 for debugging X code. */
10600 {
10601 Lisp_Object value;
10602 value = display_x_get_resource (dpyinfo,
10603 build_string ("synchronous"),
10604 build_string ("Synchronous"),
10605 Qnil, Qnil);
10606 if (STRINGP (value)
10607 && (!strcmp (SDATA (value), "true")
10608 || !strcmp (SDATA (value), "on")))
10609 XSynchronize (dpyinfo->display, True);
10610 }
10611
10612 {
10613 Lisp_Object value;
10614 value = display_x_get_resource (dpyinfo,
10615 build_string ("useXIM"),
10616 build_string ("UseXIM"),
10617 Qnil, Qnil);
10618 #ifdef USE_XIM
10619 if (STRINGP (value)
10620 && (!strcmp (XSTRING (value)->data, "false")
10621 || !strcmp (XSTRING (value)->data, "off")))
10622 use_xim = 0;
10623 #else
10624 if (STRINGP (value)
10625 && (!strcmp (XSTRING (value)->data, "true")
10626 || !strcmp (XSTRING (value)->data, "on")))
10627 use_xim = 1;
10628 #endif
10629 }
10630
10631 #ifdef HAVE_X_SM
10632 /* Only do this for the first display. */
10633 if (x_initialized == 1)
10634 x_session_initialize (dpyinfo);
10635 #endif
10636
10637 UNBLOCK_INPUT;
10638
10639 return dpyinfo;
10640 }
10641 \f
10642 /* Get rid of display DPYINFO, assuming all frames are already gone,
10643 and without sending any more commands to the X server. */
10644
10645 void
10646 x_delete_display (dpyinfo)
10647 struct x_display_info *dpyinfo;
10648 {
10649 int i;
10650
10651 {
10652 /* Delete the generic struct display for this X display. */
10653 struct display *d;
10654 for (d = display_list; d; d = d->next_display)
10655 if (d->type == output_x_window && d->display_info.x == dpyinfo)
10656 {
10657 delete_display (d);
10658 break;
10659 }
10660 }
10661
10662 delete_keyboard_wait_descriptor (dpyinfo->connection);
10663
10664 /* Discard this display from x_display_name_list and x_display_list.
10665 We can't use Fdelq because that can quit. */
10666 if (! NILP (x_display_name_list)
10667 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
10668 x_display_name_list = XCDR (x_display_name_list);
10669 else
10670 {
10671 Lisp_Object tail;
10672
10673 tail = x_display_name_list;
10674 while (CONSP (tail) && CONSP (XCDR (tail)))
10675 {
10676 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10677 {
10678 XSETCDR (tail, XCDR (XCDR (tail)));
10679 break;
10680 }
10681 tail = XCDR (tail);
10682 }
10683 }
10684
10685 if (next_noop_dpyinfo == dpyinfo)
10686 next_noop_dpyinfo = dpyinfo->next;
10687
10688 if (x_display_list == dpyinfo)
10689 x_display_list = dpyinfo->next;
10690 else
10691 {
10692 struct x_display_info *tail;
10693
10694 for (tail = x_display_list; tail; tail = tail->next)
10695 if (tail->next == dpyinfo)
10696 tail->next = tail->next->next;
10697 }
10698
10699 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
10700 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
10701 XrmDestroyDatabase (dpyinfo->xrdb);
10702 #endif
10703 #endif
10704 #ifdef MULTI_KBOARD
10705 if (--dpyinfo->kboard->reference_count == 0)
10706 delete_kboard (dpyinfo->kboard);
10707 #endif
10708 #ifdef HAVE_X_I18N
10709 if (dpyinfo->xim)
10710 xim_close_dpy (dpyinfo);
10711 #endif
10712
10713 /* Free the font names in the font table. */
10714 for (i = 0; i < dpyinfo->n_fonts; i++)
10715 if (dpyinfo->font_table[i].name)
10716 {
10717 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
10718 xfree (dpyinfo->font_table[i].full_name);
10719 xfree (dpyinfo->font_table[i].name);
10720 }
10721
10722 if (dpyinfo->font_table && dpyinfo->font_table->font_encoder)
10723 xfree (dpyinfo->font_table->font_encoder);
10724
10725 if (dpyinfo->font_table)
10726 xfree (dpyinfo->font_table);
10727 xfree (dpyinfo->x_id_name);
10728 xfree (dpyinfo->color_cells);
10729 xfree (dpyinfo);
10730 }
10731
10732 #ifdef USE_X_TOOLKIT
10733
10734 /* Atimer callback function for TIMER. Called every 0.1s to process
10735 Xt timeouts, if needed. We must avoid calling XtAppPending as
10736 much as possible because that function does an implicit XFlush
10737 that slows us down. */
10738
10739 static void
10740 x_process_timeouts (timer)
10741 struct atimer *timer;
10742 {
10743 if (toolkit_scroll_bar_interaction || popup_activated ())
10744 {
10745 BLOCK_INPUT;
10746 while (XtAppPending (Xt_app_con) & XtIMTimer)
10747 XtAppProcessEvent (Xt_app_con, XtIMTimer);
10748 UNBLOCK_INPUT;
10749 }
10750 }
10751
10752 #endif /* USE_X_TOOLKIT */
10753
10754 \f
10755 /* Set up use of X before we make the first connection. */
10756
10757 extern frame_parm_handler x_frame_parm_handlers[];
10758
10759 static struct redisplay_interface x_redisplay_interface =
10760 {
10761 x_frame_parm_handlers,
10762 x_produce_glyphs,
10763 x_write_glyphs,
10764 x_insert_glyphs,
10765 x_clear_end_of_line,
10766 x_scroll_run,
10767 x_after_update_window_line,
10768 x_update_window_begin,
10769 x_update_window_end,
10770 x_cursor_to,
10771 x_flush,
10772 #ifndef XFlush
10773 x_flush,
10774 #else
10775 0, /* flush_display_optional */
10776 #endif
10777 x_clear_window_mouse_face,
10778 x_get_glyph_overhangs,
10779 x_fix_overlapping_area,
10780 x_draw_fringe_bitmap,
10781 0, /* define_fringe_bitmap */
10782 0, /* destroy_fringe_bitmap */
10783 x_per_char_metric,
10784 x_encode_char,
10785 x_compute_glyph_string_overhangs,
10786 x_draw_glyph_string,
10787 x_define_frame_cursor,
10788 x_clear_frame_area,
10789 x_draw_window_cursor,
10790 x_draw_vertical_window_border,
10791 x_shift_glyphs_for_insert
10792 };
10793
10794
10795 /* This function is called when the last frame on a display is deleted. */
10796 void
10797 x_delete_frame_display (struct display *display)
10798 {
10799 /* We don't do anything, the connection to the X server must remain
10800 open. */
10801 }
10802
10803
10804 struct display *
10805 x_create_frame_display (struct x_display_info *dpyinfo)
10806 {
10807 struct display *display;
10808
10809 display = create_display ();
10810
10811 display->type = output_x_window;
10812 display->display_info.x = dpyinfo;
10813 dpyinfo->frame_display = display;
10814
10815 display->clear_frame_hook = x_clear_frame;
10816 display->ins_del_lines_hook = x_ins_del_lines;
10817 display->delete_glyphs_hook = x_delete_glyphs;
10818 display->ring_bell_hook = XTring_bell;
10819 display->reset_terminal_modes_hook = XTreset_terminal_modes;
10820 display->set_terminal_modes_hook = XTset_terminal_modes;
10821 display->update_begin_hook = x_update_begin;
10822 display->update_end_hook = x_update_end;
10823 display->set_terminal_window_hook = XTset_terminal_window;
10824 display->read_socket_hook = XTread_socket;
10825 display->frame_up_to_date_hook = XTframe_up_to_date;
10826 display->mouse_position_hook = XTmouse_position;
10827 display->frame_rehighlight_hook = XTframe_rehighlight;
10828 display->frame_raise_lower_hook = XTframe_raise_lower;
10829 display->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10830 display->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10831 display->redeem_scroll_bar_hook = XTredeem_scroll_bar;
10832 display->judge_scroll_bars_hook = XTjudge_scroll_bars;
10833
10834 display->delete_frame_hook = x_destroy_window;
10835 display->delete_display_hook = x_delete_frame_display;
10836
10837 display->rif = &x_redisplay_interface;
10838 display->scroll_region_ok = 1; /* We'll scroll partial frames. */
10839 display->char_ins_del_ok = 1;
10840 display->line_ins_del_ok = 1; /* We'll just blt 'em. */
10841 display->fast_clear_end_of_line = 1; /* X does this well. */
10842 display->memory_below_frame = 0; /* We don't remember what scrolls
10843 off the bottom. */
10844
10845 return display;
10846 }
10847
10848 void
10849 x_initialize ()
10850 {
10851 baud_rate = 19200;
10852
10853 x_noop_count = 0;
10854 last_tool_bar_item = -1;
10855 any_help_event_p = 0;
10856 ignore_next_mouse_click_timeout = 0;
10857
10858 #ifdef USE_GTK
10859 current_count = -1;
10860 #endif
10861
10862 /* Try to use interrupt input; if we can't, then start polling. */
10863 Fset_input_mode (Qt, Qnil, Qt, Qnil);
10864
10865 #ifdef USE_X_TOOLKIT
10866 XtToolkitInitialize ();
10867
10868 Xt_app_con = XtCreateApplicationContext ();
10869
10870 /* Register a converter from strings to pixels, which uses
10871 Emacs' color allocation infrastructure. */
10872 XtAppSetTypeConverter (Xt_app_con,
10873 XtRString, XtRPixel, cvt_string_to_pixel,
10874 cvt_string_to_pixel_args,
10875 XtNumber (cvt_string_to_pixel_args),
10876 XtCacheByDisplay, cvt_pixel_dtor);
10877
10878 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
10879
10880 /* Install an asynchronous timer that processes Xt timeout events
10881 every 0.1s. This is necessary because some widget sets use
10882 timeouts internally, for example the LessTif menu bar, or the
10883 Xaw3d scroll bar. When Xt timouts aren't processed, these
10884 widgets don't behave normally. */
10885 {
10886 EMACS_TIME interval;
10887 EMACS_SET_SECS_USECS (interval, 0, 100000);
10888 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
10889 }
10890 #endif
10891
10892 #ifdef USE_TOOLKIT_SCROLL_BARS
10893 #ifndef USE_GTK
10894 xaw3d_arrow_scroll = False;
10895 xaw3d_pick_top = True;
10896 #endif
10897 #endif
10898
10899 /* Note that there is no real way portable across R3/R4 to get the
10900 original error handler. */
10901 XSetErrorHandler (x_error_handler);
10902 XSetIOErrorHandler (x_io_error_quitter);
10903
10904 /* Disable Window Change signals; they are handled by X events. */
10905 #if 0 /* Don't. We may want to open tty frames later. */
10906 #ifdef SIGWINCH
10907 signal (SIGWINCH, SIG_DFL);
10908 #endif /* SIGWINCH */
10909 #endif
10910
10911 signal (SIGPIPE, x_connection_signal);
10912 }
10913
10914
10915 void
10916 syms_of_xterm ()
10917 {
10918 staticpro (&x_error_message_string);
10919 x_error_message_string = Qnil;
10920
10921 staticpro (&x_display_name_list);
10922 x_display_name_list = Qnil;
10923
10924 staticpro (&last_mouse_scroll_bar);
10925 last_mouse_scroll_bar = Qnil;
10926
10927 staticpro (&Qvendor_specific_keysyms);
10928 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
10929
10930 staticpro (&Qutf_8);
10931 Qutf_8 = intern ("utf-8");
10932 staticpro (&Qlatin_1);
10933 Qlatin_1 = intern ("latin-1");
10934
10935 staticpro (&last_mouse_press_frame);
10936 last_mouse_press_frame = Qnil;
10937
10938 DEFVAR_BOOL ("x-use-underline-position-properties",
10939 &x_use_underline_position_properties,
10940 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10941 nil means ignore them. If you encounter fonts with bogus
10942 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10943 to 4.1, set this to nil. */);
10944 x_use_underline_position_properties = 1;
10945
10946 DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
10947 &x_mouse_click_focus_ignore_position,
10948 doc: /* Non-nil means that a mouse click to focus a frame does not move point.
10949 This variable is only used when the window manager requires that you
10950 click on a frame to select it (give it focus). In that case, a value
10951 of nil, means that the selected window and cursor position changes to
10952 reflect the mouse click position, while a non-nil value means that the
10953 selected window or cursor position is preserved. */);
10954 x_mouse_click_focus_ignore_position = 0;
10955
10956 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10957 doc: /* What X toolkit scroll bars Emacs uses.
10958 A value of nil means Emacs doesn't use X toolkit scroll bars.
10959 Otherwise, value is a symbol describing the X toolkit. */);
10960 #ifdef USE_TOOLKIT_SCROLL_BARS
10961 #ifdef USE_MOTIF
10962 Vx_toolkit_scroll_bars = intern ("motif");
10963 #elif defined HAVE_XAW3D
10964 Vx_toolkit_scroll_bars = intern ("xaw3d");
10965 #elif USE_GTK
10966 Vx_toolkit_scroll_bars = intern ("gtk");
10967 #else
10968 Vx_toolkit_scroll_bars = intern ("xaw");
10969 #endif
10970 #else
10971 Vx_toolkit_scroll_bars = Qnil;
10972 #endif
10973
10974 staticpro (&last_mouse_motion_frame);
10975 last_mouse_motion_frame = Qnil;
10976
10977 Qmodifier_value = intern ("modifier-value");
10978 Qalt = intern ("alt");
10979 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10980 Qhyper = intern ("hyper");
10981 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10982 Qmeta = intern ("meta");
10983 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10984 Qsuper = intern ("super");
10985 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10986
10987 DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
10988 doc: /* Which keys Emacs uses for the alt modifier.
10989 This should be one of the symbols `alt', `hyper', `meta', `super'.
10990 For example, `alt' means use the Alt_L and Alt_R keysyms. The default
10991 is nil, which is the same as `alt'. */);
10992 Vx_alt_keysym = Qnil;
10993
10994 DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
10995 doc: /* Which keys Emacs uses for the hyper modifier.
10996 This should be one of the symbols `alt', `hyper', `meta', `super'.
10997 For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
10998 default is nil, which is the same as `hyper'. */);
10999 Vx_hyper_keysym = Qnil;
11000
11001 DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
11002 doc: /* Which keys Emacs uses for the meta modifier.
11003 This should be one of the symbols `alt', `hyper', `meta', `super'.
11004 For example, `meta' means use the Meta_L and Meta_R keysyms. The
11005 default is nil, which is the same as `meta'. */);
11006 Vx_meta_keysym = Qnil;
11007
11008 DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
11009 doc: /* Which keys Emacs uses for the super modifier.
11010 This should be one of the symbols `alt', `hyper', `meta', `super'.
11011 For example, `super' means use the Super_L and Super_R keysyms. The
11012 default is nil, which is the same as `super'. */);
11013 Vx_super_keysym = Qnil;
11014
11015 DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
11016 doc: /* Hash table of character codes indexed by X keysym codes. */);
11017 Vx_keysym_table = make_hash_table (Qeql, make_number (900),
11018 make_float (DEFAULT_REHASH_SIZE),
11019 make_float (DEFAULT_REHASH_THRESHOLD),
11020 Qnil, Qnil, Qnil);
11021 }
11022
11023 #endif /* HAVE_X_WINDOWS */
11024
11025 /* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
11026 (do not change this comment) */