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