]> code.delx.au - gnu-emacs/blob - src/xterm.c
(XTread_socket): For selection_clear_event and
[gnu-emacs] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* Xt features made by Fred Pierresteguy. */
21
22 /* On 4.3 these lose if they come after xterm.h. */
23 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
24 /* Putting these at the beginning seems to be standard for other .c files. */
25 #include <signal.h>
26
27 #include <config.h>
28
29 #include <stdio.h>
30
31 /* Need syssignal.h for various externs and definitions that may be required
32 by some configurations for calls to signal later in this source file. */
33 #include "syssignal.h"
34
35 #ifdef HAVE_X_WINDOWS
36
37 #include "lisp.h"
38 #include "blockinput.h"
39
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
42 #include "xterm.h"
43 #include <X11/cursorfont.h>
44
45 #ifndef USG
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
48 #ifndef makedev
49 #include <sys/types.h>
50 #endif /* makedev */
51 #endif /* USG */
52
53 #ifdef BSD
54 #include <sys/ioctl.h>
55 #endif /* ! defined (BSD) */
56
57 #include "systty.h"
58 #include "systime.h"
59
60 #ifndef INCLUDED_FCNTL
61 #include <fcntl.h>
62 #endif
63 #include <ctype.h>
64 #include <errno.h>
65 #include <setjmp.h>
66 #include <sys/stat.h>
67 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68 /* #include <sys/param.h> */
69
70 #include "frame.h"
71 #include "dispextern.h"
72 #include "termhooks.h"
73 #include "termopts.h"
74 #include "termchar.h"
75 #if 0
76 #include "sink.h"
77 #include "sinkmask.h"
78 #endif /* ! 0 */
79 #include "gnu.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85
86 #ifdef USE_X_TOOLKIT
87 extern void free_frame_menubar ();
88 extern FRAME_PTR x_menubar_window_to_frame ();
89 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
90 #define HACK_EDITRES
91 extern void _XEditResCheckMessages ();
92 #endif /* not NO_EDITRES */
93 #endif /* USE_X_TOOLKIT */
94
95 #ifndef USE_X_TOOLKIT
96 #define x_any_window_to_frame x_window_to_frame
97 #define x_top_window_to_frame x_window_to_frame
98 #endif
99
100 #ifdef USE_X_TOOLKIT
101 #include "widget.h"
102 #ifndef XtNinitialState
103 #define XtNinitialState "initialState"
104 #endif
105 #endif
106
107 #ifdef HAVE_X11XTR6
108 /* So we can do setlocale. */
109 #include <locale.h>
110 #endif
111
112 #define min(a,b) ((a)<(b) ? (a) : (b))
113 #define max(a,b) ((a)>(b) ? (a) : (b))
114 \f
115 /* This is a chain of structures for all the X displays currently in use. */
116 struct x_display_info *x_display_list;
117
118 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
119 one for each element of x_display_list and in the same order.
120 NAME is the name of the frame.
121 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
122 Lisp_Object x_display_name_list;
123
124 /* Frame being updated by update_frame. This is declared in term.c.
125 This is set by update_begin and looked at by all the
126 XT functions. It is zero while not inside an update.
127 In that case, the XT functions assume that `selected_frame'
128 is the frame to apply to. */
129 extern struct frame *updating_frame;
130
131 /* This is a frame waiting to be autoraised, within XTread_socket. */
132 struct frame *pending_autoraise_frame;
133
134 #ifdef USE_X_TOOLKIT
135 /* The application context for Xt use. */
136 XtAppContext Xt_app_con;
137
138 static String Xt_default_resources[] =
139 {
140 0
141 };
142 #endif
143
144 /* During an update, maximum vpos for ins/del line operations to affect. */
145
146 static int flexlines;
147
148 /* During an update, nonzero if chars output now should be highlighted. */
149
150 static int highlight;
151
152 /* Nominal cursor position -- where to draw output.
153 During an update, these are different from the cursor-box position. */
154
155 static int curs_x;
156 static int curs_y;
157
158 /* Mouse movement.
159
160 In order to avoid asking for motion events and then throwing most
161 of them away or busy-polling the server for mouse positions, we ask
162 the server for pointer motion hints. This means that we get only
163 one event per group of mouse movements. "Groups" are delimited by
164 other kinds of events (focus changes and button clicks, for
165 example), or by XQueryPointer calls; when one of these happens, we
166 get another MotionNotify event the next time the mouse moves. This
167 is at least as efficient as getting motion events when mouse
168 tracking is on, and I suspect only negligibly worse when tracking
169 is off.
170
171 The silly O'Reilly & Associates Nutshell guides barely document
172 pointer motion hints at all (I think you have to infer how they
173 work from an example), and the description of XQueryPointer doesn't
174 mention that calling it causes you to get another motion hint from
175 the server, which is very important. */
176
177 /* Where the mouse was last time we reported a mouse event. */
178 static FRAME_PTR last_mouse_frame;
179 static XRectangle last_mouse_glyph;
180
181 /* The scroll bar in which the last X motion event occurred.
182
183 If the last X motion event occurred in a scroll bar, we set this
184 so XTmouse_position can know whether to report a scroll bar motion or
185 an ordinary motion.
186
187 If the last X motion event didn't occur in a scroll bar, we set this
188 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
189 static Lisp_Object last_mouse_scroll_bar;
190
191 /* This is a hack. We would really prefer that XTmouse_position would
192 return the time associated with the position it returns, but there
193 doesn't seem to be any way to wrest the timestamp from the server
194 along with the position query. So, we just keep track of the time
195 of the last movement we received, and return that in hopes that
196 it's somewhat accurate. */
197 static Time last_mouse_movement_time;
198
199 /* Incremented by XTread_socket whenever it really tries to read events. */
200 #ifdef __STDC__
201 static int volatile input_signal_count;
202 #else
203 static int input_signal_count;
204 #endif
205
206 /* Used locally within XTread_socket. */
207 static int x_noop_count;
208
209 /* Initial values of argv and argc. */
210 extern char **initial_argv;
211 extern int initial_argc;
212
213 extern Lisp_Object Vcommand_line_args, Vsystem_name;
214
215 /* Tells if a window manager is present or not. */
216
217 extern Lisp_Object Vx_no_window_manager;
218
219 /* Nonzero enables some debugging for the X interface code. */
220 extern int _Xdebug;
221
222 extern Lisp_Object Qface, Qmouse_face;
223
224 extern int errno;
225
226 /* A mask of extra modifier bits to put into every keyboard char. */
227 extern int extra_keyboard_modifiers;
228
229 static Lisp_Object Qvendor_specific_keysyms;
230
231 extern XrmDatabase x_load_resources ();
232
233 extern Lisp_Object x_icon_type ();
234
235 void x_delete_display ();
236
237 static void redraw_previous_char ();
238 static void redraw_following_char ();
239 static unsigned int x_x_to_emacs_modifiers ();
240
241 static int fast_find_position ();
242 static void note_mouse_highlight ();
243 static void clear_mouse_face ();
244 static void show_mouse_face ();
245 static void do_line_dance ();
246
247 static int XTcursor_to ();
248 static int XTclear_end_of_line ();
249 static int x_io_error_quitter ();
250 void x_catch_errors ();
251 void x_uncatch_errors ();
252 \f
253 #if 0
254 /* This is a function useful for recording debugging information
255 about the sequence of occurrences in this file. */
256
257 struct record
258 {
259 char *locus;
260 int type;
261 };
262
263 struct record event_record[100];
264
265 int event_record_index;
266
267 record_event (locus, type)
268 char *locus;
269 int type;
270 {
271 if (event_record_index == sizeof (event_record) / sizeof (struct record))
272 event_record_index = 0;
273
274 event_record[event_record_index].locus = locus;
275 event_record[event_record_index].type = type;
276 event_record_index++;
277 }
278
279 #endif /* 0 */
280 \f
281 /* Return the struct x_display_info corresponding to DPY. */
282
283 struct x_display_info *
284 x_display_info_for_display (dpy)
285 Display *dpy;
286 {
287 struct x_display_info *dpyinfo;
288
289 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
290 if (dpyinfo->display == dpy)
291 return dpyinfo;
292
293 return 0;
294 }
295 \f
296 /* Starting and ending updates.
297
298 These hooks are called by update_frame at the beginning and end
299 of a frame update. We record in `updating_frame' the identity
300 of the frame being updated, so that the XT... functions do not
301 need to take a frame as argument. Most of the XT... functions
302 should never be called except during an update, the only exceptions
303 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
304
305 static
306 XTupdate_begin (f)
307 struct frame *f;
308 {
309 int mask;
310
311 if (f == 0)
312 abort ();
313
314 flexlines = f->height;
315 highlight = 0;
316
317 BLOCK_INPUT;
318
319 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
320 {
321 /* Don't do highlighting for mouse motion during the update. */
322 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
323
324 /* If the frame needs to be redrawn,
325 simply forget about any prior mouse highlighting. */
326 if (FRAME_GARBAGED_P (f))
327 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil;
328
329 if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
330 {
331 int firstline, lastline, i;
332 struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window);
333
334 /* Find the first, and the last+1, lines affected by redisplay. */
335 for (firstline = 0; firstline < f->height; firstline++)
336 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
337 break;
338
339 lastline = f->height;
340 for (i = f->height - 1; i >= 0; i--)
341 {
342 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
343 break;
344 else
345 lastline = i;
346 }
347
348 /* Can we tell that this update does not affect the window
349 where the mouse highlight is? If so, no need to turn off.
350 Likewise, don't do anything if the frame is garbaged;
351 in that case, the FRAME_CURRENT_GLYPHS that we would use
352 are all wrong, and we will redisplay that line anyway. */
353 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
354 || lastline < XFASTINT (w->top)))
355 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
356 }
357 }
358
359 UNBLOCK_INPUT;
360 }
361
362 static
363 XTupdate_end (f)
364 struct frame *f;
365 {
366 int mask;
367
368 BLOCK_INPUT;
369
370 do_line_dance ();
371 x_display_cursor (f, 1);
372
373 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
374 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
375 #if 0
376 /* This fails in the case of having updated only the echo area
377 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
378 has no relation to the current contents, and its charstarts
379 have no relation to the contents of the window-buffer.
380 I don't know a clean way to check
381 for that case. window_end_valid isn't set up yet. */
382 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
383 note_mouse_highlight (f, FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
384 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
385 #endif
386
387 XFlush (FRAME_X_DISPLAY (f));
388 UNBLOCK_INPUT;
389 }
390
391 /* This is called after a redisplay on frame F. */
392
393 static
394 XTframe_up_to_date (f)
395 FRAME_PTR f;
396 {
397 BLOCK_INPUT;
398 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
399 || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
400 {
401 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame,
402 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
403 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
404 FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
405 }
406 UNBLOCK_INPUT;
407 }
408 \f
409 /* External interface to control of standout mode.
410 Call this when about to modify line at position VPOS
411 and not change whether it is highlighted. */
412
413 XTreassert_line_highlight (new, vpos)
414 int new, vpos;
415 {
416 highlight = new;
417 }
418
419 /* Call this when about to modify line at position VPOS
420 and change whether it is highlighted. */
421
422 static
423 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
424 int new_highlight, vpos, first_unused_hpos;
425 {
426 highlight = new_highlight;
427 XTcursor_to (vpos, 0);
428 XTclear_end_of_line (updating_frame->width);
429 }
430
431 /* This is used when starting Emacs and when restarting after suspend.
432 When starting Emacs, no X window is mapped. And nothing must be done
433 to Emacs's own window if it is suspended (though that rarely happens). */
434
435 static
436 XTset_terminal_modes ()
437 {
438 }
439
440 /* This is called when exiting or suspending Emacs.
441 Exiting will make the X-windows go away, and suspending
442 requires no action. */
443
444 static
445 XTreset_terminal_modes ()
446 {
447 /* XTclear_frame (); */
448 }
449 \f
450 /* Set the nominal cursor position of the frame.
451 This is where display update commands will take effect.
452 This does not affect the place where the cursor-box is displayed. */
453
454 static int
455 XTcursor_to (row, col)
456 register int row, col;
457 {
458 int mask;
459 int orow = row;
460
461 curs_x = col;
462 curs_y = row;
463
464 if (updating_frame == 0)
465 {
466 BLOCK_INPUT;
467 x_display_cursor (selected_frame, 1);
468 XFlush (FRAME_X_DISPLAY (selected_frame));
469 UNBLOCK_INPUT;
470 }
471 }
472 \f
473 /* Display a sequence of N glyphs found at GP.
474 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
475 HL is 1 if this text is highlighted, 2 if the cursor is on it,
476 3 if should appear in its mouse-face.
477 JUST_FOREGROUND if 1 means draw only the foreground;
478 don't alter the background.
479
480 FONT is the default font to use (for glyphs whose font-code is 0).
481
482 Since the display generation code is responsible for calling
483 compute_char_face and compute_glyph_face on everything it puts in
484 the display structure, we can assume that the face code on each
485 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
486 to which we can actually apply intern_face.
487 Call this function with input blocked. */
488
489 #if 1
490 /* This is the multi-face code. */
491
492 static void
493 dumpglyphs (f, left, top, gp, n, hl, just_foreground)
494 struct frame *f;
495 int left, top;
496 register GLYPH *gp; /* Points to first GLYPH. */
497 register int n; /* Number of glyphs to display. */
498 int hl;
499 int just_foreground;
500 {
501 /* Holds characters to be displayed. */
502 char *buf = (char *) alloca (f->width * sizeof (*buf));
503 register char *cp; /* Steps through buf[]. */
504 register int tlen = GLYPH_TABLE_LENGTH;
505 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
506 Window window = FRAME_X_WINDOW (f);
507 int orig_left = left;
508
509 while (n > 0)
510 {
511 /* Get the face-code of the next GLYPH. */
512 int cf, len;
513 int g = *gp;
514
515 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
516 cf = FAST_GLYPH_FACE (g);
517
518 /* Find the run of consecutive glyphs with the same face-code.
519 Extract their character codes into BUF. */
520 cp = buf;
521 while (n > 0)
522 {
523 g = *gp;
524 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
525 if (FAST_GLYPH_FACE (g) != cf)
526 break;
527
528 *cp++ = FAST_GLYPH_CHAR (g);
529 --n;
530 ++gp;
531 }
532
533 /* LEN gets the length of the run. */
534 len = cp - buf;
535
536 /* Now output this run of chars, with the font and pixel values
537 determined by the face code CF. */
538 {
539 struct face *face = FRAME_DEFAULT_FACE (f);
540 XFontStruct *font = FACE_FONT (face);
541 GC gc = FACE_GC (face);
542 int stippled = 0;
543
544 /* HL = 3 means use a mouse face previously chosen. */
545 if (hl == 3)
546 cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id;
547
548 /* First look at the face of the text itself. */
549 if (cf != 0)
550 {
551 /* It's possible for the display table to specify
552 a face code that is out of range. Use 0 in that case. */
553 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
554 || FRAME_COMPUTED_FACES (f) [cf] == 0)
555 cf = 0;
556
557 if (cf == 1)
558 face = FRAME_MODE_LINE_FACE (f);
559 else
560 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
561 font = FACE_FONT (face);
562 gc = FACE_GC (face);
563 if (FACE_STIPPLE (face))
564 stippled = 1;
565 }
566
567 /* Then comes the distinction between modeline and normal text. */
568 else if (hl == 0)
569 ;
570 else if (hl == 1)
571 {
572 face = FRAME_MODE_LINE_FACE (f);
573 font = FACE_FONT (face);
574 gc = FACE_GC (face);
575 if (FACE_STIPPLE (face))
576 stippled = 1;
577 }
578
579 #define FACE_DEFAULT (~0)
580
581 /* Now override that if the cursor's on this character. */
582 if (hl == 2)
583 {
584 /* The cursor overrides stippling. */
585 stippled = 0;
586
587 if ((!face->font
588 || face->font == (XFontStruct *) FACE_DEFAULT
589 || face->font == f->output_data.x->font)
590 && face->background == f->output_data.x->background_pixel
591 && face->foreground == f->output_data.x->foreground_pixel)
592 {
593 gc = f->output_data.x->cursor_gc;
594 }
595 /* Cursor on non-default face: must merge. */
596 else
597 {
598 XGCValues xgcv;
599 unsigned long mask;
600
601 xgcv.background = f->output_data.x->cursor_pixel;
602 xgcv.foreground = face->background;
603 /* If the glyph would be invisible,
604 try a different foreground. */
605 if (xgcv.foreground == xgcv.background)
606 xgcv.foreground = face->foreground;
607 if (xgcv.foreground == xgcv.background)
608 xgcv.foreground = f->output_data.x->cursor_foreground_pixel;
609 if (xgcv.foreground == xgcv.background)
610 xgcv.foreground = face->foreground;
611 /* Make sure the cursor is distinct from text in this face. */
612 if (xgcv.background == face->background
613 && xgcv.foreground == face->foreground)
614 {
615 xgcv.background = face->foreground;
616 xgcv.foreground = face->background;
617 }
618 xgcv.font = face->font->fid;
619 xgcv.graphics_exposures = 0;
620 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
621 if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
622 XChangeGC (FRAME_X_DISPLAY (f),
623 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
624 mask, &xgcv);
625 else
626 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc
627 = XCreateGC (FRAME_X_DISPLAY (f), window, mask, &xgcv);
628 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
629 #if 0
630 /* If this code is restored, it must also reset to the default stipple
631 if necessary. */
632 if (face->stipple && face->stipple != FACE_DEFAULT)
633 XSetStipple (FRAME_X_DISPLAY (f), gc, face->stipple);
634 #endif
635 }
636 }
637
638 if (font == (XFontStruct *) FACE_DEFAULT)
639 font = f->output_data.x->font;
640
641 if (just_foreground)
642 XDrawString (FRAME_X_DISPLAY (f), window, gc,
643 left, top + FONT_BASE (font), buf, len);
644 else
645 {
646 if (stippled)
647 {
648 /* Turn stipple on. */
649 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
650
651 /* Draw stipple on background. */
652 XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
653 left, top,
654 FONT_WIDTH (font) * len,
655 FONT_HEIGHT (font));
656
657 /* Turn stipple off. */
658 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
659
660 /* Draw the text, solidly, onto the stipple pattern. */
661 XDrawString (FRAME_X_DISPLAY (f), window, gc,
662 left, top + FONT_BASE (font), buf, len);
663 }
664 else
665 XDrawImageString (FRAME_X_DISPLAY (f), window, gc,
666 left, top + FONT_BASE (font), buf, len);
667
668 /* Clear the rest of the line's height. */
669 if (f->output_data.x->line_height != FONT_HEIGHT (font))
670 XClearArea (FRAME_X_DISPLAY (f), window, left,
671 top + FONT_HEIGHT (font),
672 FONT_WIDTH (font) * len,
673 /* This is how many pixels of height
674 we have to clear. */
675 f->output_data.x->line_height - FONT_HEIGHT (font),
676 False);
677 }
678
679 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
680 which often is not up to date yet. */
681 if (!just_foreground)
682 {
683 if (left == orig_left)
684 redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
685 PIXEL_TO_CHAR_ROW (f, top), hl == 1);
686 if (n == 0)
687 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
688 PIXEL_TO_CHAR_ROW (f, top), hl == 1);
689 }
690 #endif
691
692 /* We should probably check for XA_UNDERLINE_POSITION and
693 XA_UNDERLINE_THICKNESS properties on the font, but let's
694 just get the thing working, and come back to that. */
695 {
696 int underline_position = 1;
697
698 if (font->descent <= underline_position)
699 underline_position = font->descent - 1;
700
701 if (face->underline)
702 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
703 FACE_GC (face),
704 left, (top
705 + FONT_BASE (font)
706 + underline_position),
707 len * FONT_WIDTH (font), 1);
708 }
709
710 left += len * FONT_WIDTH (font);
711 }
712 }
713 }
714 #endif /* 1 */
715
716 #if 0
717 /* This is the old single-face code. */
718
719 static void
720 dumpglyphs (f, left, top, gp, n, hl, font)
721 struct frame *f;
722 int left, top;
723 register GLYPH *gp; /* Points to first GLYPH. */
724 register int n; /* Number of glyphs to display. */
725 int hl;
726 XFontStruct *font;
727 {
728 register int len;
729 Window window = FRAME_X_WINDOW (f);
730 GC drawing_gc = (hl == 2 ? f->output_data.x->cursor_gc
731 : (hl ? f->output_data.x->reverse_gc
732 : f->output_data.x->normal_gc));
733
734 if (sizeof (GLYPH) == sizeof (XChar2b))
735 XDrawImageString16 (FRAME_X_DISPLAY (f), window, drawing_gc,
736 left, top + FONT_BASE (font), (XChar2b *) gp, n);
737 else if (sizeof (GLYPH) == sizeof (unsigned char))
738 XDrawImageString (FRAME_X_DISPLAY (f), window, drawing_gc,
739 left, top + FONT_BASE (font), (char *) gp, n);
740 else
741 /* What size of glyph ARE you using? And does X have a function to
742 draw them? */
743 abort ();
744 }
745 #endif
746 \f
747 /* Output some text at the nominal frame cursor position.
748 Advance the cursor over the text.
749 Output LEN glyphs at START.
750
751 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
752 controls the pixel values used for foreground and background. */
753
754 static
755 XTwrite_glyphs (start, len)
756 register GLYPH *start;
757 int len;
758 {
759 register int temp_length;
760 int mask;
761 struct frame *f;
762
763 BLOCK_INPUT;
764
765 do_line_dance ();
766 f = updating_frame;
767 if (f == 0)
768 {
769 f = selected_frame;
770 /* If not within an update,
771 output at the frame's visible cursor. */
772 curs_x = f->cursor_x;
773 curs_y = f->cursor_y;
774 }
775
776 dumpglyphs (f,
777 CHAR_TO_PIXEL_COL (f, curs_x),
778 CHAR_TO_PIXEL_ROW (f, curs_y),
779 start, len, highlight, 0);
780
781 /* If we drew on top of the cursor, note that it is turned off. */
782 if (curs_y == f->phys_cursor_y
783 && curs_x <= f->phys_cursor_x
784 && curs_x + len > f->phys_cursor_x)
785 f->phys_cursor_x = -1;
786
787 if (updating_frame == 0)
788 {
789 f->cursor_x += len;
790 x_display_cursor (f, 1);
791 f->cursor_x -= len;
792 }
793 else
794 curs_x += len;
795
796 UNBLOCK_INPUT;
797 }
798 \f
799 /* Clear to the end of the line.
800 Erase the current text line from the nominal cursor position (inclusive)
801 to column FIRST_UNUSED (exclusive). The idea is that everything
802 from FIRST_UNUSED onward is already erased. */
803
804 static
805 XTclear_end_of_line (first_unused)
806 register int first_unused;
807 {
808 struct frame *f = updating_frame;
809 int mask;
810
811 if (f == 0)
812 abort ();
813
814 if (curs_y < 0 || curs_y >= f->height)
815 return;
816 if (first_unused <= 0)
817 return;
818
819 if (first_unused >= f->width)
820 first_unused = f->width;
821
822 BLOCK_INPUT;
823
824 do_line_dance ();
825
826 /* Notice if the cursor will be cleared by this operation. */
827 if (curs_y == f->phys_cursor_y
828 && curs_x <= f->phys_cursor_x
829 && f->phys_cursor_x < first_unused)
830 f->phys_cursor_x = -1;
831
832 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
833 CHAR_TO_PIXEL_COL (f, curs_x),
834 CHAR_TO_PIXEL_ROW (f, curs_y),
835 FONT_WIDTH (f->output_data.x->font) * (first_unused - curs_x),
836 f->output_data.x->line_height, False);
837 #if 0
838 redraw_previous_char (f, curs_x, curs_y, highlight);
839 #endif
840
841 UNBLOCK_INPUT;
842 }
843
844 static
845 XTclear_frame ()
846 {
847 int mask;
848 struct frame *f = updating_frame;
849
850 if (f == 0)
851 f = selected_frame;
852
853 f->phys_cursor_x = -1; /* Cursor not visible. */
854 curs_x = 0; /* Nominal cursor position is top left. */
855 curs_y = 0;
856
857 BLOCK_INPUT;
858
859 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
860
861 /* We have to clear the scroll bars, too. If we have changed
862 colors or something like that, then they should be notified. */
863 x_scroll_bar_clear (f);
864
865 XFlush (FRAME_X_DISPLAY (f));
866 UNBLOCK_INPUT;
867 }
868 \f
869 #if 0
870 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
871 always contain the right glyphs to use.
872
873 It also needs to be changed to look at the details of the font and
874 see whether there is really overlap, and do nothing when there is
875 not. This can use font_char_overlap_left and font_char_overlap_right,
876 but just how to use them is not clear. */
877
878 /* Erase the character (if any) at the position just before X, Y in frame F,
879 then redraw it and the character before it.
880 This is necessary when we erase starting at X,
881 in case the character after X overlaps into the one before X.
882 Call this function with input blocked. */
883
884 static void
885 redraw_previous_char (f, x, y, highlight_flag)
886 FRAME_PTR f;
887 int x, y;
888 int highlight_flag;
889 {
890 /* Erase the character before the new ones, in case
891 what was here before overlaps it.
892 Reoutput that character, and the previous character
893 (in case the previous character overlaps it). */
894 if (x > 0)
895 {
896 int start_x = x - 2;
897 if (start_x < 0)
898 start_x = 0;
899 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
900 CHAR_TO_PIXEL_COL (f, x - 1),
901 CHAR_TO_PIXEL_ROW (f, y),
902 FONT_WIDTH (f->output_data.x->font),
903 f->output_data.x->line_height, False);
904
905 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
906 CHAR_TO_PIXEL_ROW (f, y),
907 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
908 x - start_x, highlight_flag, 1);
909 }
910 }
911
912 /* Erase the character (if any) at the position X, Y in frame F,
913 then redraw it and the character after it.
914 This is necessary when we erase endng at X,
915 in case the character after X overlaps into the one before X.
916 Call this function with input blocked. */
917
918 static void
919 redraw_following_char (f, x, y, highlight_flag)
920 FRAME_PTR f;
921 int x, y;
922 int highlight_flag;
923 {
924 int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
925 /* Erase the character after the new ones, in case
926 what was here before overlaps it.
927 Reoutput that character, and the following character
928 (in case the following character overlaps it). */
929 if (x < limit
930 && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
931 {
932 int end_x = x + 2;
933 if (end_x > limit)
934 end_x = limit;
935 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
936 CHAR_TO_PIXEL_COL (f, x),
937 CHAR_TO_PIXEL_ROW (f, y),
938 FONT_WIDTH (f->output_data.x->font),
939 f->output_data.x->line_height, False);
940
941 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
942 CHAR_TO_PIXEL_ROW (f, y),
943 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
944 end_x - x, highlight_flag, 1);
945 }
946 }
947 #endif /* 0 */
948 \f
949 #if 0 /* Not in use yet */
950
951 /* Return 1 if character C in font F extends past its left edge. */
952
953 static int
954 font_char_overlap_left (font, c)
955 XFontStruct *font;
956 int c;
957 {
958 XCharStruct *s;
959
960 /* Find the bounding-box info for C. */
961 if (font->per_char == 0)
962 s = &font->max_bounds;
963 else
964 {
965 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
966 int row, within;
967
968 /* Decode char into row number (byte 1) and code within row (byte 2). */
969 row = c >> 8;
970 within = c & 0177;
971 if (!(within >= font->min_char_or_byte2
972 && within <= font->max_char_or_byte2
973 && row >= font->min_byte1
974 && row <= font->max_byte1))
975 {
976 /* If char is out of range, try the font's default char instead. */
977 c = font->default_char;
978 row = c >> (BITS_PER_INT - 8);
979 within = c & 0177;
980 }
981 if (!(within >= font->min_char_or_byte2
982 && within <= font->max_char_or_byte2
983 && row >= font->min_byte1
984 && row <= font->max_byte1))
985 /* Still out of range means this char does not overlap. */
986 return 0;
987 else
988 /* We found the info for this char. */
989 s = (font->per_char + (within - font->min_char_or_byte2)
990 + row * rowlen);
991 }
992
993 return (s && s->lbearing < 0);
994 }
995
996 /* Return 1 if character C in font F extends past its right edge. */
997
998 static int
999 font_char_overlap_right (font, c)
1000 XFontStruct *font;
1001 int c;
1002 {
1003 XCharStruct *s;
1004
1005 /* Find the bounding-box info for C. */
1006 if (font->per_char == 0)
1007 s = &font->max_bounds;
1008 else
1009 {
1010 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
1011 int row, within;
1012
1013 /* Decode char into row number (byte 1) and code within row (byte 2). */
1014 row = c >> 8;
1015 within = c & 0177;
1016 if (!(within >= font->min_char_or_byte2
1017 && within <= font->max_char_or_byte2
1018 && row >= font->min_byte1
1019 && row <= font->max_byte1))
1020 {
1021 /* If char is out of range, try the font's default char instead. */
1022 c = font->default_char;
1023 row = c >> (BITS_PER_INT - 8);
1024 within = c & 0177;
1025 }
1026 if (!(within >= font->min_char_or_byte2
1027 && within <= font->max_char_or_byte2
1028 && row >= font->min_byte1
1029 && row <= font->max_byte1))
1030 /* Still out of range means this char does not overlap. */
1031 return 0;
1032 else
1033 /* We found the info for this char. */
1034 s = (font->per_char + (within - font->min_char_or_byte2)
1035 + row * rowlen);
1036 }
1037
1038 return (s && s->rbearing >= s->width);
1039 }
1040 #endif /* 0 */
1041 \f
1042 /* Invert the middle quarter of the frame for .15 sec. */
1043
1044 /* We use the select system call to do the waiting, so we have to make sure
1045 it's available. If it isn't, we just won't do visual bells. */
1046 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1047
1048 /* Subtract the `struct timeval' values X and Y,
1049 storing the result in RESULT.
1050 Return 1 if the difference is negative, otherwise 0. */
1051
1052 static int
1053 timeval_subtract (result, x, y)
1054 struct timeval *result, x, y;
1055 {
1056 /* Perform the carry for the later subtraction by updating y.
1057 This is safer because on some systems
1058 the tv_sec member is unsigned. */
1059 if (x.tv_usec < y.tv_usec)
1060 {
1061 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
1062 y.tv_usec -= 1000000 * nsec;
1063 y.tv_sec += nsec;
1064 }
1065 if (x.tv_usec - y.tv_usec > 1000000)
1066 {
1067 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
1068 y.tv_usec += 1000000 * nsec;
1069 y.tv_sec -= nsec;
1070 }
1071
1072 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1073 result->tv_sec = x.tv_sec - y.tv_sec;
1074 result->tv_usec = x.tv_usec - y.tv_usec;
1075
1076 /* Return indication of whether the result should be considered negative. */
1077 return x.tv_sec < y.tv_sec;
1078 }
1079
1080 XTflash (f)
1081 struct frame *f;
1082 {
1083 BLOCK_INPUT;
1084
1085 {
1086 GC gc;
1087
1088 /* Create a GC that will use the GXxor function to flip foreground pixels
1089 into background pixels. */
1090 {
1091 XGCValues values;
1092
1093 values.function = GXxor;
1094 values.foreground = (f->output_data.x->foreground_pixel
1095 ^ f->output_data.x->background_pixel);
1096
1097 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1098 GCFunction | GCForeground, &values);
1099 }
1100
1101 {
1102 int width = PIXEL_WIDTH (f);
1103 int height = PIXEL_HEIGHT (f);
1104
1105 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
1106 width/4, height/4, width/2, height/2);
1107 XFlush (FRAME_X_DISPLAY (f));
1108
1109 {
1110 struct timeval wakeup, now;
1111
1112 EMACS_GET_TIME (wakeup);
1113
1114 /* Compute time to wait until, propagating carry from usecs. */
1115 wakeup.tv_usec += 150000;
1116 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
1117 wakeup.tv_usec %= 1000000;
1118
1119 /* Keep waiting until past the time wakeup. */
1120 while (1)
1121 {
1122 struct timeval timeout;
1123
1124 EMACS_GET_TIME (timeout);
1125
1126 /* In effect, timeout = wakeup - timeout.
1127 Break if result would be negative. */
1128 if (timeval_subtract (&timeout, wakeup, timeout))
1129 break;
1130
1131 /* Try to wait that long--but we might wake up sooner. */
1132 select (0, NULL, NULL, NULL, &timeout);
1133 }
1134 }
1135
1136 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
1137 width/4, height/4, width/2, height/2);
1138 XFreeGC (FRAME_X_DISPLAY (f), gc);
1139 XFlush (FRAME_X_DISPLAY (f));
1140 }
1141 }
1142
1143 UNBLOCK_INPUT;
1144 }
1145
1146 #endif
1147
1148
1149 /* Make audible bell. */
1150
1151 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1152
1153 XTring_bell ()
1154 {
1155 if (FRAME_X_DISPLAY (selected_frame) == 0)
1156 return;
1157
1158 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1159 if (visible_bell)
1160 XTflash (selected_frame);
1161 else
1162 #endif
1163 {
1164 BLOCK_INPUT;
1165 XRINGBELL;
1166 XFlush (FRAME_X_DISPLAY (selected_frame));
1167 UNBLOCK_INPUT;
1168 }
1169 }
1170 \f
1171 /* Insert and delete character.
1172 These are not supposed to be used because we are supposed to turn
1173 off the feature of using them. */
1174
1175 static
1176 XTinsert_glyphs (start, len)
1177 register char *start;
1178 register int len;
1179 {
1180 abort ();
1181 }
1182
1183 static
1184 XTdelete_glyphs (n)
1185 register int n;
1186 {
1187 abort ();
1188 }
1189 \f
1190 /* Specify how many text lines, from the top of the window,
1191 should be affected by insert-lines and delete-lines operations.
1192 This, and those operations, are used only within an update
1193 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1194
1195 static
1196 XTset_terminal_window (n)
1197 register int n;
1198 {
1199 if (updating_frame == 0)
1200 abort ();
1201
1202 if ((n <= 0) || (n > updating_frame->height))
1203 flexlines = updating_frame->height;
1204 else
1205 flexlines = n;
1206 }
1207 \f
1208 /* These variables need not be per frame
1209 because redisplay is done on a frame-by-frame basis
1210 and the line dance for one frame is finished before
1211 anything is done for anoter frame. */
1212
1213 /* Array of line numbers from cached insert/delete operations.
1214 line_dance[i] is the old position of the line that we want
1215 to move to line i, or -1 if we want a blank line there. */
1216 static int *line_dance;
1217
1218 /* Allocated length of that array. */
1219 static int line_dance_len;
1220
1221 /* Flag indicating whether we've done any work. */
1222 static int line_dance_in_progress;
1223
1224 /* Perform an insert-lines or delete-lines operation,
1225 inserting N lines or deleting -N lines at vertical position VPOS. */
1226 XTins_del_lines (vpos, n)
1227 int vpos, n;
1228 {
1229 register int fence, i;
1230
1231 if (vpos >= flexlines)
1232 return;
1233
1234 if (!line_dance_in_progress)
1235 {
1236 int ht = updating_frame->height;
1237 if (ht > line_dance_len)
1238 {
1239 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
1240 line_dance_len = ht;
1241 }
1242 for (i = 0; i < ht; ++i) line_dance[i] = i;
1243 line_dance_in_progress = 1;
1244 }
1245 if (n >= 0)
1246 {
1247 if (n > flexlines - vpos)
1248 n = flexlines - vpos;
1249 fence = vpos + n;
1250 for (i = flexlines; --i >= fence;)
1251 line_dance[i] = line_dance[i-n];
1252 for (i = fence; --i >= vpos;)
1253 line_dance[i] = -1;
1254 }
1255 else
1256 {
1257 n = -n;
1258 if (n > flexlines - vpos)
1259 n = flexlines - vpos;
1260 fence = flexlines - n;
1261 for (i = vpos; i < fence; ++i)
1262 line_dance[i] = line_dance[i + n];
1263 for (i = fence; i < flexlines; ++i)
1264 line_dance[i] = -1;
1265 }
1266 }
1267
1268 /* Here's where we actually move the pixels around.
1269 Must be called with input blocked. */
1270 static void
1271 do_line_dance ()
1272 {
1273 register int i, j, distance;
1274 register struct frame *f;
1275 int ht;
1276 int intborder;
1277
1278 /* Must check this flag first. If it's not set, then not only is the
1279 array uninitialized, but we might not even have a frame. */
1280 if (!line_dance_in_progress)
1281 return;
1282
1283 f = updating_frame;
1284 if (f == 0)
1285 abort ();
1286
1287 ht = f->height;
1288 intborder = f->output_data.x->internal_border_width;
1289
1290 x_display_cursor (updating_frame, 0);
1291
1292 for (i = 0; i < ht; ++i)
1293 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
1294 {
1295 for (j = i; (j < ht && line_dance[j] != -1
1296 && line_dance[j]-j == distance); ++j);
1297 /* Copy [i,j) upward from [i+distance,j+distance) */
1298 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1299 FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
1300 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
1301 f->width * FONT_WIDTH (f->output_data.x->font),
1302 (j-i) * f->output_data.x->line_height,
1303 intborder, CHAR_TO_PIXEL_ROW (f, i));
1304 i = j-1;
1305 }
1306
1307 for (i = ht; --i >=0; )
1308 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
1309 {
1310 for (j = i; (--j >= 0 && line_dance[j] != -1
1311 && line_dance[j]-j == distance););
1312 /* Copy (j,i] downward from (j+distance, i+distance] */
1313 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1314 FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
1315 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
1316 f->width * FONT_WIDTH (f->output_data.x->font),
1317 (i-j) * f->output_data.x->line_height,
1318 intborder, CHAR_TO_PIXEL_ROW (f, j+1));
1319 i = j+1;
1320 }
1321
1322 for (i = 0; i < ht; ++i)
1323 if (line_dance[i] == -1)
1324 {
1325 for (j = i; j < ht && line_dance[j] == -1; ++j);
1326 /* Clear [i,j) */
1327 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1328 intborder, CHAR_TO_PIXEL_ROW (f, i),
1329 f->width * FONT_WIDTH (f->output_data.x->font),
1330 (j-i) * f->output_data.x->line_height, False);
1331 i = j-1;
1332 }
1333 line_dance_in_progress = 0;
1334 }
1335 \f
1336 /* Support routines for exposure events. */
1337 static void clear_cursor ();
1338
1339 /* Output into a rectangle of an X-window (for frame F)
1340 the characters in f->phys_lines that overlap that rectangle.
1341 TOP and LEFT are the position of the upper left corner of the rectangle.
1342 ROWS and COLS are the size of the rectangle.
1343 Call this function with input blocked. */
1344
1345 static void
1346 dumprectangle (f, left, top, cols, rows)
1347 struct frame *f;
1348 register int left, top, cols, rows;
1349 {
1350 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1351 int cursor_cleared = 0;
1352 int bottom, right;
1353 register int y;
1354
1355 if (FRAME_GARBAGED_P (f))
1356 return;
1357
1358 /* Express rectangle as four edges, instead of position-and-size. */
1359 bottom = top + rows;
1360 right = left + cols;
1361
1362 /* Convert rectangle edges in pixels to edges in chars.
1363 Round down for left and top, up for right and bottom. */
1364 top = PIXEL_TO_CHAR_ROW (f, top);
1365 left = PIXEL_TO_CHAR_COL (f, left);
1366 bottom += (f->output_data.x->line_height - 1);
1367 right += (FONT_WIDTH (f->output_data.x->font) - 1);
1368 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1369 right = PIXEL_TO_CHAR_COL (f, right);
1370
1371 /* Clip the rectangle to what can be visible. */
1372 if (left < 0)
1373 left = 0;
1374 if (top < 0)
1375 top = 0;
1376 if (right > f->width)
1377 right = f->width;
1378 if (bottom > f->height)
1379 bottom = f->height;
1380
1381 /* Get size in chars of the rectangle. */
1382 cols = right - left;
1383 rows = bottom - top;
1384
1385 /* If rectangle has zero area, return. */
1386 if (rows <= 0) return;
1387 if (cols <= 0) return;
1388
1389 /* Turn off the cursor if it is in the rectangle.
1390 We will turn it back on afterward. */
1391 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1392 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1393 {
1394 clear_cursor (f);
1395 cursor_cleared = 1;
1396 }
1397
1398 /* Display the text in the rectangle, one text line at a time. */
1399
1400 for (y = top; y < bottom; y++)
1401 {
1402 GLYPH *line = &active_frame->glyphs[y][left];
1403
1404 if (! active_frame->enable[y] || left > active_frame->used[y])
1405 continue;
1406
1407 dumpglyphs (f,
1408 CHAR_TO_PIXEL_COL (f, left),
1409 CHAR_TO_PIXEL_ROW (f, y),
1410 line, min (cols, active_frame->used[y] - left),
1411 active_frame->highlight[y], 0);
1412 }
1413
1414 /* Turn the cursor on if we turned it off. */
1415
1416 if (cursor_cleared)
1417 x_display_cursor (f, 1);
1418 }
1419 \f
1420 static void
1421 frame_highlight (f)
1422 struct frame *f;
1423 {
1424 /* We used to only do this if Vx_no_window_manager was non-nil, but
1425 the ICCCM (section 4.1.6) says that the window's border pixmap
1426 and border pixel are window attributes which are "private to the
1427 client", so we can always change it to whatever we want. */
1428 BLOCK_INPUT;
1429 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1430 f->output_data.x->border_pixel);
1431 UNBLOCK_INPUT;
1432 x_update_cursor (f, 1);
1433 }
1434
1435 static void
1436 frame_unhighlight (f)
1437 struct frame *f;
1438 {
1439 /* We used to only do this if Vx_no_window_manager was non-nil, but
1440 the ICCCM (section 4.1.6) says that the window's border pixmap
1441 and border pixel are window attributes which are "private to the
1442 client", so we can always change it to whatever we want. */
1443 BLOCK_INPUT;
1444 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1445 f->output_data.x->border_tile);
1446 UNBLOCK_INPUT;
1447 x_update_cursor (f, 1);
1448 }
1449
1450 static void XTframe_rehighlight ();
1451 static void x_frame_rehighlight ();
1452
1453 /* The focus has changed. Update the frames as necessary to reflect
1454 the new situation. Note that we can't change the selected frame
1455 here, because the Lisp code we are interrupting might become confused.
1456 Each event gets marked with the frame in which it occurred, so the
1457 Lisp code can tell when the switch took place by examining the events. */
1458
1459 static void
1460 x_new_focus_frame (dpyinfo, frame)
1461 struct x_display_info *dpyinfo;
1462 struct frame *frame;
1463 {
1464 struct frame *old_focus = dpyinfo->x_focus_frame;
1465 int events_enqueued = 0;
1466
1467 if (frame != dpyinfo->x_focus_frame)
1468 {
1469 /* Set this before calling other routines, so that they see
1470 the correct value of x_focus_frame. */
1471 dpyinfo->x_focus_frame = frame;
1472
1473 if (old_focus && old_focus->auto_lower)
1474 x_lower_frame (old_focus);
1475
1476 #if 0
1477 selected_frame = frame;
1478 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
1479 selected_frame);
1480 Fselect_window (selected_frame->selected_window);
1481 choose_minibuf_frame ();
1482 #endif /* ! 0 */
1483
1484 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
1485 pending_autoraise_frame = dpyinfo->x_focus_frame;
1486 else
1487 pending_autoraise_frame = 0;
1488 }
1489
1490 x_frame_rehighlight (dpyinfo);
1491 }
1492
1493 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1494
1495 void
1496 x_mouse_leave (dpyinfo)
1497 struct x_display_info *dpyinfo;
1498 {
1499 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
1500 }
1501
1502 /* The focus has changed, or we have redirected a frame's focus to
1503 another frame (this happens when a frame uses a surrogate
1504 minibuffer frame). Shift the highlight as appropriate.
1505
1506 The FRAME argument doesn't necessarily have anything to do with which
1507 frame is being highlighted or unhighlighted; we only use it to find
1508 the appropriate X display info. */
1509 static void
1510 XTframe_rehighlight (frame)
1511 struct frame *frame;
1512 {
1513 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
1514 }
1515
1516 static void
1517 x_frame_rehighlight (dpyinfo)
1518 struct x_display_info *dpyinfo;
1519 {
1520 struct frame *old_highlight = dpyinfo->x_highlight_frame;
1521
1522 if (dpyinfo->x_focus_frame)
1523 {
1524 dpyinfo->x_highlight_frame
1525 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
1526 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1527 : dpyinfo->x_focus_frame);
1528 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
1529 {
1530 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
1531 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
1532 }
1533 }
1534 else
1535 dpyinfo->x_highlight_frame = 0;
1536
1537 if (dpyinfo->x_highlight_frame != old_highlight)
1538 {
1539 if (old_highlight)
1540 frame_unhighlight (old_highlight);
1541 if (dpyinfo->x_highlight_frame)
1542 frame_highlight (dpyinfo->x_highlight_frame);
1543 }
1544 }
1545 \f
1546 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1547
1548 /* Initialize mode_switch_bit and modifier_meaning. */
1549 static void
1550 x_find_modifier_meanings (dpyinfo)
1551 struct x_display_info *dpyinfo;
1552 {
1553 int min_code, max_code;
1554 KeySym *syms;
1555 int syms_per_code;
1556 XModifierKeymap *mods;
1557
1558 dpyinfo->meta_mod_mask = 0;
1559 dpyinfo->shift_lock_mask = 0;
1560 dpyinfo->alt_mod_mask = 0;
1561 dpyinfo->super_mod_mask = 0;
1562 dpyinfo->hyper_mod_mask = 0;
1563
1564 #ifdef HAVE_X11R4
1565 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
1566 #else
1567 min_code = dpyinfo->display->min_keycode;
1568 max_code = dpyinfo->display->max_keycode;
1569 #endif
1570
1571 syms = XGetKeyboardMapping (dpyinfo->display,
1572 min_code, max_code - min_code + 1,
1573 &syms_per_code);
1574 mods = XGetModifierMapping (dpyinfo->display);
1575
1576 /* Scan the modifier table to see which modifier bits the Meta and
1577 Alt keysyms are on. */
1578 {
1579 int row, col; /* The row and column in the modifier table. */
1580
1581 for (row = 3; row < 8; row++)
1582 for (col = 0; col < mods->max_keypermod; col++)
1583 {
1584 KeyCode code
1585 = mods->modifiermap[(row * mods->max_keypermod) + col];
1586
1587 /* Zeroes are used for filler. Skip them. */
1588 if (code == 0)
1589 continue;
1590
1591 /* Are any of this keycode's keysyms a meta key? */
1592 {
1593 int code_col;
1594
1595 for (code_col = 0; code_col < syms_per_code; code_col++)
1596 {
1597 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1598
1599 switch (sym)
1600 {
1601 case XK_Meta_L:
1602 case XK_Meta_R:
1603 dpyinfo->meta_mod_mask |= (1 << row);
1604 break;
1605
1606 case XK_Alt_L:
1607 case XK_Alt_R:
1608 dpyinfo->alt_mod_mask |= (1 << row);
1609 break;
1610
1611 case XK_Hyper_L:
1612 case XK_Hyper_R:
1613 dpyinfo->hyper_mod_mask |= (1 << row);
1614 break;
1615
1616 case XK_Super_L:
1617 case XK_Super_R:
1618 dpyinfo->super_mod_mask |= (1 << row);
1619 break;
1620
1621 case XK_Shift_Lock:
1622 /* Ignore this if it's not on the lock modifier. */
1623 if ((1 << row) == LockMask)
1624 dpyinfo->shift_lock_mask = LockMask;
1625 break;
1626 }
1627 }
1628 }
1629 }
1630 }
1631
1632 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1633 if (! dpyinfo->meta_mod_mask)
1634 {
1635 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
1636 dpyinfo->alt_mod_mask = 0;
1637 }
1638
1639 /* If some keys are both alt and meta,
1640 make them just meta, not alt. */
1641 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
1642 {
1643 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
1644 }
1645
1646 XFree ((char *) syms);
1647 XFreeModifiermap (mods);
1648 }
1649
1650 /* Convert between the modifier bits X uses and the modifier bits
1651 Emacs uses. */
1652 static unsigned int
1653 x_x_to_emacs_modifiers (dpyinfo, state)
1654 struct x_display_info *dpyinfo;
1655 unsigned int state;
1656 {
1657 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
1658 | ((state & ControlMask) ? ctrl_modifier : 0)
1659 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
1660 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
1661 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
1662 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
1663 }
1664
1665 static unsigned int
1666 x_emacs_to_x_modifiers (dpyinfo, state)
1667 struct x_display_info *dpyinfo;
1668 unsigned int state;
1669 {
1670 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
1671 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
1672 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
1673 | ((state & shift_modifier) ? ShiftMask : 0)
1674 | ((state & ctrl_modifier) ? ControlMask : 0)
1675 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
1676 }
1677
1678 /* Convert a keysym to its name. */
1679
1680 char *
1681 x_get_keysym_name (keysym)
1682 KeySym keysym;
1683 {
1684 char *value;
1685
1686 BLOCK_INPUT;
1687 value = XKeysymToString (keysym);
1688 UNBLOCK_INPUT;
1689
1690 return value;
1691 }
1692 \f
1693 /* Mouse clicks and mouse movement. Rah. */
1694
1695 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1696 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1697 that the glyph at X, Y occupies, if BOUNDS != 0.
1698 If NOCLIP is nonzero, do not force the value into range. */
1699
1700 void
1701 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1702 FRAME_PTR f;
1703 register int pix_x, pix_y;
1704 register int *x, *y;
1705 XRectangle *bounds;
1706 int noclip;
1707 {
1708 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1709 even for negative values. */
1710 if (pix_x < 0)
1711 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
1712 if (pix_y < 0)
1713 pix_y -= (f)->output_data.x->line_height - 1;
1714
1715 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1716 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1717
1718 if (bounds)
1719 {
1720 bounds->width = FONT_WIDTH (f->output_data.x->font);
1721 bounds->height = f->output_data.x->line_height;
1722 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1723 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1724 }
1725
1726 if (!noclip)
1727 {
1728 if (pix_x < 0)
1729 pix_x = 0;
1730 else if (pix_x > f->width)
1731 pix_x = f->width;
1732
1733 if (pix_y < 0)
1734 pix_y = 0;
1735 else if (pix_y > f->height)
1736 pix_y = f->height;
1737 }
1738
1739 *x = pix_x;
1740 *y = pix_y;
1741 }
1742
1743 void
1744 glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1745 FRAME_PTR f;
1746 register int x, y;
1747 register int *pix_x, *pix_y;
1748 {
1749 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1750 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1751 }
1752
1753 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1754
1755 If the event is a button press, then note that we have grabbed
1756 the mouse. */
1757
1758 static Lisp_Object
1759 construct_mouse_click (result, event, f)
1760 struct input_event *result;
1761 XButtonEvent *event;
1762 struct frame *f;
1763 {
1764 /* Make the event type no_event; we'll change that when we decide
1765 otherwise. */
1766 result->kind = mouse_click;
1767 result->code = event->button - Button1;
1768 result->timestamp = event->time;
1769 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
1770 event->state)
1771 | (event->type == ButtonRelease
1772 ? up_modifier
1773 : down_modifier));
1774
1775 {
1776 int row, column;
1777
1778 #if 0
1779 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
1780 XSETFASTINT (result->x, column);
1781 XSETFASTINT (result->y, row);
1782 #endif
1783 XSETINT (result->x, event->x);
1784 XSETINT (result->y, event->y);
1785 XSETFRAME (result->frame_or_window, f);
1786 }
1787 }
1788
1789 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1790
1791 static Lisp_Object
1792 construct_menu_click (result, event, f)
1793 struct input_event *result;
1794 XButtonEvent *event;
1795 struct frame *f;
1796 {
1797 /* Make the event type no_event; we'll change that when we decide
1798 otherwise. */
1799 result->kind = mouse_click;
1800 XSETINT (result->code, event->button - Button1);
1801 result->timestamp = event->time;
1802 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
1803 event->state)
1804 | (event->type == ButtonRelease
1805 ? up_modifier
1806 : down_modifier));
1807
1808 XSETINT (result->x, event->x);
1809 XSETINT (result->y, -1);
1810 XSETFRAME (result->frame_or_window, f);
1811 }
1812 \f
1813 /* Function to report a mouse movement to the mainstream Emacs code.
1814 The input handler calls this.
1815
1816 We have received a mouse movement event, which is given in *event.
1817 If the mouse is over a different glyph than it was last time, tell
1818 the mainstream emacs code by setting mouse_moved. If not, ask for
1819 another motion event, so we can check again the next time it moves. */
1820
1821 static void
1822 note_mouse_movement (frame, event)
1823 FRAME_PTR frame;
1824 XMotionEvent *event;
1825 {
1826 last_mouse_movement_time = event->time;
1827
1828 if (event->window != FRAME_X_WINDOW (frame))
1829 {
1830 frame->mouse_moved = 1;
1831 last_mouse_scroll_bar = Qnil;
1832
1833 note_mouse_highlight (frame, -1, -1);
1834
1835 /* Ask for another mouse motion event. */
1836 {
1837 int dummy;
1838 Window dummy_window;
1839
1840 XQueryPointer (event->display, FRAME_X_WINDOW (frame),
1841 &dummy_window, &dummy_window,
1842 &dummy, &dummy, &dummy, &dummy,
1843 (unsigned int *) &dummy);
1844 }
1845 }
1846
1847 /* Has the mouse moved off the glyph it was on at the last sighting? */
1848 else if (event->x < last_mouse_glyph.x
1849 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1850 || event->y < last_mouse_glyph.y
1851 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1852 {
1853 frame->mouse_moved = 1;
1854 last_mouse_scroll_bar = Qnil;
1855
1856 note_mouse_highlight (frame, event->x, event->y);
1857
1858 /* Ask for another mouse motion event. */
1859 {
1860 int dummy;
1861 Window dummy_window;
1862
1863 XQueryPointer (event->display, FRAME_X_WINDOW (frame),
1864 &dummy_window, &dummy_window,
1865 &dummy, &dummy, &dummy, &dummy,
1866 (unsigned int *) &dummy);
1867 }
1868 }
1869 else
1870 {
1871 /* It's on the same glyph. Call XQueryPointer so we'll get an
1872 event the next time the mouse moves and we can see if it's
1873 *still* on the same glyph. */
1874 int dummy;
1875 Window dummy_window;
1876
1877 XQueryPointer (event->display, FRAME_X_WINDOW (frame),
1878 &dummy_window, &dummy_window,
1879 &dummy, &dummy, &dummy, &dummy,
1880 (unsigned int *) &dummy);
1881 }
1882 }
1883
1884 /* This is used for debugging, to turn off note_mouse_highlight. */
1885 static int disable_mouse_highlight;
1886
1887 /* Take proper action when the mouse has moved to position X, Y on frame F
1888 as regards highlighting characters that have mouse-face properties.
1889 Also dehighlighting chars where the mouse was before.
1890 X and Y can be negative or out of range. */
1891
1892 static void
1893 note_mouse_highlight (f, x, y)
1894 FRAME_PTR f;
1895 int x, y;
1896 {
1897 int row, column, portion;
1898 XRectangle new_glyph;
1899 Lisp_Object window;
1900 struct window *w;
1901
1902 if (disable_mouse_highlight)
1903 return;
1904
1905 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
1906 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
1907 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
1908
1909 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer)
1910 return;
1911
1912 if (gc_in_progress)
1913 {
1914 FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1915 return;
1916 }
1917
1918 /* Find out which glyph the mouse is on. */
1919 pixel_to_glyph_coords (f, x, y, &column, &row,
1920 &new_glyph, FRAME_X_DISPLAY_INFO (f)->grabbed);
1921
1922 /* Which window is that in? */
1923 window = window_from_coordinates (f, column, row, &portion);
1924 w = XWINDOW (window);
1925
1926 /* If we were displaying active text in another window, clear that. */
1927 if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
1928 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
1929
1930 /* Are we in a window whose display is up to date?
1931 And verify the buffer's text has not changed. */
1932 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
1933 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
1934 && EQ (w->window_end_valid, w->buffer)
1935 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
1936 {
1937 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1938 int i, pos;
1939
1940 /* Find which buffer position the mouse corresponds to. */
1941 for (i = column; i >= 0; i--)
1942 if (ptr[i] > 0)
1943 break;
1944 pos = ptr[i];
1945 /* Is it outside the displayed active region (if any)? */
1946 if (pos <= 0)
1947 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
1948 else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)
1949 && row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
1950 && row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
1951 && (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
1952 || column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)
1953 && (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
1954 || column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
1955 || FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end)))
1956 {
1957 Lisp_Object mouse_face, overlay, position;
1958 Lisp_Object *overlay_vec;
1959 int len, noverlays, ignor1;
1960 struct buffer *obuf;
1961 int obegv, ozv;
1962
1963 /* If we get an out-of-range value, return now; avoid an error. */
1964 if (pos > BUF_Z (XBUFFER (w->buffer)))
1965 return;
1966
1967 /* Make the window's buffer temporarily current for
1968 overlays_at and compute_char_face. */
1969 obuf = current_buffer;
1970 current_buffer = XBUFFER (w->buffer);
1971 obegv = BEGV;
1972 ozv = ZV;
1973 BEGV = BEG;
1974 ZV = Z;
1975
1976 /* Yes. Clear the display of the old active region, if any. */
1977 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
1978
1979 /* Is this char mouse-active? */
1980 XSETINT (position, pos);
1981
1982 len = 10;
1983 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1984
1985 /* Put all the overlays we want in a vector in overlay_vec.
1986 Store the length in len. */
1987 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
1988 NULL, NULL);
1989 noverlays = sort_overlays (overlay_vec, noverlays, w);
1990
1991 /* Find the highest priority overlay that has a mouse-face prop. */
1992 overlay = Qnil;
1993 for (i = 0; i < noverlays; i++)
1994 {
1995 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1996 if (!NILP (mouse_face))
1997 {
1998 overlay = overlay_vec[i];
1999 break;
2000 }
2001 }
2002 free (overlay_vec);
2003 /* If no overlay applies, get a text property. */
2004 if (NILP (overlay))
2005 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
2006
2007 /* Handle the overlay case. */
2008 if (! NILP (overlay))
2009 {
2010 /* Find the range of text around this char that
2011 should be active. */
2012 Lisp_Object before, after;
2013 int ignore;
2014
2015 before = Foverlay_start (overlay);
2016 after = Foverlay_end (overlay);
2017 /* Record this as the current active region. */
2018 fast_find_position (window, before,
2019 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
2020 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
2021 FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
2022 = !fast_find_position (window, after,
2023 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
2024 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
2025 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
2026 FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
2027 = compute_char_face (f, w, pos, 0, 0,
2028 &ignore, pos + 1, 1);
2029
2030 /* Display it as active. */
2031 show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
2032 }
2033 /* Handle the text property case. */
2034 else if (! NILP (mouse_face))
2035 {
2036 /* Find the range of text around this char that
2037 should be active. */
2038 Lisp_Object before, after, beginning, end;
2039 int ignore;
2040
2041 beginning = Fmarker_position (w->start);
2042 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
2043 - XFASTINT (w->window_end_pos)));
2044 before
2045 = Fprevious_single_property_change (make_number (pos + 1),
2046 Qmouse_face,
2047 w->buffer, beginning);
2048 after
2049 = Fnext_single_property_change (position, Qmouse_face,
2050 w->buffer, end);
2051 /* Record this as the current active region. */
2052 fast_find_position (window, before,
2053 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
2054 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
2055 FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
2056 = !fast_find_position (window, after,
2057 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
2058 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
2059 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
2060 FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
2061 = compute_char_face (f, w, pos, 0, 0,
2062 &ignore, pos + 1, 1);
2063
2064 /* Display it as active. */
2065 show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
2066 }
2067 BEGV = obegv;
2068 ZV = ozv;
2069 current_buffer = obuf;
2070 }
2071 }
2072 }
2073 \f
2074 /* Find the row and column of position POS in window WINDOW.
2075 Store them in *COLUMNP and *ROWP.
2076 This assumes display in WINDOW is up to date.
2077 If POS is above start of WINDOW, return coords
2078 of start of first screen line.
2079 If POS is after end of WINDOW, return coords of end of last screen line.
2080
2081 Value is 1 if POS is in range, 0 if it was off screen. */
2082
2083 static int
2084 fast_find_position (window, pos, columnp, rowp)
2085 Lisp_Object window;
2086 int pos;
2087 int *columnp, *rowp;
2088 {
2089 struct window *w = XWINDOW (window);
2090 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2091 int i;
2092 int row = 0;
2093 int left = w->left;
2094 int top = w->top;
2095 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
2096 int width = window_internal_width (w);
2097 int *charstarts;
2098 int lastcol;
2099 int maybe_next_line = 0;
2100
2101 /* Find the right row. */
2102 for (i = 0;
2103 i < height;
2104 i++)
2105 {
2106 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
2107 if (linestart > pos)
2108 break;
2109 /* If the position sought is the end of the buffer,
2110 don't include the blank lines at the bottom of the window. */
2111 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
2112 {
2113 maybe_next_line = 1;
2114 break;
2115 }
2116 if (linestart > 0)
2117 row = i;
2118 }
2119
2120 /* Find the right column with in it. */
2121 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
2122 lastcol = left;
2123 for (i = 0; i < width; i++)
2124 {
2125 if (charstarts[left + i] == pos)
2126 {
2127 *rowp = row + top;
2128 *columnp = i + left;
2129 return 1;
2130 }
2131 else if (charstarts[left + i] > pos)
2132 break;
2133 else if (charstarts[left + i] > 0)
2134 lastcol = left + i;
2135 }
2136
2137 /* If we're looking for the end of the buffer,
2138 and we didn't find it in the line we scanned,
2139 use the start of the following line. */
2140 if (maybe_next_line)
2141 {
2142 row++;
2143 i = 0;
2144 }
2145
2146 *rowp = row + top;
2147 *columnp = lastcol;
2148 return 0;
2149 }
2150
2151 /* Display the active region described by mouse_face_*
2152 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2153
2154 static void
2155 show_mouse_face (dpyinfo, hl)
2156 struct x_display_info *dpyinfo;
2157 int hl;
2158 {
2159 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
2160 int width = window_internal_width (w);
2161 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2162 int i;
2163 int cursor_off = 0;
2164 int old_curs_x = curs_x;
2165 int old_curs_y = curs_y;
2166
2167 /* Set these variables temporarily
2168 so that if we have to turn the cursor off and on again
2169 we will put it back at the same place. */
2170 curs_x = f->phys_cursor_x;
2171 curs_y = f->phys_cursor_y;
2172
2173 for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row;
2174 i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++)
2175 {
2176 int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
2177 ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col
2178 : w->left);
2179 int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
2180 ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
2181 : w->left + width);
2182 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
2183
2184 /* If the cursor's in the text we are about to rewrite,
2185 turn the cursor off. */
2186 if (i == curs_y
2187 && curs_x >= column - 1
2188 && curs_x <= endcolumn)
2189 {
2190 x_display_cursor (f, 0);
2191 cursor_off = 1;
2192 }
2193
2194 dumpglyphs (f,
2195 CHAR_TO_PIXEL_COL (f, column),
2196 CHAR_TO_PIXEL_ROW (f, i),
2197 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
2198 endcolumn - column,
2199 /* Highlight with mouse face if hl > 0. */
2200 hl > 0 ? 3 : 0, 0);
2201 }
2202
2203 /* If we turned the cursor off, turn it back on. */
2204 if (cursor_off)
2205 x_display_cursor (f, 1);
2206
2207 curs_x = old_curs_x;
2208 curs_y = old_curs_y;
2209
2210 /* Change the mouse cursor according to the value of HL. */
2211 if (hl > 0)
2212 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2213 f->output_data.x->cross_cursor);
2214 else
2215 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2216 f->output_data.x->text_cursor);
2217 }
2218
2219 /* Clear out the mouse-highlighted active region.
2220 Redraw it unhighlighted first. */
2221
2222 static void
2223 clear_mouse_face (dpyinfo)
2224 struct x_display_info *dpyinfo;
2225 {
2226 if (! NILP (dpyinfo->mouse_face_window))
2227 show_mouse_face (dpyinfo, 0);
2228
2229 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2230 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2231 dpyinfo->mouse_face_window = Qnil;
2232 }
2233 \f
2234 static struct scroll_bar *x_window_to_scroll_bar ();
2235 static void x_scroll_bar_report_motion ();
2236
2237 /* Return the current position of the mouse.
2238 *fp should be a frame which indicates which display to ask about.
2239
2240 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2241 and *part to the frame, window, and scroll bar part that the mouse
2242 is over. Set *x and *y to the portion and whole of the mouse's
2243 position on the scroll bar.
2244
2245 If the mouse movement started elsewhere, set *fp to the frame the
2246 mouse is on, *bar_window to nil, and *x and *y to the character cell
2247 the mouse is over.
2248
2249 Set *time to the server timestamp for the time at which the mouse
2250 was at this position.
2251
2252 Don't store anything if we don't have a valid set of values to report.
2253
2254 This clears the mouse_moved flag, so we can wait for the next mouse
2255 movement. This also calls XQueryPointer, which will cause the
2256 server to give us another MotionNotify when the mouse moves
2257 again. */
2258
2259 static void
2260 XTmouse_position (fp, insist, bar_window, part, x, y, time)
2261 FRAME_PTR *fp;
2262 int insist;
2263 Lisp_Object *bar_window;
2264 enum scroll_bar_part *part;
2265 Lisp_Object *x, *y;
2266 unsigned long *time;
2267 {
2268 FRAME_PTR f1;
2269
2270 BLOCK_INPUT;
2271
2272 if (! NILP (last_mouse_scroll_bar))
2273 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
2274 else
2275 {
2276 Window root;
2277 int root_x, root_y;
2278
2279 Window dummy_window;
2280 int dummy;
2281
2282 Lisp_Object frame, tail;
2283
2284 /* Clear the mouse-moved flag for every frame on this display. */
2285 FOR_EACH_FRAME (tail, frame)
2286 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
2287 XFRAME (frame)->mouse_moved = 0;
2288
2289 last_mouse_scroll_bar = Qnil;
2290
2291 /* Figure out which root window we're on. */
2292 XQueryPointer (FRAME_X_DISPLAY (*fp),
2293 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
2294
2295 /* The root window which contains the pointer. */
2296 &root,
2297
2298 /* Trash which we can't trust if the pointer is on
2299 a different screen. */
2300 &dummy_window,
2301
2302 /* The position on that root window. */
2303 &root_x, &root_y,
2304
2305 /* More trash we can't trust. */
2306 &dummy, &dummy,
2307
2308 /* Modifier keys and pointer buttons, about which
2309 we don't care. */
2310 (unsigned int *) &dummy);
2311
2312 /* Now we have a position on the root; find the innermost window
2313 containing the pointer. */
2314 {
2315 Window win, child;
2316 int win_x, win_y;
2317 int parent_x, parent_y;
2318
2319 win = root;
2320
2321 /* XTranslateCoordinates can get errors if the window
2322 structure is changing at the same time this function
2323 is running. So at least we must not crash from them. */
2324
2325 x_catch_errors (FRAME_X_DISPLAY (*fp));
2326
2327 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
2328 && FRAME_LIVE_P (last_mouse_frame))
2329 {
2330 /* If mouse was grabbed on a frame, give coords for that frame
2331 even if the mouse is now outside it. */
2332 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
2333
2334 /* From-window, to-window. */
2335 root, FRAME_X_WINDOW (last_mouse_frame),
2336
2337 /* From-position, to-position. */
2338 root_x, root_y, &win_x, &win_y,
2339
2340 /* Child of win. */
2341 &child);
2342 f1 = last_mouse_frame;
2343 }
2344 else
2345 {
2346 while (1)
2347 {
2348 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
2349
2350 /* From-window, to-window. */
2351 root, win,
2352
2353 /* From-position, to-position. */
2354 root_x, root_y, &win_x, &win_y,
2355
2356 /* Child of win. */
2357 &child);
2358
2359 if (child == None || child == win)
2360 break;
2361
2362 win = child;
2363 parent_x = win_x;
2364 parent_y = win_y;
2365 }
2366
2367 /* Now we know that:
2368 win is the innermost window containing the pointer
2369 (XTC says it has no child containing the pointer),
2370 win_x and win_y are the pointer's position in it
2371 (XTC did this the last time through), and
2372 parent_x and parent_y are the pointer's position in win's parent.
2373 (They are what win_x and win_y were when win was child.
2374 If win is the root window, it has no parent, and
2375 parent_{x,y} are invalid, but that's okay, because we'll
2376 never use them in that case.) */
2377
2378 /* Is win one of our frames? */
2379 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
2380 }
2381
2382 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
2383 f1 = 0;
2384
2385 x_uncatch_errors (FRAME_X_DISPLAY (*fp));
2386
2387 /* If not, is it one of our scroll bars? */
2388 if (! f1)
2389 {
2390 struct scroll_bar *bar = x_window_to_scroll_bar (win);
2391
2392 if (bar)
2393 {
2394 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2395 win_x = parent_x;
2396 win_y = parent_y;
2397 }
2398 }
2399
2400 if (f1 == 0 && insist)
2401 f1 = selected_frame;
2402
2403 if (f1)
2404 {
2405 int ignore1, ignore2;
2406
2407 /* Ok, we found a frame. Store all the values. */
2408
2409 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
2410 &last_mouse_glyph,
2411 FRAME_X_DISPLAY_INFO (f1)->grabbed
2412 || insist);
2413
2414 *bar_window = Qnil;
2415 *part = 0;
2416 *fp = f1;
2417 XSETINT (*x, win_x);
2418 XSETINT (*y, win_y);
2419 *time = last_mouse_movement_time;
2420 }
2421 }
2422 }
2423
2424 UNBLOCK_INPUT;
2425 }
2426 \f
2427 /* Scroll bar support. */
2428
2429 /* Given an X window ID, find the struct scroll_bar which manages it.
2430 This can be called in GC, so we have to make sure to strip off mark
2431 bits. */
2432 static struct scroll_bar *
2433 x_window_to_scroll_bar (window_id)
2434 Window window_id;
2435 {
2436 Lisp_Object tail, frame;
2437
2438 for (tail = Vframe_list;
2439 XGCTYPE (tail) == Lisp_Cons;
2440 tail = XCONS (tail)->cdr)
2441 {
2442 Lisp_Object frame, bar, condemned;
2443
2444 frame = XCONS (tail)->car;
2445 /* All elements of Vframe_list should be frames. */
2446 if (! GC_FRAMEP (frame))
2447 abort ();
2448
2449 /* Scan this frame's scroll bar list for a scroll bar with the
2450 right window ID. */
2451 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
2452 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
2453 /* This trick allows us to search both the ordinary and
2454 condemned scroll bar lists with one loop. */
2455 ! GC_NILP (bar) || (bar = condemned,
2456 condemned = Qnil,
2457 ! GC_NILP (bar));
2458 bar = XSCROLL_BAR (bar)->next)
2459 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
2460 return XSCROLL_BAR (bar);
2461 }
2462
2463 return 0;
2464 }
2465
2466 /* Open a new X window to serve as a scroll bar, and return the
2467 scroll bar vector for it. */
2468 static struct scroll_bar *
2469 x_scroll_bar_create (window, top, left, width, height)
2470 struct window *window;
2471 int top, left, width, height;
2472 {
2473 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2474 struct scroll_bar *bar
2475 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
2476
2477 BLOCK_INPUT;
2478
2479 {
2480 XSetWindowAttributes a;
2481 unsigned long mask;
2482 a.background_pixel = f->output_data.x->background_pixel;
2483 a.event_mask = (ButtonPressMask | ButtonReleaseMask
2484 | ButtonMotionMask | PointerMotionHintMask
2485 | ExposureMask);
2486 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
2487
2488 mask = (CWBackPixel | CWEventMask | CWCursor);
2489
2490 #if 0
2491
2492 ac = 0;
2493 XtSetArg (al[ac], XtNx, left); ac++;
2494 XtSetArg (al[ac], XtNy, top); ac++;
2495 XtSetArg (al[ac], XtNwidth, width); ac++;
2496 XtSetArg (al[ac], XtNheight, height); ac++;
2497 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2498 sb_widget = XtCreateManagedWidget ("box",
2499 boxWidgetClass,
2500 f->output_data.x->edit_widget, al, ac);
2501 SET_SCROLL_BAR_X_WINDOW
2502 (bar, sb_widget->core.window);
2503 #endif
2504 SET_SCROLL_BAR_X_WINDOW
2505 (bar,
2506 XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2507
2508 /* Position and size of scroll bar. */
2509 left, top, width, height,
2510
2511 /* Border width, depth, class, and visual. */
2512 0, CopyFromParent, CopyFromParent, CopyFromParent,
2513
2514 /* Attributes. */
2515 mask, &a));
2516 }
2517
2518 XSETWINDOW (bar->window, window);
2519 XSETINT (bar->top, top);
2520 XSETINT (bar->left, left);
2521 XSETINT (bar->width, width);
2522 XSETINT (bar->height, height);
2523 XSETINT (bar->start, 0);
2524 XSETINT (bar->end, 0);
2525 bar->dragging = Qnil;
2526
2527 /* Add bar to its frame's list of scroll bars. */
2528 bar->next = FRAME_SCROLL_BARS (f);
2529 bar->prev = Qnil;
2530 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2531 if (! NILP (bar->next))
2532 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2533
2534 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
2535
2536 UNBLOCK_INPUT;
2537
2538 return bar;
2539 }
2540
2541 /* Draw BAR's handle in the proper position.
2542 If the handle is already drawn from START to END, don't bother
2543 redrawing it, unless REBUILD is non-zero; in that case, always
2544 redraw it. (REBUILD is handy for drawing the handle after expose
2545 events.)
2546
2547 Normally, we want to constrain the start and end of the handle to
2548 fit inside its rectangle, but if the user is dragging the scroll bar
2549 handle, we want to let them drag it down all the way, so that the
2550 bar's top is as far down as it goes; otherwise, there's no way to
2551 move to the very end of the buffer. */
2552 static void
2553 x_scroll_bar_set_handle (bar, start, end, rebuild)
2554 struct scroll_bar *bar;
2555 int start, end;
2556 int rebuild;
2557 {
2558 int dragging = ! NILP (bar->dragging);
2559 Window w = SCROLL_BAR_X_WINDOW (bar);
2560 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2561 GC gc = f->output_data.x->normal_gc;
2562
2563 /* If the display is already accurate, do nothing. */
2564 if (! rebuild
2565 && start == XINT (bar->start)
2566 && end == XINT (bar->end))
2567 return;
2568
2569 BLOCK_INPUT;
2570
2571 {
2572 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
2573 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2574 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2575
2576 /* Make sure the values are reasonable, and try to preserve
2577 the distance between start and end. */
2578 {
2579 int length = end - start;
2580
2581 if (start < 0)
2582 start = 0;
2583 else if (start > top_range)
2584 start = top_range;
2585 end = start + length;
2586
2587 if (end < start)
2588 end = start;
2589 else if (end > top_range && ! dragging)
2590 end = top_range;
2591 }
2592
2593 /* Store the adjusted setting in the scroll bar. */
2594 XSETINT (bar->start, start);
2595 XSETINT (bar->end, end);
2596
2597 /* Clip the end position, just for display. */
2598 if (end > top_range)
2599 end = top_range;
2600
2601 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2602 below top positions, to make sure the handle is always at least
2603 that many pixels tall. */
2604 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
2605
2606 /* Draw the empty space above the handle. Note that we can't clear
2607 zero-height areas; that means "clear to end of window." */
2608 if (0 < start)
2609 XClearArea (FRAME_X_DISPLAY (f), w,
2610
2611 /* x, y, width, height, and exposures. */
2612 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2613 VERTICAL_SCROLL_BAR_TOP_BORDER,
2614 inside_width, start,
2615 False);
2616
2617 /* Draw the handle itself. */
2618 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
2619
2620 /* x, y, width, height */
2621 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2622 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
2623 inside_width, end - start);
2624
2625
2626 /* Draw the empty space below the handle. Note that we can't
2627 clear zero-height areas; that means "clear to end of window." */
2628 if (end < inside_height)
2629 XClearArea (FRAME_X_DISPLAY (f), w,
2630
2631 /* x, y, width, height, and exposures. */
2632 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2633 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2634 inside_width, inside_height - end,
2635 False);
2636
2637 }
2638
2639 UNBLOCK_INPUT;
2640 }
2641
2642 /* Move a scroll bar around on the screen, to accommodate changing
2643 window configurations. */
2644 static void
2645 x_scroll_bar_move (bar, top, left, width, height)
2646 struct scroll_bar *bar;
2647 int top, left, width, height;
2648 {
2649 Window w = SCROLL_BAR_X_WINDOW (bar);
2650 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2651
2652 BLOCK_INPUT;
2653
2654 {
2655 XWindowChanges wc;
2656 unsigned int mask = 0;
2657
2658 wc.x = left;
2659 wc.y = top;
2660 wc.width = width;
2661 wc.height = height;
2662
2663 if (left != XINT (bar->left)) mask |= CWX;
2664 if (top != XINT (bar->top)) mask |= CWY;
2665 if (width != XINT (bar->width)) mask |= CWWidth;
2666 if (height != XINT (bar->height)) mask |= CWHeight;
2667
2668 if (mask)
2669 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
2670 mask, &wc);
2671 }
2672
2673 XSETINT (bar->left, left);
2674 XSETINT (bar->top, top);
2675 XSETINT (bar->width, width);
2676 XSETINT (bar->height, height);
2677
2678 UNBLOCK_INPUT;
2679 }
2680
2681 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2682 to nil. */
2683 static void
2684 x_scroll_bar_remove (bar)
2685 struct scroll_bar *bar;
2686 {
2687 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2688
2689 BLOCK_INPUT;
2690
2691 /* Destroy the window. */
2692 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
2693
2694 /* Disassociate this scroll bar from its window. */
2695 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2696
2697 UNBLOCK_INPUT;
2698 }
2699
2700 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2701 that we are displaying PORTION characters out of a total of WHOLE
2702 characters, starting at POSITION. If WINDOW has no scroll bar,
2703 create one. */
2704 static void
2705 XTset_vertical_scroll_bar (window, portion, whole, position)
2706 struct window *window;
2707 int portion, whole, position;
2708 {
2709 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2710 int top = XINT (window->top);
2711 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2712 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2713
2714 /* Where should this scroll bar be, pixelwise? */
2715 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2716 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2717 int pixel_width
2718 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2719 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2720 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2721 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2722
2723 struct scroll_bar *bar;
2724
2725 /* Does the scroll bar exist yet? */
2726 if (NILP (window->vertical_scroll_bar))
2727 bar = x_scroll_bar_create (window,
2728 pixel_top, pixel_left,
2729 pixel_width, pixel_height);
2730 else
2731 {
2732 /* It may just need to be moved and resized. */
2733 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2734 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2735 }
2736
2737 /* Set the scroll bar's current state, unless we're currently being
2738 dragged. */
2739 if (NILP (bar->dragging))
2740 {
2741 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2742
2743 if (whole == 0)
2744 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2745 else
2746 {
2747 int start = ((double) position * top_range) / whole;
2748 int end = ((double) (position + portion) * top_range) / whole;
2749
2750 x_scroll_bar_set_handle (bar, start, end, 0);
2751 }
2752 }
2753
2754 XSETVECTOR (window->vertical_scroll_bar, bar);
2755 }
2756
2757
2758 /* The following three hooks are used when we're doing a thorough
2759 redisplay of the frame. We don't explicitly know which scroll bars
2760 are going to be deleted, because keeping track of when windows go
2761 away is a real pain - "Can you say set-window-configuration, boys
2762 and girls?" Instead, we just assert at the beginning of redisplay
2763 that *all* scroll bars are to be removed, and then save a scroll bar
2764 from the fiery pit when we actually redisplay its window. */
2765
2766 /* Arrange for all scroll bars on FRAME to be removed at the next call
2767 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2768 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2769 static void
2770 XTcondemn_scroll_bars (frame)
2771 FRAME_PTR frame;
2772 {
2773 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2774 while (! NILP (FRAME_SCROLL_BARS (frame)))
2775 {
2776 Lisp_Object bar;
2777 bar = FRAME_SCROLL_BARS (frame);
2778 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
2779 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
2780 XSCROLL_BAR (bar)->prev = Qnil;
2781 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2782 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
2783 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
2784 }
2785 }
2786
2787 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2788 Note that WINDOW isn't necessarily condemned at all. */
2789 static void
2790 XTredeem_scroll_bar (window)
2791 struct window *window;
2792 {
2793 struct scroll_bar *bar;
2794
2795 /* We can't redeem this window's scroll bar if it doesn't have one. */
2796 if (NILP (window->vertical_scroll_bar))
2797 abort ();
2798
2799 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2800
2801 /* Unlink it from the condemned list. */
2802 {
2803 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2804
2805 if (NILP (bar->prev))
2806 {
2807 /* If the prev pointer is nil, it must be the first in one of
2808 the lists. */
2809 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2810 /* It's not condemned. Everything's fine. */
2811 return;
2812 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2813 window->vertical_scroll_bar))
2814 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2815 else
2816 /* If its prev pointer is nil, it must be at the front of
2817 one or the other! */
2818 abort ();
2819 }
2820 else
2821 XSCROLL_BAR (bar->prev)->next = bar->next;
2822
2823 if (! NILP (bar->next))
2824 XSCROLL_BAR (bar->next)->prev = bar->prev;
2825
2826 bar->next = FRAME_SCROLL_BARS (f);
2827 bar->prev = Qnil;
2828 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2829 if (! NILP (bar->next))
2830 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2831 }
2832 }
2833
2834 /* Remove all scroll bars on FRAME that haven't been saved since the
2835 last call to `*condemn_scroll_bars_hook'. */
2836 static void
2837 XTjudge_scroll_bars (f)
2838 FRAME_PTR f;
2839 {
2840 Lisp_Object bar, next;
2841
2842 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2843
2844 /* Clear out the condemned list now so we won't try to process any
2845 more events on the hapless scroll bars. */
2846 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2847
2848 for (; ! NILP (bar); bar = next)
2849 {
2850 struct scroll_bar *b = XSCROLL_BAR (bar);
2851
2852 x_scroll_bar_remove (b);
2853
2854 next = b->next;
2855 b->next = b->prev = Qnil;
2856 }
2857
2858 /* Now there should be no references to the condemned scroll bars,
2859 and they should get garbage-collected. */
2860 }
2861
2862
2863 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2864
2865 This may be called from a signal handler, so we have to ignore GC
2866 mark bits. */
2867 static void
2868 x_scroll_bar_expose (bar, event)
2869 struct scroll_bar *bar;
2870 XEvent *event;
2871 {
2872 Window w = SCROLL_BAR_X_WINDOW (bar);
2873 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2874 GC gc = f->output_data.x->normal_gc;
2875
2876 BLOCK_INPUT;
2877
2878 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2879
2880 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2881 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
2882
2883 /* x, y, width, height */
2884 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2885
2886 UNBLOCK_INPUT;
2887 }
2888
2889 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2890 is set to something other than no_event, it is enqueued.
2891
2892 This may be called from a signal handler, so we have to ignore GC
2893 mark bits. */
2894 static void
2895 x_scroll_bar_handle_click (bar, event, emacs_event)
2896 struct scroll_bar *bar;
2897 XEvent *event;
2898 struct input_event *emacs_event;
2899 {
2900 if (! GC_WINDOWP (bar->window))
2901 abort ();
2902
2903 emacs_event->kind = scroll_bar_click;
2904 emacs_event->code = event->xbutton.button - Button1;
2905 emacs_event->modifiers
2906 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2907 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
2908 event->xbutton.state)
2909 | (event->type == ButtonRelease
2910 ? up_modifier
2911 : down_modifier));
2912 emacs_event->frame_or_window = bar->window;
2913 emacs_event->timestamp = event->xbutton.time;
2914 {
2915 int internal_height
2916 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2917 int top_range
2918 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2919 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2920
2921 if (y < 0) y = 0;
2922 if (y > top_range) y = top_range;
2923
2924 if (y < XINT (bar->start))
2925 emacs_event->part = scroll_bar_above_handle;
2926 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2927 emacs_event->part = scroll_bar_handle;
2928 else
2929 emacs_event->part = scroll_bar_below_handle;
2930
2931 /* Just because the user has clicked on the handle doesn't mean
2932 they want to drag it. Lisp code needs to be able to decide
2933 whether or not we're dragging. */
2934 #if 0
2935 /* If the user has just clicked on the handle, record where they're
2936 holding it. */
2937 if (event->type == ButtonPress
2938 && emacs_event->part == scroll_bar_handle)
2939 XSETINT (bar->dragging, y - XINT (bar->start));
2940 #endif
2941
2942 /* If the user has released the handle, set it to its final position. */
2943 if (event->type == ButtonRelease
2944 && ! NILP (bar->dragging))
2945 {
2946 int new_start = y - XINT (bar->dragging);
2947 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2948
2949 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2950 bar->dragging = Qnil;
2951 }
2952
2953 /* Same deal here as the other #if 0. */
2954 #if 0
2955 /* Clicks on the handle are always reported as occurring at the top of
2956 the handle. */
2957 if (emacs_event->part == scroll_bar_handle)
2958 emacs_event->x = bar->start;
2959 else
2960 XSETINT (emacs_event->x, y);
2961 #else
2962 XSETINT (emacs_event->x, y);
2963 #endif
2964
2965 XSETINT (emacs_event->y, top_range);
2966 }
2967 }
2968
2969 /* Handle some mouse motion while someone is dragging the scroll bar.
2970
2971 This may be called from a signal handler, so we have to ignore GC
2972 mark bits. */
2973 static void
2974 x_scroll_bar_note_movement (bar, event)
2975 struct scroll_bar *bar;
2976 XEvent *event;
2977 {
2978 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
2979
2980 last_mouse_movement_time = event->xmotion.time;
2981
2982 f->mouse_moved = 1;
2983 XSETVECTOR (last_mouse_scroll_bar, bar);
2984
2985 /* If we're dragging the bar, display it. */
2986 if (! GC_NILP (bar->dragging))
2987 {
2988 /* Where should the handle be now? */
2989 int new_start = event->xmotion.y - XINT (bar->dragging);
2990
2991 if (new_start != XINT (bar->start))
2992 {
2993 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2994
2995 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2996 }
2997 }
2998
2999 /* Call XQueryPointer so we'll get an event the next time the mouse
3000 moves and we can see *still* on the same position. */
3001 {
3002 int dummy;
3003 Window dummy_window;
3004
3005 XQueryPointer (event->xmotion.display, event->xmotion.window,
3006 &dummy_window, &dummy_window,
3007 &dummy, &dummy, &dummy, &dummy,
3008 (unsigned int *) &dummy);
3009 }
3010 }
3011
3012 /* Return information to the user about the current position of the mouse
3013 on the scroll bar. */
3014 static void
3015 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3016 FRAME_PTR *fp;
3017 Lisp_Object *bar_window;
3018 enum scroll_bar_part *part;
3019 Lisp_Object *x, *y;
3020 unsigned long *time;
3021 {
3022 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3023 Window w = SCROLL_BAR_X_WINDOW (bar);
3024 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3025 int win_x, win_y;
3026 Window dummy_window;
3027 int dummy_coord;
3028 unsigned int dummy_mask;
3029
3030 BLOCK_INPUT;
3031
3032 /* Get the mouse's position relative to the scroll bar window, and
3033 report that. */
3034 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
3035
3036 /* Root, child, root x and root y. */
3037 &dummy_window, &dummy_window,
3038 &dummy_coord, &dummy_coord,
3039
3040 /* Position relative to scroll bar. */
3041 &win_x, &win_y,
3042
3043 /* Mouse buttons and modifier keys. */
3044 &dummy_mask))
3045 ;
3046 else
3047 {
3048 int inside_height
3049 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
3050 int top_range
3051 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
3052
3053 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
3054
3055 if (! NILP (bar->dragging))
3056 win_y -= XINT (bar->dragging);
3057
3058 if (win_y < 0)
3059 win_y = 0;
3060 if (win_y > top_range)
3061 win_y = top_range;
3062
3063 *fp = f;
3064 *bar_window = bar->window;
3065
3066 if (! NILP (bar->dragging))
3067 *part = scroll_bar_handle;
3068 else if (win_y < XINT (bar->start))
3069 *part = scroll_bar_above_handle;
3070 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
3071 *part = scroll_bar_handle;
3072 else
3073 *part = scroll_bar_below_handle;
3074
3075 XSETINT (*x, win_y);
3076 XSETINT (*y, top_range);
3077
3078 f->mouse_moved = 0;
3079 last_mouse_scroll_bar = Qnil;
3080 }
3081
3082 *time = last_mouse_movement_time;
3083
3084 UNBLOCK_INPUT;
3085 }
3086
3087
3088 /* The screen has been cleared so we may have changed foreground or
3089 background colors, and the scroll bars may need to be redrawn.
3090 Clear out the scroll bars, and ask for expose events, so we can
3091 redraw them. */
3092
3093 x_scroll_bar_clear (f)
3094 FRAME_PTR f;
3095 {
3096 Lisp_Object bar;
3097
3098 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
3099 bar = XSCROLL_BAR (bar)->next)
3100 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
3101 0, 0, 0, 0, True);
3102 }
3103
3104 /* This processes Expose events from the menubar specific X event
3105 loop in xmenu.c. This allows to redisplay the frame if necessary
3106 when handling menubar or popup items. */
3107
3108 void
3109 process_expose_from_menu (event)
3110 XEvent event;
3111 {
3112 FRAME_PTR f;
3113 struct x_display_info *dpyinfo;
3114
3115 BLOCK_INPUT;
3116
3117 dpyinfo = x_display_info_for_display (event.xexpose.display);
3118 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3119 if (f)
3120 {
3121 if (f->async_visible == 0)
3122 {
3123 f->async_visible = 1;
3124 f->async_iconified = 0;
3125 SET_FRAME_GARBAGED (f);
3126 }
3127 else
3128 {
3129 dumprectangle (x_window_to_frame (dpyinfo, event.xexpose.window),
3130 event.xexpose.x, event.xexpose.y,
3131 event.xexpose.width, event.xexpose.height);
3132 }
3133 }
3134 else
3135 {
3136 struct scroll_bar *bar
3137 = x_window_to_scroll_bar (event.xexpose.window);
3138
3139 if (bar)
3140 x_scroll_bar_expose (bar, &event);
3141 }
3142
3143 UNBLOCK_INPUT;
3144 }
3145 \f
3146 /* Define a queue to save up SelectionRequest events for later handling. */
3147
3148 struct selection_event_queue
3149 {
3150 XEvent event;
3151 struct selection_event_queue *next;
3152 };
3153
3154 static struct selection_event_queue *queue;
3155
3156 /* Nonzero means queue up certain events--don't process them yet. */
3157 static int x_queue_selection_requests;
3158
3159 /* Queue up an X event *EVENT, to be processed later. */
3160
3161 static void
3162 x_queue_event (f, event)
3163 FRAME_PTR f;
3164 XEvent *event;
3165 {
3166 struct selection_event_queue *queue_tmp
3167 = (struct selection_event_queue *) malloc (sizeof (struct selection_event_queue));
3168
3169 if (queue_tmp != NULL)
3170 {
3171 queue_tmp->event = *event;
3172 queue_tmp->next = queue;
3173 queue = queue_tmp;
3174 }
3175 }
3176
3177 /* Take all the queued events and put them back
3178 so that they get processed afresh. */
3179
3180 static void
3181 x_unqueue_events (display)
3182 Display *display;
3183 {
3184 while (queue != NULL)
3185 {
3186 struct selection_event_queue *queue_tmp = queue;
3187 XPutBackEvent (display, &queue_tmp->event);
3188 queue = queue_tmp->next;
3189 free ((char *)queue_tmp);
3190 }
3191 }
3192
3193 /* Start queuing SelectionRequest events. */
3194
3195 void
3196 x_start_queuing_selection_requests (display)
3197 Display *display;
3198 {
3199 x_queue_selection_requests++;
3200 }
3201
3202 /* Stop queuing SelectionRequest events. */
3203
3204 void
3205 x_stop_queuing_selection_requests (display)
3206 Display *display;
3207 {
3208 x_queue_selection_requests--;
3209 x_unqueue_events (display);
3210 }
3211 \f
3212 /* The main X event-reading loop - XTread_socket. */
3213
3214 /* Timestamp of enter window event. This is only used by XTread_socket,
3215 but we have to put it out here, since static variables within functions
3216 sometimes don't work. */
3217 static Time enter_timestamp;
3218
3219 /* This holds the state XLookupString needs to implement dead keys
3220 and other tricks known as "compose processing". _X Window System_
3221 says that a portable program can't use this, but Stephen Gildea assures
3222 me that letting the compiler initialize it to zeros will work okay.
3223
3224 This must be defined outside of XTread_socket, for the same reasons
3225 given for enter_timestamp, above. */
3226 static XComposeStatus compose_status;
3227
3228 /* Record the last 100 characters stored
3229 to help debug the loss-of-chars-during-GC problem. */
3230 static int temp_index;
3231 static short temp_buffer[100];
3232
3233 /* Set this to nonzero to fake an "X I/O error"
3234 on a particular display. */
3235 struct x_display_info *XTread_socket_fake_io_error;
3236
3237 /* When we find no input here, we occasionally do a no-op command
3238 to verify that the X server is still running and we can still talk with it.
3239 We try all the open displays, one by one.
3240 This variable is used for cycling thru the displays. */
3241 static struct x_display_info *next_noop_dpyinfo;
3242
3243 /* Read events coming from the X server.
3244 This routine is called by the SIGIO handler.
3245 We return as soon as there are no more events to be read.
3246
3247 Events representing keys are stored in buffer BUFP,
3248 which can hold up to NUMCHARS characters.
3249 We return the number of characters stored into the buffer,
3250 thus pretending to be `read'.
3251
3252 WAITP is nonzero if we should block until input arrives.
3253 EXPECTED is nonzero if the caller knows input is available. */
3254
3255 int
3256 XTread_socket (sd, bufp, numchars, waitp, expected)
3257 register int sd;
3258 register struct input_event *bufp;
3259 register int numchars;
3260 int waitp;
3261 int expected;
3262 {
3263 int count = 0;
3264 int nbytes = 0;
3265 int mask;
3266 int items_pending; /* How many items are in the X queue. */
3267 XEvent event;
3268 struct frame *f;
3269 int event_found = 0;
3270 int prefix;
3271 Lisp_Object part;
3272 struct x_display_info *dpyinfo;
3273 #ifdef HAVE_X_I18N
3274 Status status_return;
3275 #endif
3276
3277 if (interrupt_input_blocked)
3278 {
3279 interrupt_input_pending = 1;
3280 return -1;
3281 }
3282
3283 interrupt_input_pending = 0;
3284 BLOCK_INPUT;
3285
3286 /* So people can tell when we have read the available input. */
3287 input_signal_count++;
3288
3289 if (numchars <= 0)
3290 abort (); /* Don't think this happens. */
3291
3292 /* Find the display we are supposed to read input for.
3293 It's the one communicating on descriptor SD. */
3294 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
3295 {
3296 #if 0 /* This ought to be unnecessary; let's verify it. */
3297 #ifdef FIOSNBIO
3298 /* If available, Xlib uses FIOSNBIO to make the socket
3299 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3300 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3301 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3302 fcntl (dpyinfo->connection, F_SETFL, 0);
3303 #endif /* ! defined (FIOSNBIO) */
3304 #endif
3305
3306 #if 0 /* This code can't be made to work, with multiple displays,
3307 and appears not to be used on any system any more.
3308 Also keyboard.c doesn't turn O_NDELAY on and off
3309 for X connections. */
3310 #ifndef SIGIO
3311 #ifndef HAVE_SELECT
3312 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
3313 {
3314 extern int read_alarm_should_throw;
3315 read_alarm_should_throw = 1;
3316 XPeekEvent (dpyinfo->display, &event);
3317 read_alarm_should_throw = 0;
3318 }
3319 #endif /* HAVE_SELECT */
3320 #endif /* SIGIO */
3321 #endif
3322
3323 /* For debugging, this gives a way to fake an I/O error. */
3324 if (dpyinfo == XTread_socket_fake_io_error)
3325 {
3326 XTread_socket_fake_io_error = 0;
3327 x_io_error_quitter (dpyinfo->display);
3328 }
3329
3330 while (XPending (dpyinfo->display) != 0)
3331 {
3332 XNextEvent (dpyinfo->display, &event);
3333 event_found = 1;
3334
3335 switch (event.type)
3336 {
3337 case ClientMessage:
3338 {
3339 if (event.xclient.message_type
3340 == dpyinfo->Xatom_wm_protocols
3341 && event.xclient.format == 32)
3342 {
3343 if (event.xclient.data.l[0]
3344 == dpyinfo->Xatom_wm_take_focus)
3345 {
3346 f = x_window_to_frame (dpyinfo, event.xclient.window);
3347 /* Since we set WM_TAKE_FOCUS, we must call
3348 XSetInputFocus explicitly. But not if f is null,
3349 since that might be an event for a deleted frame. */
3350 #ifdef HAVE_X_I18N
3351 /* Not quite sure this is needed -pd */
3352 if (f)
3353 XSetICFocus (FRAME_XIC (f));
3354 #endif
3355 if (f)
3356 XSetInputFocus (event.xclient.display,
3357 event.xclient.window,
3358 RevertToPointerRoot,
3359 event.xclient.data.l[1]);
3360 /* Not certain about handling scroll bars here */
3361 }
3362 else if (event.xclient.data.l[0]
3363 == dpyinfo->Xatom_wm_save_yourself)
3364 {
3365 /* Save state modify the WM_COMMAND property to
3366 something which can reinstate us. This notifies
3367 the session manager, who's looking for such a
3368 PropertyNotify. Can restart processing when
3369 a keyboard or mouse event arrives. */
3370 if (numchars > 0)
3371 {
3372 f = x_top_window_to_frame (dpyinfo,
3373 event.xclient.window);
3374
3375 /* This is just so we only give real data once
3376 for a single Emacs process. */
3377 if (f == selected_frame)
3378 XSetCommand (FRAME_X_DISPLAY (f),
3379 event.xclient.window,
3380 initial_argv, initial_argc);
3381 else
3382 XSetCommand (FRAME_X_DISPLAY (f),
3383 event.xclient.window,
3384 0, 0);
3385 }
3386 }
3387 else if (event.xclient.data.l[0]
3388 == dpyinfo->Xatom_wm_delete_window)
3389 {
3390 struct frame *f
3391 = x_any_window_to_frame (dpyinfo,
3392 event.xclient.window);
3393
3394 if (f)
3395 {
3396 if (numchars == 0)
3397 abort ();
3398
3399 bufp->kind = delete_window_event;
3400 XSETFRAME (bufp->frame_or_window, f);
3401 bufp++;
3402
3403 count += 1;
3404 numchars -= 1;
3405 }
3406 }
3407 }
3408 else if (event.xclient.message_type
3409 == dpyinfo->Xatom_wm_configure_denied)
3410 {
3411 }
3412 else if (event.xclient.message_type
3413 == dpyinfo->Xatom_wm_window_moved)
3414 {
3415 int new_x, new_y;
3416 struct frame *f
3417 = x_window_to_frame (dpyinfo, event.xclient.window);
3418
3419 new_x = event.xclient.data.s[0];
3420 new_y = event.xclient.data.s[1];
3421
3422 if (f)
3423 {
3424 f->output_data.x->left_pos = new_x;
3425 f->output_data.x->top_pos = new_y;
3426 }
3427 }
3428 #ifdef HACK_EDITRES
3429 else if (event.xclient.message_type
3430 == dpyinfo->Xatom_editres)
3431 {
3432 struct frame *f
3433 = x_any_window_to_frame (dpyinfo, event.xclient.window);
3434 _XEditResCheckMessages (f->output_data.x->widget, NULL,
3435 &event, NULL);
3436 }
3437 #endif /* HACK_EDITRES */
3438 }
3439 break;
3440
3441 case SelectionNotify:
3442 #ifdef USE_X_TOOLKIT
3443 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
3444 goto OTHER;
3445 #endif /* not USE_X_TOOLKIT */
3446 x_handle_selection_notify (&event);
3447 break;
3448
3449 case SelectionClear: /* Someone has grabbed ownership. */
3450 #ifdef USE_X_TOOLKIT
3451 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
3452 goto OTHER;
3453 #endif /* USE_X_TOOLKIT */
3454 {
3455 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
3456
3457 if (numchars == 0)
3458 abort ();
3459
3460 bufp->kind = selection_clear_event;
3461 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3462 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3463 SELECTION_EVENT_TIME (bufp) = eventp->time;
3464 bufp->frame_or_window = Qnil;
3465 bufp++;
3466
3467 count += 1;
3468 numchars -= 1;
3469 }
3470 break;
3471
3472 case SelectionRequest: /* Someone wants our selection. */
3473 #ifdef USE_X_TOOLKIT
3474 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
3475 goto OTHER;
3476 #endif /* USE_X_TOOLKIT */
3477 if (x_queue_selection_requests)
3478 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
3479 &event);
3480 else
3481 {
3482 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
3483
3484 if (numchars == 0)
3485 abort ();
3486
3487 bufp->kind = selection_request_event;
3488 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3489 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
3490 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3491 SELECTION_EVENT_TARGET (bufp) = eventp->target;
3492 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
3493 SELECTION_EVENT_TIME (bufp) = eventp->time;
3494 bufp->frame_or_window = Qnil;
3495 bufp++;
3496
3497 count += 1;
3498 numchars -= 1;
3499 }
3500 break;
3501
3502 case PropertyNotify:
3503 #ifdef USE_X_TOOLKIT
3504 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
3505 goto OTHER;
3506 #endif /* not USE_X_TOOLKIT */
3507 x_handle_property_notify (&event);
3508 break;
3509
3510 case ReparentNotify:
3511 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
3512 if (f)
3513 {
3514 int x, y;
3515 f->output_data.x->parent_desc = event.xreparent.parent;
3516 x_real_positions (f, &x, &y);
3517 f->output_data.x->left_pos = x;
3518 f->output_data.x->top_pos = y;
3519 }
3520 break;
3521
3522 case Expose:
3523 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3524 if (f)
3525 {
3526 if (f->async_visible == 0)
3527 {
3528 f->async_visible = 1;
3529 f->async_iconified = 0;
3530 SET_FRAME_GARBAGED (f);
3531 }
3532 else
3533 dumprectangle (x_window_to_frame (dpyinfo,
3534 event.xexpose.window),
3535 event.xexpose.x, event.xexpose.y,
3536 event.xexpose.width, event.xexpose.height);
3537 }
3538 else
3539 {
3540 struct scroll_bar *bar
3541 = x_window_to_scroll_bar (event.xexpose.window);
3542
3543 if (bar)
3544 x_scroll_bar_expose (bar, &event);
3545 #ifdef USE_X_TOOLKIT
3546 else
3547 goto OTHER;
3548 #endif /* USE_X_TOOLKIT */
3549 }
3550 break;
3551
3552 case GraphicsExpose: /* This occurs when an XCopyArea's
3553 source area was obscured or not
3554 available.*/
3555 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
3556 if (f)
3557 {
3558 dumprectangle (f,
3559 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
3560 event.xgraphicsexpose.width,
3561 event.xgraphicsexpose.height);
3562 }
3563 #ifdef USE_X_TOOLKIT
3564 else
3565 goto OTHER;
3566 #endif /* USE_X_TOOLKIT */
3567 break;
3568
3569 case NoExpose: /* This occurs when an XCopyArea's
3570 source area was completely
3571 available */
3572 break;
3573
3574 case UnmapNotify:
3575 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
3576 if (f) /* F may no longer exist if
3577 the frame was deleted. */
3578 {
3579 /* While a frame is unmapped, display generation is
3580 disabled; you don't want to spend time updating a
3581 display that won't ever be seen. */
3582 f->async_visible = 0;
3583 /* We can't distinguish, from the event, whether the window
3584 has become iconified or invisible. So assume, if it
3585 was previously visible, than now it is iconified.
3586 We depend on x_make_frame_invisible to mark it iconified. */
3587 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
3588 f->async_iconified = 1;
3589
3590 bufp->kind = iconify_event;
3591 XSETFRAME (bufp->frame_or_window, f);
3592 bufp++;
3593 count++;
3594 numchars--;
3595 }
3596 goto OTHER;
3597
3598 case MapNotify:
3599 /* We use x_top_window_to_frame because map events can come
3600 for subwindows and they don't mean that the frame is visible. */
3601 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
3602 if (f)
3603 {
3604 f->async_visible = 1;
3605 f->async_iconified = 0;
3606
3607 /* wait_reading_process_input will notice this and update
3608 the frame's display structures. */
3609 SET_FRAME_GARBAGED (f);
3610
3611 if (f->iconified)
3612 {
3613 bufp->kind = deiconify_event;
3614 XSETFRAME (bufp->frame_or_window, f);
3615 bufp++;
3616 count++;
3617 numchars--;
3618 }
3619 else
3620 /* Force a redisplay sooner or later
3621 to update the frame titles
3622 in case this is the second frame. */
3623 record_asynch_buffer_change ();
3624 }
3625 goto OTHER;
3626
3627 /* Turn off processing if we become fully obscured. */
3628 case VisibilityNotify:
3629 break;
3630
3631 case KeyPress:
3632 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
3633
3634 if (f != 0)
3635 {
3636 KeySym keysym, orig_keysym;
3637 /* al%imercury@uunet.uu.net says that making this 81 instead of
3638 80 fixed a bug whereby meta chars made his Emacs hang. */
3639 unsigned char copy_buffer[81];
3640 int modifiers;
3641
3642 event.xkey.state
3643 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
3644 extra_keyboard_modifiers);
3645 modifiers = event.xkey.state;
3646
3647 /* This will have to go some day... */
3648
3649 /* make_lispy_event turns chars into control chars.
3650 Don't do it here because XLookupString is too eager. */
3651 event.xkey.state &= ~ControlMask;
3652 event.xkey.state &= ~(dpyinfo->meta_mod_mask
3653 | dpyinfo->super_mod_mask
3654 | dpyinfo->hyper_mod_mask
3655 | dpyinfo->alt_mod_mask);
3656
3657 #ifdef HAVE_X_I18N
3658 if (FRAME_XIC (f))
3659 {
3660 /* The necessity of the following line took me
3661 a full work-day to decipher from the docs!! */
3662 if (XFilterEvent (&event, None))
3663 break;
3664 nbytes = XmbLookupString (FRAME_XIC (f),
3665 &event.xkey, copy_buffer,
3666 80, &keysym,
3667 &status_return);
3668 }
3669 else
3670 nbytes = XLookupString (&event.xkey, copy_buffer,
3671 80, &keysym, &compose_status);
3672 #else
3673 nbytes = XLookupString (&event.xkey, copy_buffer,
3674 80, &keysym, &compose_status);
3675 #endif
3676
3677 orig_keysym = keysym;
3678
3679 if (numchars > 1)
3680 {
3681 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
3682 || keysym == XK_Delete
3683 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
3684 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
3685 #ifdef HPUX
3686 /* This recognizes the "extended function keys".
3687 It seems there's no cleaner way.
3688 Test IsModifierKey to avoid handling mode_switch
3689 incorrectly. */
3690 || ((unsigned) (keysym) >= XK_Select
3691 && (unsigned)(keysym) < XK_KP_Space)
3692 #endif
3693 #ifdef XK_dead_circumflex
3694 || orig_keysym == XK_dead_circumflex
3695 #endif
3696 #ifdef XK_dead_grave
3697 || orig_keysym == XK_dead_grave
3698 #endif
3699 #ifdef XK_dead_tilde
3700 || orig_keysym == XK_dead_tilde
3701 #endif
3702 #ifdef XK_dead_diaeresis
3703 || orig_keysym == XK_dead_diaeresis
3704 #endif
3705 #ifdef XK_dead_macron
3706 || orig_keysym == XK_dead_macron
3707 #endif
3708 #ifdef XK_dead_degree
3709 || orig_keysym == XK_dead_degree
3710 #endif
3711 #ifdef XK_dead_acute
3712 || orig_keysym == XK_dead_acute
3713 #endif
3714 #ifdef XK_dead_cedilla
3715 || orig_keysym == XK_dead_cedilla
3716 #endif
3717 #ifdef XK_dead_breve
3718 || orig_keysym == XK_dead_breve
3719 #endif
3720 #ifdef XK_dead_ogonek
3721 || orig_keysym == XK_dead_ogonek
3722 #endif
3723 #ifdef XK_dead_caron
3724 || orig_keysym == XK_dead_caron
3725 #endif
3726 #ifdef XK_dead_doubleacute
3727 || orig_keysym == XK_dead_doubleacute
3728 #endif
3729 #ifdef XK_dead_abovedot
3730 || orig_keysym == XK_dead_abovedot
3731 #endif
3732 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
3733 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
3734 /* Any "vendor-specific" key is ok. */
3735 || (orig_keysym & (1 << 28)))
3736 && ! (IsModifierKey (orig_keysym)
3737 #ifndef HAVE_X11R5
3738 #ifdef XK_Mode_switch
3739 || ((unsigned)(orig_keysym) == XK_Mode_switch)
3740 #endif
3741 #ifdef XK_Num_Lock
3742 || ((unsigned)(orig_keysym) == XK_Num_Lock)
3743 #endif
3744 #endif /* not HAVE_X11R5 */
3745 ))
3746 {
3747 if (temp_index == sizeof temp_buffer / sizeof (short))
3748 temp_index = 0;
3749 temp_buffer[temp_index++] = keysym;
3750 bufp->kind = non_ascii_keystroke;
3751 bufp->code = keysym;
3752 XSETFRAME (bufp->frame_or_window, f);
3753 bufp->modifiers
3754 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3755 modifiers);
3756 bufp->timestamp = event.xkey.time;
3757 bufp++;
3758 count++;
3759 numchars--;
3760 }
3761 else if (numchars > nbytes)
3762 {
3763 register int i;
3764
3765 for (i = 0; i < nbytes; i++)
3766 {
3767 if (temp_index == sizeof temp_buffer / sizeof (short))
3768 temp_index = 0;
3769 temp_buffer[temp_index++] = copy_buffer[i];
3770 bufp->kind = ascii_keystroke;
3771 bufp->code = copy_buffer[i];
3772 XSETFRAME (bufp->frame_or_window, f);
3773 bufp->modifiers
3774 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3775 modifiers);
3776 bufp->timestamp = event.xkey.time;
3777 bufp++;
3778 }
3779
3780 count += nbytes;
3781 numchars -= nbytes;
3782 }
3783 else
3784 abort ();
3785 }
3786 else
3787 abort ();
3788 }
3789 goto OTHER;
3790
3791 /* Here's a possible interpretation of the whole
3792 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3793 FocusIn event, you have to get a FocusOut event before you
3794 relinquish the focus. If you haven't received a FocusIn event,
3795 then a mere LeaveNotify is enough to free you. */
3796
3797 case EnterNotify:
3798 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
3799
3800 if (event.xcrossing.focus) /* Entered Window */
3801 {
3802 /* Avoid nasty pop/raise loops. */
3803 if (f && (!(f->auto_raise)
3804 || !(f->auto_lower)
3805 || (event.xcrossing.time - enter_timestamp) > 500))
3806 {
3807 x_new_focus_frame (dpyinfo, f);
3808 enter_timestamp = event.xcrossing.time;
3809 }
3810 }
3811 else if (f == dpyinfo->x_focus_frame)
3812 x_new_focus_frame (dpyinfo, 0);
3813 /* EnterNotify counts as mouse movement,
3814 so update things that depend on mouse position. */
3815 if (f)
3816 note_mouse_movement (f, &event.xmotion);
3817 goto OTHER;
3818
3819 case FocusIn:
3820 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
3821 if (event.xfocus.detail != NotifyPointer)
3822 dpyinfo->x_focus_event_frame = f;
3823 if (f)
3824 x_new_focus_frame (dpyinfo, f);
3825
3826 #ifdef HAVE_X_I18N
3827 if (f && FRAME_XIC (f))
3828 XSetICFocus (FRAME_XIC (f));
3829 #endif
3830
3831 goto OTHER;
3832
3833 case LeaveNotify:
3834 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
3835 if (f)
3836 {
3837 if (f == dpyinfo->mouse_face_mouse_frame)
3838 /* If we move outside the frame,
3839 then we're certainly no longer on any text in the frame. */
3840 clear_mouse_face (dpyinfo);
3841
3842 if (event.xcrossing.focus)
3843 x_mouse_leave (dpyinfo);
3844 else
3845 {
3846 if (f == dpyinfo->x_focus_event_frame)
3847 dpyinfo->x_focus_event_frame = 0;
3848 if (f == dpyinfo->x_focus_frame)
3849 x_new_focus_frame (dpyinfo, 0);
3850 }
3851 }
3852 goto OTHER;
3853
3854 case FocusOut:
3855 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
3856 if (event.xfocus.detail != NotifyPointer
3857 && f == dpyinfo->x_focus_event_frame)
3858 dpyinfo->x_focus_event_frame = 0;
3859 if (f && f == dpyinfo->x_focus_frame)
3860 x_new_focus_frame (dpyinfo, 0);
3861
3862 #ifdef HAVE_X_I18N
3863 if (f && FRAME_XIC (f))
3864 XUnsetICFocus (FRAME_XIC (f));
3865 #endif
3866
3867 goto OTHER;
3868
3869 case MotionNotify:
3870 {
3871 if (dpyinfo->grabbed && last_mouse_frame
3872 && FRAME_LIVE_P (last_mouse_frame))
3873 f = last_mouse_frame;
3874 else
3875 f = x_window_to_frame (dpyinfo, event.xmotion.window);
3876 if (f)
3877 note_mouse_movement (f, &event.xmotion);
3878 else
3879 {
3880 struct scroll_bar *bar
3881 = x_window_to_scroll_bar (event.xmotion.window);
3882
3883 if (bar)
3884 x_scroll_bar_note_movement (bar, &event);
3885
3886 /* If we move outside the frame,
3887 then we're certainly no longer on any text in the frame. */
3888 clear_mouse_face (dpyinfo);
3889 }
3890 }
3891 goto OTHER;
3892
3893 case ConfigureNotify:
3894 f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
3895 if (f
3896 #ifdef USE_X_TOOLKIT
3897 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
3898 #endif
3899 )
3900 {
3901 #ifndef USE_X_TOOLKIT
3902 /* In the toolkit version, change_frame_size
3903 is called by the code that handles resizing
3904 of the EmacsFrame widget. */
3905
3906 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3907 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3908
3909 /* Even if the number of character rows and columns has
3910 not changed, the font size may have changed, so we need
3911 to check the pixel dimensions as well. */
3912 if (columns != f->width
3913 || rows != f->height
3914 || event.xconfigure.width != f->output_data.x->pixel_width
3915 || event.xconfigure.height != f->output_data.x->pixel_height)
3916 {
3917 change_frame_size (f, rows, columns, 0, 1);
3918 SET_FRAME_GARBAGED (f);
3919 }
3920 #endif
3921
3922 /* Formerly, in the USE_X_TOOLKIT version,
3923 we did not test send_event here. */
3924 if (1
3925 #ifndef USE_X_TOOLKIT
3926 && ! event.xconfigure.send_event
3927 #endif
3928 )
3929 {
3930 Window win, child;
3931 int win_x, win_y;
3932
3933 /* Find the position of the outside upper-left corner of
3934 the window, in the root coordinate system. Don't
3935 refer to the parent window here; we may be processing
3936 this event after the window manager has changed our
3937 parent, but before we have reached the ReparentNotify. */
3938 XTranslateCoordinates (FRAME_X_DISPLAY (f),
3939
3940 /* From-window, to-window. */
3941 event.xconfigure.window,
3942 FRAME_X_DISPLAY_INFO (f)->root_window,
3943
3944 /* From-position, to-position. */
3945 -event.xconfigure.border_width,
3946 -event.xconfigure.border_width,
3947 &win_x, &win_y,
3948
3949 /* Child of win. */
3950 &child);
3951 event.xconfigure.x = win_x;
3952 event.xconfigure.y = win_y;
3953 }
3954
3955 f->output_data.x->pixel_width = event.xconfigure.width;
3956 f->output_data.x->pixel_height = event.xconfigure.height;
3957 f->output_data.x->left_pos = event.xconfigure.x;
3958 f->output_data.x->top_pos = event.xconfigure.y;
3959
3960 /* What we have now is the position of Emacs's own window.
3961 Convert that to the position of the window manager window. */
3962 {
3963 int x, y;
3964 x_real_positions (f, &x, &y);
3965 f->output_data.x->left_pos = x;
3966 f->output_data.x->top_pos = y;
3967 /* Formerly we did not do this in the USE_X_TOOLKIT
3968 version. Let's try making them the same. */
3969 /* #ifndef USE_X_TOOLKIT */
3970 if (y != event.xconfigure.y)
3971 {
3972 /* Since the WM decorations come below top_pos now,
3973 we must put them below top_pos in the future. */
3974 f->output_data.x->win_gravity = NorthWestGravity;
3975 x_wm_set_size_hint (f, (long) 0, 0);
3976 }
3977 /* #endif */
3978 }
3979 }
3980 goto OTHER;
3981
3982 case ButtonPress:
3983 case ButtonRelease:
3984 {
3985 /* If we decide we want to generate an event to be seen
3986 by the rest of Emacs, we put it here. */
3987 struct input_event emacs_event;
3988 emacs_event.kind = no_event;
3989
3990 bzero (&compose_status, sizeof (compose_status));
3991
3992 if (dpyinfo->grabbed && last_mouse_frame
3993 && FRAME_LIVE_P (last_mouse_frame))
3994 f = last_mouse_frame;
3995 else
3996 f = x_window_to_frame (dpyinfo, event.xbutton.window);
3997
3998 if (f)
3999 {
4000 if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
4001 construct_mouse_click (&emacs_event, &event, f);
4002 }
4003 else
4004 {
4005 struct scroll_bar *bar
4006 = x_window_to_scroll_bar (event.xbutton.window);
4007
4008 if (bar)
4009 x_scroll_bar_handle_click (bar, &event, &emacs_event);
4010 }
4011
4012 if (event.type == ButtonPress)
4013 {
4014 dpyinfo->grabbed |= (1 << event.xbutton.button);
4015 last_mouse_frame = f;
4016 }
4017 else
4018 {
4019 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
4020 }
4021
4022 if (numchars >= 1 && emacs_event.kind != no_event)
4023 {
4024 bcopy (&emacs_event, bufp, sizeof (struct input_event));
4025 bufp++;
4026 count++;
4027 numchars--;
4028 }
4029
4030 #ifdef USE_X_TOOLKIT
4031 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
4032 /* For a down-event in the menu bar,
4033 don't pass it to Xt right now.
4034 Instead, save it away
4035 and we will pass it to Xt from kbd_buffer_get_event.
4036 That way, we can run some Lisp code first. */
4037 if (f && event.type == ButtonPress
4038 /* Verify the event is really within the menu bar
4039 and not just sent to it due to grabbing. */
4040 && event.xbutton.x >= 0
4041 && event.xbutton.x < f->output_data.x->pixel_width
4042 && event.xbutton.y >= 0
4043 && event.xbutton.y < f->output_data.x->menubar_height
4044 && event.xbutton.same_screen)
4045 {
4046 if (f->output_data.x->saved_button_event == 0)
4047 f->output_data.x->saved_button_event
4048 = (XButtonEvent *) xmalloc (sizeof (XButtonEvent));
4049 bcopy (&event, f->output_data.x->saved_button_event,
4050 sizeof (XButtonEvent));
4051 if (numchars >= 1)
4052 {
4053 bufp->kind = menu_bar_activate_event;
4054 XSETFRAME (bufp->frame_or_window, f);
4055 bufp++;
4056 count++;
4057 numchars--;
4058 }
4059 }
4060 else
4061 goto OTHER;
4062 #endif /* USE_X_TOOLKIT */
4063 }
4064 break;
4065
4066 case CirculateNotify:
4067 break;
4068 case CirculateRequest:
4069 break;
4070
4071 case MappingNotify:
4072 /* Someone has changed the keyboard mapping - update the
4073 local cache. */
4074 switch (event.xmapping.request)
4075 {
4076 case MappingModifier:
4077 x_find_modifier_meanings (dpyinfo);
4078 /* This is meant to fall through. */
4079 case MappingKeyboard:
4080 XRefreshKeyboardMapping (&event.xmapping);
4081 }
4082 goto OTHER;
4083
4084 default:
4085 OTHER:
4086 #ifdef USE_X_TOOLKIT
4087 BLOCK_INPUT;
4088 XtDispatchEvent (&event);
4089 UNBLOCK_INPUT;
4090 #endif /* USE_X_TOOLKIT */
4091 break;
4092 }
4093 }
4094 }
4095
4096 /* On some systems, an X bug causes Emacs to get no more events
4097 when the window is destroyed. Detect that. (1994.) */
4098 if (! event_found)
4099 {
4100 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4101 One XNOOP in 100 loops will make Emacs terminate.
4102 B. Bretthauer, 1994 */
4103 x_noop_count++;
4104 if (x_noop_count >= 100)
4105 {
4106 x_noop_count=0;
4107
4108 if (next_noop_dpyinfo == 0)
4109 next_noop_dpyinfo = x_display_list;
4110
4111 XNoOp (next_noop_dpyinfo->display);
4112
4113 /* Each time we get here, cycle through the displays now open. */
4114 next_noop_dpyinfo = next_noop_dpyinfo->next;
4115 }
4116 }
4117
4118 /* If the focus was just given to an autoraising frame,
4119 raise it now. */
4120 /* ??? This ought to be able to handle more than one such frame. */
4121 if (pending_autoraise_frame)
4122 {
4123 x_raise_frame (pending_autoraise_frame);
4124 pending_autoraise_frame = 0;
4125 }
4126
4127 UNBLOCK_INPUT;
4128 return count;
4129 }
4130 \f
4131 /* Drawing the cursor. */
4132
4133
4134 /* Draw a hollow box cursor on frame F at X, Y.
4135 Don't change the inside of the box. */
4136
4137 static void
4138 x_draw_box (f, x, y)
4139 struct frame *f;
4140 int x, y;
4141 {
4142 int left = CHAR_TO_PIXEL_COL (f, x);
4143 int top = CHAR_TO_PIXEL_ROW (f, y);
4144 int width = FONT_WIDTH (f->output_data.x->font);
4145 int height = f->output_data.x->line_height;
4146
4147 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4148 f->output_data.x->cursor_gc,
4149 left, top, width - 1, height - 1);
4150 }
4151
4152 /* Clear the cursor of frame F to background color,
4153 and mark the cursor as not shown.
4154 This is used when the text where the cursor is
4155 is about to be rewritten. */
4156
4157 static void
4158 clear_cursor (f)
4159 struct frame *f;
4160 {
4161 int mask;
4162
4163 if (! FRAME_VISIBLE_P (f)
4164 || f->phys_cursor_x < 0)
4165 return;
4166
4167 x_display_cursor (f, 0);
4168 f->phys_cursor_x = -1;
4169 }
4170
4171 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4172 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4173 glyph drawn. */
4174
4175 static void
4176 x_draw_single_glyph (f, row, column, glyph, highlight)
4177 struct frame *f;
4178 int row, column;
4179 GLYPH glyph;
4180 int highlight;
4181 {
4182 dumpglyphs (f,
4183 CHAR_TO_PIXEL_COL (f, column),
4184 CHAR_TO_PIXEL_ROW (f, row),
4185 &glyph, 1, highlight, 0);
4186 }
4187
4188 static void
4189 x_display_bar_cursor (f, on, x, y)
4190 struct frame *f;
4191 int on;
4192 int x, y;
4193 {
4194 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4195
4196 /* This is pointless on invisible frames, and dangerous on garbaged
4197 frames; in the latter case, the frame may be in the midst of
4198 changing its size, and x and y may be off the frame. */
4199 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4200 return;
4201
4202 if (! on && f->phys_cursor_x < 0)
4203 return;
4204
4205 /* If there is anything wrong with the current cursor state, remove it. */
4206 if (f->phys_cursor_x >= 0
4207 && (!on
4208 || f->phys_cursor_x != x
4209 || f->phys_cursor_y != y
4210 || f->output_data.x->current_cursor != bar_cursor))
4211 {
4212 /* Erase the cursor by redrawing the character underneath it. */
4213 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4214 f->phys_cursor_glyph,
4215 current_glyphs->highlight[f->phys_cursor_y]);
4216 f->phys_cursor_x = -1;
4217 }
4218
4219 /* If we now need a cursor in the new place or in the new form, do it so. */
4220 if (on
4221 && (f->phys_cursor_x < 0
4222 || (f->output_data.x->current_cursor != bar_cursor)))
4223 {
4224 f->phys_cursor_glyph
4225 = ((current_glyphs->enable[y]
4226 && x < current_glyphs->used[y])
4227 ? current_glyphs->glyphs[y][x]
4228 : SPACEGLYPH);
4229 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4230 f->output_data.x->cursor_gc,
4231 CHAR_TO_PIXEL_COL (f, x),
4232 CHAR_TO_PIXEL_ROW (f, y),
4233 max (f->output_data.x->cursor_width, 1),
4234 f->output_data.x->line_height);
4235
4236 f->phys_cursor_x = x;
4237 f->phys_cursor_y = y;
4238
4239 f->output_data.x->current_cursor = bar_cursor;
4240 }
4241
4242 if (updating_frame != f)
4243 XFlush (FRAME_X_DISPLAY (f));
4244 }
4245
4246
4247 /* Turn the displayed cursor of frame F on or off according to ON.
4248 If ON is nonzero, where to put the cursor is specified by X and Y. */
4249
4250 static void
4251 x_display_box_cursor (f, on, x, y)
4252 struct frame *f;
4253 int on;
4254 int x, y;
4255 {
4256 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4257
4258 /* This is pointless on invisible frames, and dangerous on garbaged
4259 frames; in the latter case, the frame may be in the midst of
4260 changing its size, and x and y may be off the frame. */
4261 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4262 return;
4263
4264 /* If cursor is off and we want it off, return quickly. */
4265 if (!on && f->phys_cursor_x < 0)
4266 return;
4267
4268 /* If cursor is currently being shown and we don't want it to be
4269 or it is in the wrong place,
4270 or we want a hollow box and it's not so, (pout!)
4271 erase it. */
4272 if (f->phys_cursor_x >= 0
4273 && (!on
4274 || f->phys_cursor_x != x
4275 || f->phys_cursor_y != y
4276 || (f->output_data.x->current_cursor != hollow_box_cursor
4277 && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
4278 {
4279 int mouse_face_here = 0;
4280 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
4281
4282 /* If the cursor is in the mouse face area, redisplay that when
4283 we clear the cursor. */
4284 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame
4285 &&
4286 (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4287 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4288 && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col))
4289 &&
4290 (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4291 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4292 && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))
4293 /* Don't redraw the cursor's spot in mouse face
4294 if it is at the end of a line (on a newline).
4295 The cursor appears there, but mouse highlighting does not. */
4296 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
4297 mouse_face_here = 1;
4298
4299 /* If the font is not as tall as a whole line,
4300 we must explicitly clear the line's whole height. */
4301 if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
4302 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4303 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4304 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4305 FONT_WIDTH (f->output_data.x->font),
4306 f->output_data.x->line_height, False);
4307 /* Erase the cursor by redrawing the character underneath it. */
4308 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4309 f->phys_cursor_glyph,
4310 (mouse_face_here
4311 ? 3
4312 : current_glyphs->highlight[f->phys_cursor_y]));
4313 f->phys_cursor_x = -1;
4314 }
4315
4316 /* If we want to show a cursor,
4317 or we want a box cursor and it's not so,
4318 write it in the right place. */
4319 if (on
4320 && (f->phys_cursor_x < 0
4321 || (f->output_data.x->current_cursor != filled_box_cursor
4322 && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
4323 {
4324 f->phys_cursor_glyph
4325 = ((current_glyphs->enable[y]
4326 && x < current_glyphs->used[y])
4327 ? current_glyphs->glyphs[y][x]
4328 : SPACEGLYPH);
4329 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
4330 {
4331 x_draw_box (f, x, y);
4332 f->output_data.x->current_cursor = hollow_box_cursor;
4333 }
4334 else
4335 {
4336 x_draw_single_glyph (f, y, x,
4337 f->phys_cursor_glyph, 2);
4338 f->output_data.x->current_cursor = filled_box_cursor;
4339 }
4340
4341 f->phys_cursor_x = x;
4342 f->phys_cursor_y = y;
4343 }
4344
4345 if (updating_frame != f)
4346 XFlush (FRAME_X_DISPLAY (f));
4347 }
4348
4349 /* Display the cursor on frame F, or clear it, according to ON.
4350 Use the position specified by curs_x and curs_y
4351 if we are doing an update of frame F now.
4352 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4353 of F. */
4354
4355 x_display_cursor (f, on)
4356 struct frame *f;
4357 int on;
4358 {
4359 BLOCK_INPUT;
4360
4361 /* If we're not updating, then don't change the physical cursor
4362 position. Just change (if appropriate) the style of display. */
4363 if (f != updating_frame)
4364 {
4365 curs_x = FRAME_CURSOR_X (f);
4366 curs_y = FRAME_CURSOR_Y (f);
4367 }
4368
4369 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4370 x_display_box_cursor (f, on, curs_x, curs_y);
4371 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4372 x_display_bar_cursor (f, on, curs_x, curs_y);
4373 else
4374 /* Those are the only two we have implemented! */
4375 abort ();
4376
4377 UNBLOCK_INPUT;
4378 }
4379
4380 /* Display the cursor on frame F, or clear it, according to ON.
4381 Don't change the cursor's position. */
4382
4383 x_update_cursor (f, on)
4384 struct frame *f;
4385 int on;
4386 {
4387 BLOCK_INPUT;
4388
4389 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4390 x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
4391 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4392 x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
4393 else
4394 /* Those are the only two we have implemented! */
4395 abort ();
4396
4397 UNBLOCK_INPUT;
4398 }
4399 \f
4400 /* Icons. */
4401
4402 /* Refresh bitmap kitchen sink icon for frame F
4403 when we get an expose event for it. */
4404
4405 refreshicon (f)
4406 struct frame *f;
4407 {
4408 /* Normally, the window manager handles this function. */
4409 }
4410
4411 /* Make the x-window of frame F use the gnu icon bitmap. */
4412
4413 int
4414 x_bitmap_icon (f, file)
4415 struct frame *f;
4416 Lisp_Object file;
4417 {
4418 int mask, bitmap_id;
4419 Window icon_window;
4420
4421 if (FRAME_X_WINDOW (f) == 0)
4422 return 1;
4423
4424 /* Free up our existing icon bitmap if any. */
4425 if (f->output_data.x->icon_bitmap > 0)
4426 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4427 f->output_data.x->icon_bitmap = 0;
4428
4429 if (STRINGP (file))
4430 bitmap_id = x_create_bitmap_from_file (f, file);
4431 else
4432 {
4433 /* Create the GNU bitmap if necessary. */
4434 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
4435 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
4436 = x_create_bitmap_from_data (f, gnu_bits,
4437 gnu_width, gnu_height);
4438
4439 /* The first time we create the GNU bitmap,
4440 this increments the refcount one extra time.
4441 As a result, the GNU bitmap is never freed.
4442 That way, we don't have to worry about allocating it again. */
4443 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
4444
4445 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
4446 }
4447
4448 x_wm_set_icon_pixmap (f, bitmap_id);
4449 f->output_data.x->icon_bitmap = bitmap_id;
4450
4451 return 0;
4452 }
4453
4454
4455 /* Make the x-window of frame F use a rectangle with text.
4456 Use ICON_NAME as the text. */
4457
4458 int
4459 x_text_icon (f, icon_name)
4460 struct frame *f;
4461 char *icon_name;
4462 {
4463 if (FRAME_X_WINDOW (f) == 0)
4464 return 1;
4465
4466 #ifdef HAVE_X11R4
4467 {
4468 XTextProperty text;
4469 text.value = (unsigned char *) icon_name;
4470 text.encoding = XA_STRING;
4471 text.format = 8;
4472 text.nitems = strlen (icon_name);
4473 #ifdef USE_X_TOOLKIT
4474 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4475 &text);
4476 #else /* not USE_X_TOOLKIT */
4477 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
4478 #endif /* not USE_X_TOOLKIT */
4479 }
4480 #else /* not HAVE_X11R4 */
4481 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
4482 #endif /* not HAVE_X11R4 */
4483
4484 if (f->output_data.x->icon_bitmap > 0)
4485 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4486 f->output_data.x->icon_bitmap = 0;
4487 x_wm_set_icon_pixmap (f, 0);
4488
4489 return 0;
4490 }
4491 \f
4492 /* Handling X errors. */
4493
4494 /* Handle the loss of connection to display DISPLAY. */
4495
4496 static SIGTYPE
4497 x_connection_closed (display, error_message)
4498 Display *display;
4499 char *error_message;
4500 {
4501 struct x_display_info *dpyinfo = x_display_info_for_display (display);
4502 Lisp_Object frame, tail;
4503
4504 /* Whatever we were in the middle of, we are going to throw out of it,
4505 so reassure various things that have error checks about being
4506 called with input blocked. */
4507 TOTALLY_UNBLOCK_INPUT;
4508
4509 if (_Xdebug)
4510 abort ();
4511
4512 /* First delete frames whose minibuffers are on frames
4513 that are on the dead display. */
4514 FOR_EACH_FRAME (tail, frame)
4515 {
4516 Lisp_Object minibuf_frame;
4517 minibuf_frame
4518 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
4519 if (FRAME_X_P (XFRAME (frame))
4520 && FRAME_X_P (XFRAME (minibuf_frame))
4521 && ! EQ (frame, minibuf_frame)
4522 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
4523 Fdelete_frame (frame, Qt);
4524 }
4525
4526 /* Now delete all remaining frames on the dead display.
4527 We are now sure none of these is used as the minibuffer
4528 for another frame that we need to delete. */
4529 FOR_EACH_FRAME (tail, frame)
4530 if (FRAME_X_P (XFRAME (frame))
4531 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
4532 {
4533 /* Set this to t so that Fdelete_frame won't get confused
4534 trying to find a replacement. */
4535 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
4536 Fdelete_frame (frame, Qt);
4537 }
4538
4539 if (dpyinfo)
4540 x_delete_display (dpyinfo);
4541
4542 if (x_display_list == 0)
4543 {
4544 fprintf (stderr, "%s", error_message);
4545 shut_down_emacs (0, 0, Qnil);
4546 exit (70);
4547 }
4548
4549 /* Ordinary stack unwind doesn't deal with these. */
4550 #ifdef SIGIO
4551 sigunblock (sigmask (SIGIO));
4552 #endif
4553 sigunblock (sigmask (SIGALRM));
4554 TOTALLY_UNBLOCK_INPUT;
4555
4556 error ("%s", error_message);
4557 }
4558
4559 /* This is the usual handler for X protocol errors.
4560 It kills all frames on the display that we got the error for.
4561 If that was the only one, it prints an error message and kills Emacs. */
4562
4563 static int
4564 x_error_quitter (display, error)
4565 Display *display;
4566 XErrorEvent *error;
4567 {
4568 char buf[256], buf1[356];
4569
4570 /* Note that there is no real way portable across R3/R4 to get the
4571 original error handler. */
4572
4573 XGetErrorText (display, error->error_code, buf, sizeof (buf));
4574 sprintf (buf1, "X protocol error: %s on protocol request %d",
4575 buf, error->request_code);
4576 x_connection_closed (display, buf1);
4577 }
4578
4579 /* This is the handler for X IO errors, always.
4580 It kills all frames on the display that we lost touch with.
4581 If that was the only one, it prints an error message and kills Emacs. */
4582
4583 static int
4584 x_io_error_quitter (display)
4585 Display *display;
4586 {
4587 char buf[256];
4588
4589 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
4590 x_connection_closed (display, buf);
4591 }
4592 \f
4593 /* Handle SIGPIPE, which can happen when the connection to a server
4594 simply goes away. SIGPIPE is handled by x_connection_signal.
4595 It works by sending a no-op command to each X server connection.
4596 When we try a connection that has closed, we get SIGPIPE again.
4597 But this time, it is handled by x_connection_signal_1.
4598 That function knows which connection we were testing,
4599 so it closes that one.
4600
4601 x_connection_closed never returns,
4602 so if more than one connection was lost at once,
4603 we only find one. But XTread_socket keeps trying them all,
4604 so it will notice the other closed one sooner or later. */
4605
4606
4607 static struct x_display_info *x_connection_signal_dpyinfo;
4608
4609 static SIGTYPE x_connection_signal ();
4610
4611 static SIGTYPE
4612 x_connection_signal_1 (signalnum) /* If we don't have an argument, */
4613 int signalnum; /* some compilers complain in signal calls. */
4614 {
4615 signal (SIGPIPE, x_connection_signal);
4616 x_connection_closed (x_connection_signal_dpyinfo,
4617 "connection was lost");
4618 }
4619
4620 static SIGTYPE
4621 x_connection_signal (signalnum) /* If we don't have an argument, */
4622 int signalnum; /* some compilers complain in signal calls. */
4623 {
4624 x_connection_signal_dpyinfo = x_display_list;
4625
4626 stop_polling ();
4627 sigunblock (SIGPIPE);
4628
4629 while (x_connection_signal_dpyinfo)
4630 {
4631 signal (SIGPIPE, x_connection_signal_1);
4632 signal (SIGALRM, x_connection_signal_1);
4633
4634 /* According to Jim Campbell <jec@murzim.ca.boeing.com>,
4635 On Solaris 2.4, XNoOp can hang when the connection
4636 has already died. Since XNoOp should not wait,
4637 let's assume that if it hangs for 3 seconds
4638 that means the connection is dead.
4639 This is a kludge, but I don't see any other way that works. */
4640 alarm (3);
4641 XNoOp (x_connection_signal_dpyinfo->display);
4642 alarm (0);
4643
4644 XSync (x_connection_signal_dpyinfo->display, False);
4645
4646 /* Each time we get here, cycle through the displays now open. */
4647 x_connection_signal_dpyinfo = x_connection_signal_dpyinfo->next;
4648 }
4649
4650 /* We should have found some closed connection. */
4651 abort ();
4652 }
4653 \f
4654 /* A buffer for storing X error messages. */
4655 static char *x_caught_error_message;
4656 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4657
4658 /* An X error handler which stores the error message in
4659 x_caught_error_message. This is what's installed when
4660 x_catch_errors is in effect. */
4661
4662 static int
4663 x_error_catcher (display, error)
4664 Display *display;
4665 XErrorEvent *error;
4666 {
4667 XGetErrorText (display, error->error_code,
4668 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
4669 }
4670
4671
4672 /* Begin trapping X errors for display DPY. Actually we trap X errors
4673 for all displays, but DPY should be the display you are actually
4674 operating on.
4675
4676 After calling this function, X protocol errors no longer cause
4677 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4678
4679 Calling x_check_errors signals an Emacs error if an X error has
4680 occurred since the last call to x_catch_errors or x_check_errors.
4681
4682 Calling x_uncatch_errors resumes the normal error handling. */
4683
4684 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4685
4686 void
4687 x_catch_errors (dpy)
4688 Display *dpy;
4689 {
4690 /* Make sure any errors from previous requests have been dealt with. */
4691 XSync (dpy, False);
4692
4693 /* Set up the error buffer. */
4694 x_caught_error_message
4695 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
4696 x_caught_error_message[0] = '\0';
4697
4698 /* Install our little error handler. */
4699 XSetErrorHandler (x_error_catcher);
4700 }
4701
4702 /* If any X protocol errors have arrived since the last call to
4703 x_catch_errors or x_check_errors, signal an Emacs error using
4704 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4705
4706 void
4707 x_check_errors (dpy, format)
4708 Display *dpy;
4709 char *format;
4710 {
4711 /* Make sure to catch any errors incurred so far. */
4712 XSync (dpy, False);
4713
4714 if (x_caught_error_message[0])
4715 {
4716 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
4717
4718 sprintf (buf, format, x_caught_error_message);
4719 x_uncatch_errors (dpy);
4720 error (buf);
4721 }
4722 }
4723
4724 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4725
4726 int
4727 x_had_errors_p (dpy)
4728 Display *dpy;
4729 {
4730 /* Make sure to catch any errors incurred so far. */
4731 XSync (dpy, False);
4732
4733 return x_caught_error_message[0] != 0;
4734 }
4735
4736 /* Stop catching X protocol errors and let them make Emacs die. */
4737
4738 void
4739 x_uncatch_errors (dpy)
4740 Display *dpy;
4741 {
4742 xfree (x_caught_error_message);
4743 x_caught_error_message = 0;
4744 XSetErrorHandler (x_error_quitter);
4745 }
4746
4747 #if 0
4748 static unsigned int x_wire_count;
4749 x_trace_wire ()
4750 {
4751 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
4752 }
4753 #endif /* ! 0 */
4754
4755 \f
4756 /* Changing the font of the frame. */
4757
4758 /* Give frame F the font named FONTNAME as its default font, and
4759 return the full name of that font. FONTNAME may be a wildcard
4760 pattern; in that case, we choose some font that fits the pattern.
4761 The return value shows which font we chose. */
4762
4763 Lisp_Object
4764 x_new_font (f, fontname)
4765 struct frame *f;
4766 register char *fontname;
4767 {
4768 int already_loaded;
4769 int n_matching_fonts;
4770 XFontStruct *font_info;
4771 char **font_names;
4772
4773 /* Get a list of all the fonts that match this name. Once we
4774 have a list of matching fonts, we compare them against the fonts
4775 we already have by comparing font ids. */
4776 font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname,
4777 1024, &n_matching_fonts);
4778 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4779 find any matches; font_names == 0 is the only clue. */
4780 if (! font_names)
4781 n_matching_fonts = 0;
4782
4783 /* Don't just give up if n_matching_fonts is 0.
4784 Apparently there's a bug on Suns: XListFontsWithInfo can
4785 fail to find a font, but XLoadQueryFont may still find it. */
4786
4787 /* See if we've already loaded a matching font. */
4788 already_loaded = -1;
4789 if (n_matching_fonts != 0)
4790 {
4791 int i, j;
4792
4793 for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++)
4794 for (j = 0; j < n_matching_fonts; j++)
4795 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j])
4796 || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j]))
4797 {
4798 already_loaded = i;
4799 fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name;
4800 goto found_font;
4801 }
4802 }
4803 found_font:
4804
4805 /* If we have, just return it from the table. */
4806 if (already_loaded >= 0)
4807 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
4808 /* Otherwise, load the font and add it to the table. */
4809 else
4810 {
4811 int i;
4812 char *full_name;
4813 XFontStruct *font;
4814 int n_fonts;
4815
4816 /* Try to find a character-cell font in the list. */
4817 #if 0
4818 /* A laudable goal, but this isn't how to do it. */
4819 for (i = 0; i < n_matching_fonts; i++)
4820 if (! font_info[i].per_char)
4821 break;
4822 #else
4823 i = 0;
4824 #endif
4825
4826 /* See comment above. */
4827 if (n_matching_fonts != 0)
4828 fontname = font_names[i];
4829
4830 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
4831 if (! font)
4832 {
4833 /* Free the information from XListFonts. */
4834 if (n_matching_fonts)
4835 XFreeFontNames (font_names);
4836 return Qnil;
4837 }
4838
4839 /* Do we need to create the table? */
4840 if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0)
4841 {
4842 FRAME_X_DISPLAY_INFO (f)->font_table_size = 16;
4843 FRAME_X_DISPLAY_INFO (f)->font_table
4844 = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size
4845 * sizeof (struct font_info));
4846 }
4847 /* Do we need to grow the table? */
4848 else if (FRAME_X_DISPLAY_INFO (f)->n_fonts
4849 >= FRAME_X_DISPLAY_INFO (f)->font_table_size)
4850 {
4851 FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2;
4852 FRAME_X_DISPLAY_INFO (f)->font_table
4853 = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table,
4854 (FRAME_X_DISPLAY_INFO (f)->font_table_size
4855 * sizeof (struct font_info)));
4856 }
4857
4858 /* Try to get the full name of FONT. Put it in full_name. */
4859 full_name = 0;
4860 for (i = 0; i < font->n_properties; i++)
4861 {
4862 char *atom
4863 = XGetAtomName (FRAME_X_DISPLAY (f), font->properties[i].name);
4864 if (!strcmp (atom, "FONT"))
4865 {
4866 char *name = XGetAtomName (FRAME_X_DISPLAY (f),
4867 (Atom) (font->properties[i].card32));
4868 char *p = name;
4869 int dashes = 0;
4870
4871 /* Count the number of dashes in the "full name".
4872 If it is too few, this isn't really the font's full name,
4873 so don't use it.
4874 In X11R4, the fonts did not come with their canonical names
4875 stored in them. */
4876 while (*p)
4877 {
4878 if (*p == '-')
4879 dashes++;
4880 p++;
4881 }
4882
4883 if (dashes >= 13)
4884 full_name = name;
4885
4886 break;
4887 }
4888
4889 XFree (atom);
4890 }
4891
4892 n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts;
4893 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
4894 bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
4895 if (full_name != 0)
4896 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name;
4897 else
4898 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name;
4899 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
4900 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
4901
4902 if (full_name)
4903 fontname = full_name;
4904 }
4905
4906 /* Compute the scroll bar width in character columns. */
4907 if (f->scroll_bar_pixel_width > 0)
4908 {
4909 int wid = FONT_WIDTH (f->output_data.x->font);
4910 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
4911 }
4912 else
4913 f->scroll_bar_cols = 2;
4914
4915 /* Now make the frame display the given font. */
4916 if (FRAME_X_WINDOW (f) != 0)
4917 {
4918 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
4919 f->output_data.x->font->fid);
4920 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
4921 f->output_data.x->font->fid);
4922 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
4923 f->output_data.x->font->fid);
4924
4925 frame_update_line_height (f);
4926 x_set_window_size (f, 0, f->width, f->height);
4927 }
4928 else
4929 /* If we are setting a new frame's font for the first time,
4930 there are no faces yet, so this font's height is the line height. */
4931 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
4932
4933 {
4934 Lisp_Object lispy_name;
4935
4936 lispy_name = build_string (fontname);
4937
4938 /* Free the information from XListFonts. The data
4939 we actually retain comes from XLoadQueryFont. */
4940 XFreeFontNames (font_names);
4941
4942 return lispy_name;
4943 }
4944 }
4945 \f
4946 x_calc_absolute_position (f)
4947 struct frame *f;
4948 {
4949 Window win, child;
4950 int win_x = 0, win_y = 0;
4951 int flags = f->output_data.x->size_hint_flags;
4952 int this_window;
4953
4954 #ifdef USE_X_TOOLKIT
4955 this_window = XtWindow (f->output_data.x->widget);
4956 #else
4957 this_window = FRAME_X_WINDOW (f);
4958 #endif
4959
4960 /* Find the position of the outside upper-left corner of
4961 the inner window, with respect to the outer window. */
4962 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
4963 {
4964 BLOCK_INPUT;
4965 XTranslateCoordinates (FRAME_X_DISPLAY (f),
4966
4967 /* From-window, to-window. */
4968 this_window,
4969 f->output_data.x->parent_desc,
4970
4971 /* From-position, to-position. */
4972 0, 0, &win_x, &win_y,
4973
4974 /* Child of win. */
4975 &child);
4976 UNBLOCK_INPUT;
4977 }
4978
4979 /* Treat negative positions as relative to the leftmost bottommost
4980 position that fits on the screen. */
4981 if (flags & XNegative)
4982 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
4983 - 2 * f->output_data.x->border_width - win_x
4984 - PIXEL_WIDTH (f)
4985 + f->output_data.x->left_pos);
4986
4987 if (flags & YNegative)
4988 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
4989 - 2 * f->output_data.x->border_width - win_y
4990 - PIXEL_HEIGHT (f)
4991 - (FRAME_EXTERNAL_MENU_BAR (f)
4992 ? f->output_data.x->menubar_height : 0)
4993 + f->output_data.x->top_pos);
4994 /* The left_pos and top_pos
4995 are now relative to the top and left screen edges,
4996 so the flags should correspond. */
4997 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
4998 }
4999
5000 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5001 to really change the position, and 0 when calling from
5002 x_make_frame_visible (in that case, XOFF and YOFF are the current
5003 position values). It is -1 when calling from x_set_frame_parameters,
5004 which means, do adjust for borders but don't change the gravity. */
5005
5006 x_set_offset (f, xoff, yoff, change_gravity)
5007 struct frame *f;
5008 register int xoff, yoff;
5009 int change_gravity;
5010 {
5011 int modified_top, modified_left;
5012
5013 if (change_gravity > 0)
5014 {
5015 f->output_data.x->top_pos = yoff;
5016 f->output_data.x->left_pos = xoff;
5017 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
5018 if (xoff < 0)
5019 f->output_data.x->size_hint_flags |= XNegative;
5020 if (yoff < 0)
5021 f->output_data.x->size_hint_flags |= YNegative;
5022 f->output_data.x->win_gravity = NorthWestGravity;
5023 }
5024 x_calc_absolute_position (f);
5025
5026 BLOCK_INPUT;
5027 x_wm_set_size_hint (f, (long) 0, 0);
5028
5029 /* It is a mystery why we need to add the border_width here
5030 when the frame is already visible, but experiment says we do. */
5031 modified_left = f->output_data.x->left_pos;
5032 modified_top = f->output_data.x->top_pos;
5033 if (change_gravity != 0)
5034 {
5035 modified_left += f->output_data.x->border_width;
5036 modified_top += f->output_data.x->border_width;
5037 }
5038
5039 #ifdef USE_X_TOOLKIT
5040 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
5041 modified_left, modified_top);
5042 #else /* not USE_X_TOOLKIT */
5043 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5044 modified_left, modified_top);
5045 #endif /* not USE_X_TOOLKIT */
5046 UNBLOCK_INPUT;
5047 }
5048
5049 /* Call this to change the size of frame F's x-window.
5050 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5051 for this size change and subsequent size changes.
5052 Otherwise we leave the window gravity unchanged. */
5053
5054 x_set_window_size (f, change_gravity, cols, rows)
5055 struct frame *f;
5056 int change_gravity;
5057 int cols, rows;
5058 {
5059 int pixelwidth, pixelheight;
5060 int mask;
5061
5062 #ifdef USE_X_TOOLKIT
5063 BLOCK_INPUT;
5064 {
5065 /* The x and y position of the widget is clobbered by the
5066 call to XtSetValues within EmacsFrameSetCharSize.
5067 This is a real kludge, but I don't understand Xt so I can't
5068 figure out a correct fix. Can anyone else tell me? -- rms. */
5069 int xpos = f->output_data.x->widget->core.x;
5070 int ypos = f->output_data.x->widget->core.y;
5071 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
5072 f->output_data.x->widget->core.x = xpos;
5073 f->output_data.x->widget->core.y = ypos;
5074 }
5075 UNBLOCK_INPUT;
5076
5077 #else /* not USE_X_TOOLKIT */
5078
5079 BLOCK_INPUT;
5080
5081 check_frame_size (f, &rows, &cols);
5082 f->output_data.x->vertical_scroll_bar_extra
5083 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5084 ? 0
5085 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
5086 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
5087 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
5088 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
5089 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
5090
5091 f->output_data.x->win_gravity = NorthWestGravity;
5092 x_wm_set_size_hint (f, (long) 0, 0);
5093
5094 XSync (FRAME_X_DISPLAY (f), False);
5095 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5096 pixelwidth, pixelheight);
5097
5098 /* Now, strictly speaking, we can't be sure that this is accurate,
5099 but the window manager will get around to dealing with the size
5100 change request eventually, and we'll hear how it went when the
5101 ConfigureNotify event gets here.
5102
5103 We could just not bother storing any of this information here,
5104 and let the ConfigureNotify event set everything up, but that
5105 might be kind of confusing to the lisp code, since size changes
5106 wouldn't be reported in the frame parameters until some random
5107 point in the future when the ConfigureNotify event arrives. */
5108 change_frame_size (f, rows, cols, 0, 0);
5109 PIXEL_WIDTH (f) = pixelwidth;
5110 PIXEL_HEIGHT (f) = pixelheight;
5111
5112 /* If cursor was outside the new size, mark it as off. */
5113 if (f->phys_cursor_y >= rows
5114 || f->phys_cursor_x >= cols)
5115 {
5116 f->phys_cursor_x = -1;
5117 f->phys_cursor_y = -1;
5118 }
5119
5120 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5121 receive in the ConfigureNotify event; if we get what we asked
5122 for, then the event won't cause the screen to become garbaged, so
5123 we have to make sure to do it here. */
5124 SET_FRAME_GARBAGED (f);
5125
5126 XFlush (FRAME_X_DISPLAY (f));
5127 UNBLOCK_INPUT;
5128 #endif /* not USE_X_TOOLKIT */
5129 }
5130 \f
5131 /* Mouse warping. */
5132
5133 void
5134 x_set_mouse_position (f, x, y)
5135 struct frame *f;
5136 int x, y;
5137 {
5138 int pix_x, pix_y;
5139
5140 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
5141 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
5142
5143 if (pix_x < 0) pix_x = 0;
5144 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
5145
5146 if (pix_y < 0) pix_y = 0;
5147 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
5148
5149 BLOCK_INPUT;
5150
5151 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5152 0, 0, 0, 0, pix_x, pix_y);
5153 UNBLOCK_INPUT;
5154 }
5155
5156 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5157
5158 void
5159 x_set_mouse_pixel_position (f, pix_x, pix_y)
5160 struct frame *f;
5161 int pix_x, pix_y;
5162 {
5163 BLOCK_INPUT;
5164
5165 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5166 0, 0, 0, 0, pix_x, pix_y);
5167 UNBLOCK_INPUT;
5168 }
5169 \f
5170 /* focus shifting, raising and lowering. */
5171
5172 x_focus_on_frame (f)
5173 struct frame *f;
5174 {
5175 #if 0 /* This proves to be unpleasant. */
5176 x_raise_frame (f);
5177 #endif
5178 #if 0
5179 /* I don't think that the ICCCM allows programs to do things like this
5180 without the interaction of the window manager. Whatever you end up
5181 doing with this code, do it to x_unfocus_frame too. */
5182 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5183 RevertToPointerRoot, CurrentTime);
5184 #endif /* ! 0 */
5185 }
5186
5187 x_unfocus_frame (f)
5188 struct frame *f;
5189 {
5190 #if 0
5191 /* Look at the remarks in x_focus_on_frame. */
5192 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
5193 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
5194 RevertToPointerRoot, CurrentTime);
5195 #endif /* ! 0 */
5196 }
5197
5198 /* Raise frame F. */
5199
5200 x_raise_frame (f)
5201 struct frame *f;
5202 {
5203 if (f->async_visible)
5204 {
5205 BLOCK_INPUT;
5206 #ifdef USE_X_TOOLKIT
5207 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
5208 #else /* not USE_X_TOOLKIT */
5209 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5210 #endif /* not USE_X_TOOLKIT */
5211 XFlush (FRAME_X_DISPLAY (f));
5212 UNBLOCK_INPUT;
5213 }
5214 }
5215
5216 /* Lower frame F. */
5217
5218 x_lower_frame (f)
5219 struct frame *f;
5220 {
5221 if (f->async_visible)
5222 {
5223 BLOCK_INPUT;
5224 #ifdef USE_X_TOOLKIT
5225 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
5226 #else /* not USE_X_TOOLKIT */
5227 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5228 #endif /* not USE_X_TOOLKIT */
5229 XFlush (FRAME_X_DISPLAY (f));
5230 UNBLOCK_INPUT;
5231 }
5232 }
5233
5234 static void
5235 XTframe_raise_lower (f, raise)
5236 FRAME_PTR f;
5237 int raise;
5238 {
5239 if (raise)
5240 x_raise_frame (f);
5241 else
5242 x_lower_frame (f);
5243 }
5244 \f
5245 /* Change of visibility. */
5246
5247 /* This tries to wait until the frame is really visible.
5248 However, if the window manager asks the user where to position
5249 the frame, this will return before the user finishes doing that.
5250 The frame will not actually be visible at that time,
5251 but it will become visible later when the window manager
5252 finishes with it. */
5253
5254 x_make_frame_visible (f)
5255 struct frame *f;
5256 {
5257 int mask;
5258 Lisp_Object type;
5259
5260 BLOCK_INPUT;
5261
5262 type = x_icon_type (f);
5263 if (!NILP (type))
5264 x_bitmap_icon (f, type);
5265
5266 if (! FRAME_VISIBLE_P (f))
5267 {
5268 /* We test FRAME_GARBAGED_P here to make sure we don't
5269 call x_set_offset a second time
5270 if we get to x_make_frame_visible a second time
5271 before the window gets really visible. */
5272 if (! FRAME_ICONIFIED_P (f)
5273 && ! f->output_data.x->asked_for_visible)
5274 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
5275
5276 f->output_data.x->asked_for_visible = 1;
5277
5278 if (! EQ (Vx_no_window_manager, Qt))
5279 x_wm_set_window_state (f, NormalState);
5280 #ifdef USE_X_TOOLKIT
5281 /* This was XtPopup, but that did nothing for an iconified frame. */
5282 XtMapWidget (f->output_data.x->widget);
5283 #else /* not USE_X_TOOLKIT */
5284 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5285 #endif /* not USE_X_TOOLKIT */
5286 #if 0 /* This seems to bring back scroll bars in the wrong places
5287 if the window configuration has changed. They seem
5288 to come back ok without this. */
5289 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5290 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5291 #endif
5292 }
5293
5294 XFlush (FRAME_X_DISPLAY (f));
5295
5296 /* Synchronize to ensure Emacs knows the frame is visible
5297 before we do anything else. We do this loop with input not blocked
5298 so that incoming events are handled. */
5299 {
5300 Lisp_Object frame;
5301 int count = input_signal_count;
5302
5303 /* This must come after we set COUNT. */
5304 UNBLOCK_INPUT;
5305
5306 XSETFRAME (frame, f);
5307
5308 while (1)
5309 {
5310 x_sync (f);
5311 /* Once we have handled input events,
5312 we should have received the MapNotify if one is coming.
5313 So if we have not got it yet, stop looping.
5314 Some window managers make their own decisions
5315 about visibility. */
5316 if (input_signal_count != count)
5317 break;
5318 /* Machines that do polling rather than SIGIO have been observed
5319 to go into a busy-wait here. So we'll fake an alarm signal
5320 to let the handler know that there's something to be read.
5321 We used to raise a real alarm, but it seems that the handler
5322 isn't always enabled here. This is probably a bug. */
5323 if (input_polling_used ())
5324 {
5325 /* It could be confusing if a real alarm arrives while processing
5326 the fake one. Turn it off and let the handler reset it. */
5327 alarm (0);
5328 input_poll_signal ();
5329 }
5330 /* Once we have handled input events,
5331 we should have received the MapNotify if one is coming.
5332 So if we have not got it yet, stop looping.
5333 Some window managers make their own decisions
5334 about visibility. */
5335 if (input_signal_count != count)
5336 break;
5337 }
5338 FRAME_SAMPLE_VISIBILITY (f);
5339 }
5340 }
5341
5342 /* Change from mapped state to withdrawn state. */
5343
5344 /* Make the frame visible (mapped and not iconified). */
5345
5346 x_make_frame_invisible (f)
5347 struct frame *f;
5348 {
5349 int mask;
5350 Window window;
5351
5352 #ifdef USE_X_TOOLKIT
5353 /* Use the frame's outermost window, not the one we normally draw on. */
5354 window = XtWindow (f->output_data.x->widget);
5355 #else /* not USE_X_TOOLKIT */
5356 window = FRAME_X_WINDOW (f);
5357 #endif /* not USE_X_TOOLKIT */
5358
5359 /* Don't keep the highlight on an invisible frame. */
5360 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5361 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
5362
5363 #if 0/* This might add unreliability; I don't trust it -- rms. */
5364 if (! f->async_visible && ! f->async_iconified)
5365 return;
5366 #endif
5367
5368 BLOCK_INPUT;
5369
5370 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5371 that the current position of the window is user-specified, rather than
5372 program-specified, so that when the window is mapped again, it will be
5373 placed at the same location, without forcing the user to position it
5374 by hand again (they have already done that once for this window.) */
5375 x_wm_set_size_hint (f, (long) 0, 1);
5376
5377 #ifdef HAVE_X11R4
5378
5379 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
5380 DefaultScreen (FRAME_X_DISPLAY (f))))
5381 {
5382 UNBLOCK_INPUT_RESIGNAL;
5383 error ("Can't notify window manager of window withdrawal");
5384 }
5385 #else /* ! defined (HAVE_X11R4) */
5386
5387 /* Tell the window manager what we're going to do. */
5388 if (! EQ (Vx_no_window_manager, Qt))
5389 {
5390 XEvent unmap;
5391
5392 unmap.xunmap.type = UnmapNotify;
5393 unmap.xunmap.window = window;
5394 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
5395 unmap.xunmap.from_configure = False;
5396 if (! XSendEvent (FRAME_X_DISPLAY (f),
5397 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5398 False,
5399 SubstructureRedirectMask|SubstructureNotifyMask,
5400 &unmap))
5401 {
5402 UNBLOCK_INPUT_RESIGNAL;
5403 error ("Can't notify window manager of withdrawal");
5404 }
5405 }
5406
5407 /* Unmap the window ourselves. Cheeky! */
5408 XUnmapWindow (FRAME_X_DISPLAY (f), window);
5409 #endif /* ! defined (HAVE_X11R4) */
5410
5411 /* We can't distinguish this from iconification
5412 just by the event that we get from the server.
5413 So we can't win using the usual strategy of letting
5414 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5415 and synchronize with the server to make sure we agree. */
5416 f->visible = 0;
5417 FRAME_ICONIFIED_P (f) = 0;
5418 f->async_visible = 0;
5419 f->async_iconified = 0;
5420
5421 x_sync (f);
5422
5423 UNBLOCK_INPUT;
5424 }
5425
5426 /* Change window state from mapped to iconified. */
5427
5428 x_iconify_frame (f)
5429 struct frame *f;
5430 {
5431 int mask;
5432 int result;
5433 Lisp_Object type;
5434
5435 /* Don't keep the highlight on an invisible frame. */
5436 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5437 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
5438
5439 if (f->async_iconified)
5440 return;
5441
5442 BLOCK_INPUT;
5443
5444 FRAME_SAMPLE_VISIBILITY (f);
5445
5446 type = x_icon_type (f);
5447 if (!NILP (type))
5448 x_bitmap_icon (f, type);
5449
5450 #ifdef USE_X_TOOLKIT
5451
5452 if (! FRAME_VISIBLE_P (f))
5453 {
5454 if (! EQ (Vx_no_window_manager, Qt))
5455 x_wm_set_window_state (f, IconicState);
5456 /* This was XtPopup, but that did nothing for an iconified frame. */
5457 XtMapWidget (f->output_data.x->widget);
5458 UNBLOCK_INPUT;
5459 return;
5460 }
5461
5462 result = XIconifyWindow (FRAME_X_DISPLAY (f),
5463 XtWindow (f->output_data.x->widget),
5464 DefaultScreen (FRAME_X_DISPLAY (f)));
5465 UNBLOCK_INPUT;
5466
5467 if (!result)
5468 error ("Can't notify window manager of iconification");
5469
5470 f->async_iconified = 1;
5471
5472 BLOCK_INPUT;
5473 XFlush (FRAME_X_DISPLAY (f));
5474 UNBLOCK_INPUT;
5475 #else /* not USE_X_TOOLKIT */
5476
5477 /* Make sure the X server knows where the window should be positioned,
5478 in case the user deiconifies with the window manager. */
5479 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
5480 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
5481
5482 /* Since we don't know which revision of X we're running, we'll use both
5483 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5484
5485 /* X11R4: send a ClientMessage to the window manager using the
5486 WM_CHANGE_STATE type. */
5487 {
5488 XEvent message;
5489
5490 message.xclient.window = FRAME_X_WINDOW (f);
5491 message.xclient.type = ClientMessage;
5492 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
5493 message.xclient.format = 32;
5494 message.xclient.data.l[0] = IconicState;
5495
5496 if (! XSendEvent (FRAME_X_DISPLAY (f),
5497 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5498 False,
5499 SubstructureRedirectMask | SubstructureNotifyMask,
5500 &message))
5501 {
5502 UNBLOCK_INPUT_RESIGNAL;
5503 error ("Can't notify window manager of iconification");
5504 }
5505 }
5506
5507 /* X11R3: set the initial_state field of the window manager hints to
5508 IconicState. */
5509 x_wm_set_window_state (f, IconicState);
5510
5511 if (!FRAME_VISIBLE_P (f))
5512 {
5513 /* If the frame was withdrawn, before, we must map it. */
5514 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5515 }
5516
5517 f->async_iconified = 1;
5518
5519 XFlush (FRAME_X_DISPLAY (f));
5520 UNBLOCK_INPUT;
5521 #endif /* not USE_X_TOOLKIT */
5522 }
5523 \f
5524 /* Destroy the X window of frame F. */
5525
5526 x_destroy_window (f)
5527 struct frame *f;
5528 {
5529 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5530
5531 BLOCK_INPUT;
5532
5533 if (f->output_data.x->icon_desc != 0)
5534 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
5535 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
5536 #ifdef USE_X_TOOLKIT
5537 XtDestroyWidget (f->output_data.x->widget);
5538 free_frame_menubar (f);
5539 #endif /* USE_X_TOOLKIT */
5540
5541 free_frame_faces (f);
5542 XFlush (FRAME_X_DISPLAY (f));
5543
5544 xfree (f->output_data.x);
5545 f->output_data.x = 0;
5546 if (f == dpyinfo->x_focus_frame)
5547 dpyinfo->x_focus_frame = 0;
5548 if (f == dpyinfo->x_focus_event_frame)
5549 dpyinfo->x_focus_event_frame = 0;
5550 if (f == dpyinfo->x_highlight_frame)
5551 dpyinfo->x_highlight_frame = 0;
5552
5553 dpyinfo->reference_count--;
5554
5555 if (f == dpyinfo->mouse_face_mouse_frame)
5556 {
5557 dpyinfo->mouse_face_beg_row
5558 = dpyinfo->mouse_face_beg_col = -1;
5559 dpyinfo->mouse_face_end_row
5560 = dpyinfo->mouse_face_end_col = -1;
5561 dpyinfo->mouse_face_window = Qnil;
5562 }
5563
5564 UNBLOCK_INPUT;
5565 }
5566 \f
5567 /* Setting window manager hints. */
5568
5569 /* Set the normal size hints for the window manager, for frame F.
5570 FLAGS is the flags word to use--or 0 meaning preserve the flags
5571 that the window now has.
5572 If USER_POSITION is nonzero, we set the USPosition
5573 flag (this is useful when FLAGS is 0). */
5574
5575 x_wm_set_size_hint (f, flags, user_position)
5576 struct frame *f;
5577 long flags;
5578 int user_position;
5579 {
5580 XSizeHints size_hints;
5581
5582 #ifdef USE_X_TOOLKIT
5583 Arg al[2];
5584 int ac = 0;
5585 Dimension widget_width, widget_height;
5586 Window window = XtWindow (f->output_data.x->widget);
5587 #else /* not USE_X_TOOLKIT */
5588 Window window = FRAME_X_WINDOW (f);
5589 #endif /* not USE_X_TOOLKIT */
5590
5591 /* Setting PMaxSize caused various problems. */
5592 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5593
5594 flexlines = f->height;
5595
5596 size_hints.x = f->output_data.x->left_pos;
5597 size_hints.y = f->output_data.x->top_pos;
5598
5599 #ifdef USE_X_TOOLKIT
5600 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5601 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5602 XtGetValues (f->output_data.x->widget, al, ac);
5603 size_hints.height = widget_height;
5604 size_hints.width = widget_width;
5605 #else /* not USE_X_TOOLKIT */
5606 size_hints.height = PIXEL_HEIGHT (f);
5607 size_hints.width = PIXEL_WIDTH (f);
5608 #endif /* not USE_X_TOOLKIT */
5609
5610 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
5611 size_hints.height_inc = f->output_data.x->line_height;
5612 size_hints.max_width
5613 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
5614 size_hints.max_height
5615 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
5616
5617 /* Calculate the base and minimum sizes.
5618
5619 (When we use the X toolkit, we don't do it here.
5620 Instead we copy the values that the widgets are using, below.) */
5621 #ifndef USE_X_TOOLKIT
5622 {
5623 int base_width, base_height;
5624 int min_rows = 0, min_cols = 0;
5625
5626 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5627 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
5628
5629 check_frame_size (f, &min_rows, &min_cols);
5630
5631 /* The window manager uses the base width hints to calculate the
5632 current number of rows and columns in the frame while
5633 resizing; min_width and min_height aren't useful for this
5634 purpose, since they might not give the dimensions for a
5635 zero-row, zero-column frame.
5636
5637 We use the base_width and base_height members if we have
5638 them; otherwise, we set the min_width and min_height members
5639 to the size for a zero x zero frame. */
5640
5641 #ifdef HAVE_X11R4
5642 size_hints.flags |= PBaseSize;
5643 size_hints.base_width = base_width;
5644 size_hints.base_height = base_height;
5645 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5646 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5647 #else
5648 size_hints.min_width = base_width;
5649 size_hints.min_height = base_height;
5650 #endif
5651 }
5652
5653 /* If we don't need the old flags, we don't need the old hint at all. */
5654 if (flags)
5655 {
5656 size_hints.flags |= flags;
5657 goto no_read;
5658 }
5659 #endif /* not USE_X_TOOLKIT */
5660
5661 {
5662 XSizeHints hints; /* Sometimes I hate X Windows... */
5663 long supplied_return;
5664 int value;
5665
5666 #ifdef HAVE_X11R4
5667 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5668 &supplied_return);
5669 #else
5670 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5671 #endif
5672
5673 #ifdef USE_X_TOOLKIT
5674 size_hints.base_height = hints.base_height;
5675 size_hints.base_width = hints.base_width;
5676 size_hints.min_height = hints.min_height;
5677 size_hints.min_width = hints.min_width;
5678 #endif
5679
5680 if (flags)
5681 size_hints.flags |= flags;
5682 else
5683 {
5684 if (value == 0)
5685 hints.flags = 0;
5686 if (hints.flags & PSize)
5687 size_hints.flags |= PSize;
5688 if (hints.flags & PPosition)
5689 size_hints.flags |= PPosition;
5690 if (hints.flags & USPosition)
5691 size_hints.flags |= USPosition;
5692 if (hints.flags & USSize)
5693 size_hints.flags |= USSize;
5694 }
5695 }
5696
5697 no_read:
5698
5699 #ifdef PWinGravity
5700 size_hints.win_gravity = f->output_data.x->win_gravity;
5701 size_hints.flags |= PWinGravity;
5702
5703 if (user_position)
5704 {
5705 size_hints.flags &= ~ PPosition;
5706 size_hints.flags |= USPosition;
5707 }
5708 #endif /* PWinGravity */
5709
5710 #ifdef HAVE_X11R4
5711 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5712 #else
5713 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5714 #endif
5715 }
5716
5717 /* Used for IconicState or NormalState */
5718 x_wm_set_window_state (f, state)
5719 struct frame *f;
5720 int state;
5721 {
5722 #ifdef USE_X_TOOLKIT
5723 Arg al[1];
5724
5725 XtSetArg (al[0], XtNinitialState, state);
5726 XtSetValues (f->output_data.x->widget, al, 1);
5727 #else /* not USE_X_TOOLKIT */
5728 Window window = FRAME_X_WINDOW (f);
5729
5730 f->output_data.x->wm_hints.flags |= StateHint;
5731 f->output_data.x->wm_hints.initial_state = state;
5732
5733 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5734 #endif /* not USE_X_TOOLKIT */
5735 }
5736
5737 x_wm_set_icon_pixmap (f, pixmap_id)
5738 struct frame *f;
5739 int pixmap_id;
5740 {
5741 #ifdef USE_X_TOOLKIT
5742 Window window = XtWindow (f->output_data.x->widget);
5743 #else
5744 Window window = FRAME_X_WINDOW (f);
5745 #endif
5746
5747 if (pixmap_id > 0)
5748 {
5749 Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5750 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5751 }
5752 else
5753 {
5754 /* It seems there is no way to turn off use of an icon pixmap.
5755 The following line does it, only if no icon has yet been created,
5756 for some window managers. But with mwm it crashes.
5757 Some people say it should clear the IconPixmapHint bit in this case,
5758 but that doesn't work, and the X consortium said it isn't the
5759 right thing at all. Since there is no way to win,
5760 best to explicitly give up. */
5761 #if 0
5762 f->output_data.x->wm_hints.icon_pixmap = None;
5763 #else
5764 return;
5765 #endif
5766 }
5767
5768 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5769 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5770 }
5771
5772 x_wm_set_icon_position (f, icon_x, icon_y)
5773 struct frame *f;
5774 int icon_x, icon_y;
5775 {
5776 #ifdef USE_X_TOOLKIT
5777 Window window = XtWindow (f->output_data.x->widget);
5778 #else
5779 Window window = FRAME_X_WINDOW (f);
5780 #endif
5781
5782 f->output_data.x->wm_hints.flags |= IconPositionHint;
5783 f->output_data.x->wm_hints.icon_x = icon_x;
5784 f->output_data.x->wm_hints.icon_y = icon_y;
5785
5786 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5787 }
5788
5789 \f
5790 /* Initialization. */
5791
5792 #ifdef USE_X_TOOLKIT
5793 static XrmOptionDescRec emacs_options[] = {
5794 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
5795 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
5796
5797 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5798 XrmoptionSepArg, NULL},
5799 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
5800
5801 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5802 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5803 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5804 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5805 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5806 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
5807 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
5808 };
5809 #endif /* USE_X_TOOLKIT */
5810
5811 static int x_initialized;
5812
5813 #ifdef MULTI_KBOARD
5814 /* Test whether two display-name strings agree up to the dot that separates
5815 the screen number from the server number. */
5816 static int
5817 same_x_server (name1, name2)
5818 char *name1, *name2;
5819 {
5820 int seen_colon = 0;
5821 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
5822 {
5823 if (*name1 == ':')
5824 seen_colon++;
5825 if (seen_colon && *name1 == '.')
5826 return 1;
5827 }
5828 return (seen_colon
5829 && (*name1 == '.' || *name1 == '\0')
5830 && (*name2 == '.' || *name2 == '\0'));
5831 }
5832 #endif
5833
5834 struct x_display_info *
5835 x_term_init (display_name, xrm_option, resource_name)
5836 Lisp_Object display_name;
5837 char *xrm_option;
5838 char *resource_name;
5839 {
5840 Lisp_Object frame;
5841 char *defaultvalue;
5842 int connection;
5843 Display *dpy;
5844 struct x_display_info *dpyinfo;
5845 XrmDatabase xrdb;
5846
5847 BLOCK_INPUT;
5848
5849 if (!x_initialized)
5850 {
5851 x_initialize ();
5852 x_initialized = 1;
5853 }
5854
5855 #ifdef HAVE_X_I18N
5856 setlocale (LC_ALL, NULL);
5857 #endif
5858
5859 #ifdef USE_X_TOOLKIT
5860 /* weiner@footloose.sps.mot.com reports that this causes
5861 errors with X11R5:
5862 X protocol error: BadAtom (invalid Atom parameter)
5863 on protocol request 18skiloaf.
5864 So let's not use it until R6. */
5865 #ifdef HAVE_X11XTR6
5866 XtSetLanguageProc (NULL, NULL, NULL);
5867 #endif
5868
5869 {
5870 int argc = 0;
5871 char *argv[3];
5872
5873 argv[0] = "";
5874 argc = 1;
5875 if (xrm_option)
5876 {
5877 argv[argc++] = "-xrm";
5878 argv[argc++] = xrm_option;
5879 }
5880 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
5881 resource_name, EMACS_CLASS,
5882 emacs_options, XtNumber (emacs_options),
5883 &argc, argv);
5884
5885 #ifdef HAVE_X11XTR6
5886 setlocale (LC_NUMERIC, "C");
5887 setlocale (LC_TIME, "C");
5888 #endif
5889 }
5890
5891 #else /* not USE_X_TOOLKIT */
5892 #ifdef HAVE_X11R5
5893 XSetLocaleModifiers ("");
5894 #endif
5895 dpy = XOpenDisplay (XSTRING (display_name)->data);
5896 #endif /* not USE_X_TOOLKIT */
5897
5898 /* Detect failure. */
5899 if (dpy == 0)
5900 {
5901 UNBLOCK_INPUT;
5902 return 0;
5903 }
5904
5905 /* We have definitely succeeded. Record the new connection. */
5906
5907 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
5908
5909 #ifdef MULTI_KBOARD
5910 {
5911 struct x_display_info *share;
5912 Lisp_Object tail;
5913
5914 for (share = x_display_list, tail = x_display_name_list; share;
5915 share = share->next, tail = XCONS (tail)->cdr)
5916 if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
5917 XSTRING (display_name)->data))
5918 break;
5919 if (share)
5920 dpyinfo->kboard = share->kboard;
5921 else
5922 {
5923 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
5924 init_kboard (dpyinfo->kboard);
5925 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
5926 {
5927 char *vendor = ServerVendor (dpy);
5928 dpyinfo->kboard->Vsystem_key_alist
5929 = call1 (Qvendor_specific_keysyms,
5930 build_string (vendor ? vendor : ""));
5931 }
5932
5933 dpyinfo->kboard->next_kboard = all_kboards;
5934 all_kboards = dpyinfo->kboard;
5935 /* Don't let the initial kboard remain current longer than necessary.
5936 That would cause problems if a file loaded on startup tries to
5937 prompt in the minibuffer. */
5938 if (current_kboard == initial_kboard)
5939 current_kboard = dpyinfo->kboard;
5940 }
5941 dpyinfo->kboard->reference_count++;
5942 }
5943 #endif
5944
5945 /* Put this display on the chain. */
5946 dpyinfo->next = x_display_list;
5947 x_display_list = dpyinfo;
5948
5949 /* Put it on x_display_name_list as well, to keep them parallel. */
5950 x_display_name_list = Fcons (Fcons (display_name, Qnil),
5951 x_display_name_list);
5952 dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
5953
5954 dpyinfo->display = dpy;
5955
5956 #if 0
5957 XSetAfterFunction (x_current_display, x_trace_wire);
5958 #endif /* ! 0 */
5959
5960 dpyinfo->x_id_name
5961 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
5962 + XSTRING (Vsystem_name)->size
5963 + 2);
5964 sprintf (dpyinfo->x_id_name, "%s@%s",
5965 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
5966
5967 /* Figure out which modifier bits mean what. */
5968 x_find_modifier_meanings (dpyinfo);
5969
5970 /* Get the scroll bar cursor. */
5971 dpyinfo->vertical_scroll_bar_cursor
5972 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
5973
5974 xrdb = x_load_resources (dpyinfo->display, xrm_option,
5975 resource_name, EMACS_CLASS);
5976 #ifdef HAVE_XRMSETDATABASE
5977 XrmSetDatabase (dpyinfo->display, xrdb);
5978 #else
5979 dpyinfo->display->db = xrdb;
5980 #endif
5981 /* Put the rdb where we can find it in a way that works on
5982 all versions. */
5983 dpyinfo->xrdb = xrdb;
5984
5985 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
5986 DefaultScreen (dpyinfo->display));
5987 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
5988 &dpyinfo->n_planes);
5989 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
5990 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
5991 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
5992 dpyinfo->grabbed = 0;
5993 dpyinfo->reference_count = 0;
5994 dpyinfo->icon_bitmap_id = -1;
5995 dpyinfo->n_fonts = 0;
5996 dpyinfo->font_table_size = 0;
5997 dpyinfo->bitmaps = 0;
5998 dpyinfo->bitmaps_size = 0;
5999 dpyinfo->bitmaps_last = 0;
6000 dpyinfo->scratch_cursor_gc = 0;
6001 dpyinfo->mouse_face_mouse_frame = 0;
6002 dpyinfo->mouse_face_deferred_gc = 0;
6003 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6004 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6005 dpyinfo->mouse_face_face_id = 0;
6006 dpyinfo->mouse_face_window = Qnil;
6007 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
6008 dpyinfo->mouse_face_defer = 0;
6009 dpyinfo->x_focus_frame = 0;
6010 dpyinfo->x_focus_event_frame = 0;
6011 dpyinfo->x_highlight_frame = 0;
6012
6013 dpyinfo->Xatom_wm_protocols
6014 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
6015 dpyinfo->Xatom_wm_take_focus
6016 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
6017 dpyinfo->Xatom_wm_save_yourself
6018 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
6019 dpyinfo->Xatom_wm_delete_window
6020 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
6021 dpyinfo->Xatom_wm_change_state
6022 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
6023 dpyinfo->Xatom_wm_configure_denied
6024 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
6025 dpyinfo->Xatom_wm_window_moved
6026 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
6027 dpyinfo->Xatom_editres
6028 = XInternAtom (dpyinfo->display, "Editres", False);
6029 dpyinfo->Xatom_CLIPBOARD
6030 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
6031 dpyinfo->Xatom_TIMESTAMP
6032 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
6033 dpyinfo->Xatom_TEXT
6034 = XInternAtom (dpyinfo->display, "TEXT", False);
6035 dpyinfo->Xatom_DELETE
6036 = XInternAtom (dpyinfo->display, "DELETE", False);
6037 dpyinfo->Xatom_MULTIPLE
6038 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
6039 dpyinfo->Xatom_INCR
6040 = XInternAtom (dpyinfo->display, "INCR", False);
6041 dpyinfo->Xatom_EMACS_TMP
6042 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
6043 dpyinfo->Xatom_TARGETS
6044 = XInternAtom (dpyinfo->display, "TARGETS", False);
6045 dpyinfo->Xatom_NULL
6046 = XInternAtom (dpyinfo->display, "NULL", False);
6047 dpyinfo->Xatom_ATOM_PAIR
6048 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
6049
6050 dpyinfo->cut_buffers_initialized = 0;
6051
6052 connection = ConnectionNumber (dpyinfo->display);
6053 dpyinfo->connection = connection;
6054
6055 #ifdef subprocesses
6056 /* This is only needed for distinguishing keyboard and process input. */
6057 if (connection != 0)
6058 add_keyboard_wait_descriptor (connection);
6059 #endif
6060
6061 #ifndef F_SETOWN_BUG
6062 #ifdef F_SETOWN
6063 #ifdef F_SETOWN_SOCK_NEG
6064 /* stdin is a socket here */
6065 fcntl (connection, F_SETOWN, -getpid ());
6066 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6067 fcntl (connection, F_SETOWN, getpid ());
6068 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6069 #endif /* ! defined (F_SETOWN) */
6070 #endif /* F_SETOWN_BUG */
6071
6072 #ifdef SIGIO
6073 if (interrupt_input)
6074 init_sigio (connection);
6075 #endif /* ! defined (SIGIO) */
6076
6077 UNBLOCK_INPUT;
6078
6079 return dpyinfo;
6080 }
6081 \f
6082 /* Get rid of display DPYINFO, assuming all frames are already gone,
6083 and without sending any more commands to the X server. */
6084
6085 void
6086 x_delete_display (dpyinfo)
6087 struct x_display_info *dpyinfo;
6088 {
6089 delete_keyboard_wait_descriptor (dpyinfo->connection);
6090
6091 /* Discard this display from x_display_name_list and x_display_list.
6092 We can't use Fdelq because that can quit. */
6093 if (! NILP (x_display_name_list)
6094 && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
6095 x_display_name_list = XCONS (x_display_name_list)->cdr;
6096 else
6097 {
6098 Lisp_Object tail;
6099
6100 tail = x_display_name_list;
6101 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
6102 {
6103 if (EQ (XCONS (XCONS (tail)->cdr)->car,
6104 dpyinfo->name_list_element))
6105 {
6106 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
6107 break;
6108 }
6109 tail = XCONS (tail)->cdr;
6110 }
6111 }
6112
6113 if (x_display_list == dpyinfo)
6114 x_display_list = dpyinfo->next;
6115 else
6116 {
6117 struct x_display_info *tail;
6118
6119 for (tail = x_display_list; tail; tail = tail->next)
6120 if (tail->next == dpyinfo)
6121 tail->next = tail->next->next;
6122 }
6123
6124 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6125 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6126 XrmDestroyDatabase (dpyinfo->xrdb);
6127 #endif
6128 #endif
6129 #ifdef MULTI_KBOARD
6130 if (--dpyinfo->kboard->reference_count == 0)
6131 delete_kboard (dpyinfo->kboard);
6132 #endif
6133 xfree (dpyinfo->font_table);
6134 xfree (dpyinfo->x_id_name);
6135 xfree (dpyinfo);
6136 }
6137 \f
6138 /* Set up use of X before we make the first connection. */
6139
6140 x_initialize ()
6141 {
6142 clear_frame_hook = XTclear_frame;
6143 clear_end_of_line_hook = XTclear_end_of_line;
6144 ins_del_lines_hook = XTins_del_lines;
6145 change_line_highlight_hook = XTchange_line_highlight;
6146 insert_glyphs_hook = XTinsert_glyphs;
6147 write_glyphs_hook = XTwrite_glyphs;
6148 delete_glyphs_hook = XTdelete_glyphs;
6149 ring_bell_hook = XTring_bell;
6150 reset_terminal_modes_hook = XTreset_terminal_modes;
6151 set_terminal_modes_hook = XTset_terminal_modes;
6152 update_begin_hook = XTupdate_begin;
6153 update_end_hook = XTupdate_end;
6154 set_terminal_window_hook = XTset_terminal_window;
6155 read_socket_hook = XTread_socket;
6156 frame_up_to_date_hook = XTframe_up_to_date;
6157 cursor_to_hook = XTcursor_to;
6158 reassert_line_highlight_hook = XTreassert_line_highlight;
6159 mouse_position_hook = XTmouse_position;
6160 frame_rehighlight_hook = XTframe_rehighlight;
6161 frame_raise_lower_hook = XTframe_raise_lower;
6162 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
6163 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
6164 redeem_scroll_bar_hook = XTredeem_scroll_bar;
6165 judge_scroll_bars_hook = XTjudge_scroll_bars;
6166
6167 scroll_region_ok = 1; /* we'll scroll partial frames */
6168 char_ins_del_ok = 0; /* just as fast to write the line */
6169 line_ins_del_ok = 1; /* we'll just blt 'em */
6170 fast_clear_end_of_line = 1; /* X does this well */
6171 memory_below_frame = 0; /* we don't remember what scrolls
6172 off the bottom */
6173 baud_rate = 19200;
6174
6175 x_noop_count = 0;
6176
6177 /* Try to use interrupt input; if we can't, then start polling. */
6178 Fset_input_mode (Qt, Qnil, Qt, Qnil);
6179
6180 #ifdef USE_X_TOOLKIT
6181 XtToolkitInitialize ();
6182 Xt_app_con = XtCreateApplicationContext ();
6183 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
6184 #endif
6185
6186 /* Note that there is no real way portable across R3/R4 to get the
6187 original error handler. */
6188 XSetErrorHandler (x_error_quitter);
6189 XSetIOErrorHandler (x_io_error_quitter);
6190
6191 /* Disable Window Change signals; they are handled by X events. */
6192 #ifdef SIGWINCH
6193 signal (SIGWINCH, SIG_DFL);
6194 #endif /* ! defined (SIGWINCH) */
6195
6196 signal (SIGPIPE, x_connection_signal);
6197 }
6198
6199 void
6200 syms_of_xterm ()
6201 {
6202 staticpro (&x_display_name_list);
6203 x_display_name_list = Qnil;
6204
6205 staticpro (&last_mouse_scroll_bar);
6206 last_mouse_scroll_bar = Qnil;
6207
6208 staticpro (&Qvendor_specific_keysyms);
6209 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
6210 }
6211 #endif /* ! defined (HAVE_X_WINDOWS) */