]> code.delx.au - gnu-emacs/blob - src/xterm.c
(compilation-handle-exit): New function, broken out of compilation-sentinel.
[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 signalling 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++;
3465
3466 count += 1;
3467 numchars -= 1;
3468 }
3469 break;
3470
3471 case SelectionRequest: /* Someone wants our selection. */
3472 #ifdef USE_X_TOOLKIT
3473 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
3474 goto OTHER;
3475 #endif /* USE_X_TOOLKIT */
3476 if (x_queue_selection_requests)
3477 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
3478 &event);
3479 else
3480 {
3481 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
3482
3483 if (numchars == 0)
3484 abort ();
3485
3486 bufp->kind = selection_request_event;
3487 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3488 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
3489 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3490 SELECTION_EVENT_TARGET (bufp) = eventp->target;
3491 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
3492 SELECTION_EVENT_TIME (bufp) = eventp->time;
3493 bufp++;
3494
3495 count += 1;
3496 numchars -= 1;
3497 }
3498 break;
3499
3500 case PropertyNotify:
3501 #ifdef USE_X_TOOLKIT
3502 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
3503 goto OTHER;
3504 #endif /* not USE_X_TOOLKIT */
3505 x_handle_property_notify (&event);
3506 break;
3507
3508 case ReparentNotify:
3509 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
3510 if (f)
3511 {
3512 int x, y;
3513 f->output_data.x->parent_desc = event.xreparent.parent;
3514 x_real_positions (f, &x, &y);
3515 f->output_data.x->left_pos = x;
3516 f->output_data.x->top_pos = y;
3517 }
3518 break;
3519
3520 case Expose:
3521 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3522 if (f)
3523 {
3524 if (f->async_visible == 0)
3525 {
3526 f->async_visible = 1;
3527 f->async_iconified = 0;
3528 SET_FRAME_GARBAGED (f);
3529 }
3530 else
3531 dumprectangle (x_window_to_frame (dpyinfo,
3532 event.xexpose.window),
3533 event.xexpose.x, event.xexpose.y,
3534 event.xexpose.width, event.xexpose.height);
3535 }
3536 else
3537 {
3538 struct scroll_bar *bar
3539 = x_window_to_scroll_bar (event.xexpose.window);
3540
3541 if (bar)
3542 x_scroll_bar_expose (bar, &event);
3543 #ifdef USE_X_TOOLKIT
3544 else
3545 goto OTHER;
3546 #endif /* USE_X_TOOLKIT */
3547 }
3548 break;
3549
3550 case GraphicsExpose: /* This occurs when an XCopyArea's
3551 source area was obscured or not
3552 available.*/
3553 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
3554 if (f)
3555 {
3556 dumprectangle (f,
3557 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
3558 event.xgraphicsexpose.width,
3559 event.xgraphicsexpose.height);
3560 }
3561 #ifdef USE_X_TOOLKIT
3562 else
3563 goto OTHER;
3564 #endif /* USE_X_TOOLKIT */
3565 break;
3566
3567 case NoExpose: /* This occurs when an XCopyArea's
3568 source area was completely
3569 available */
3570 break;
3571
3572 case UnmapNotify:
3573 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
3574 if (f) /* F may no longer exist if
3575 the frame was deleted. */
3576 {
3577 /* While a frame is unmapped, display generation is
3578 disabled; you don't want to spend time updating a
3579 display that won't ever be seen. */
3580 f->async_visible = 0;
3581 /* We can't distinguish, from the event, whether the window
3582 has become iconified or invisible. So assume, if it
3583 was previously visible, than now it is iconified.
3584 We depend on x_make_frame_invisible to mark it iconified. */
3585 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
3586 f->async_iconified = 1;
3587
3588 bufp->kind = iconify_event;
3589 XSETFRAME (bufp->frame_or_window, f);
3590 bufp++;
3591 count++;
3592 numchars--;
3593 }
3594 goto OTHER;
3595
3596 case MapNotify:
3597 /* We use x_top_window_to_frame because map events can come
3598 for subwindows and they don't mean that the frame is visible. */
3599 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
3600 if (f)
3601 {
3602 f->async_visible = 1;
3603 f->async_iconified = 0;
3604
3605 /* wait_reading_process_input will notice this and update
3606 the frame's display structures. */
3607 SET_FRAME_GARBAGED (f);
3608
3609 if (f->iconified)
3610 {
3611 bufp->kind = deiconify_event;
3612 XSETFRAME (bufp->frame_or_window, f);
3613 bufp++;
3614 count++;
3615 numchars--;
3616 }
3617 else
3618 /* Force a redisplay sooner or later
3619 to update the frame titles
3620 in case this is the second frame. */
3621 record_asynch_buffer_change ();
3622 }
3623 goto OTHER;
3624
3625 /* Turn off processing if we become fully obscured. */
3626 case VisibilityNotify:
3627 break;
3628
3629 case KeyPress:
3630 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
3631
3632 if (f != 0)
3633 {
3634 KeySym keysym, orig_keysym;
3635 /* al%imercury@uunet.uu.net says that making this 81 instead of
3636 80 fixed a bug whereby meta chars made his Emacs hang. */
3637 unsigned char copy_buffer[81];
3638 int modifiers;
3639
3640 event.xkey.state
3641 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
3642 extra_keyboard_modifiers);
3643 modifiers = event.xkey.state;
3644
3645 /* This will have to go some day... */
3646
3647 /* make_lispy_event turns chars into control chars.
3648 Don't do it here because XLookupString is too eager. */
3649 event.xkey.state &= ~ControlMask;
3650 event.xkey.state &= ~(dpyinfo->meta_mod_mask
3651 | dpyinfo->super_mod_mask
3652 | dpyinfo->hyper_mod_mask
3653 | dpyinfo->alt_mod_mask);
3654
3655 #ifdef HAVE_X_I18N
3656 if (FRAME_XIC (f))
3657 {
3658 /* The necessity of the following line took me
3659 a full work-day to decipher from the docs!! */
3660 if (XFilterEvent (&event, None))
3661 break;
3662 nbytes = XmbLookupString (FRAME_XIC (f),
3663 &event.xkey, copy_buffer,
3664 80, &keysym,
3665 &status_return);
3666 }
3667 else
3668 nbytes = XLookupString (&event.xkey, copy_buffer,
3669 80, &keysym, &compose_status);
3670 #else
3671 nbytes = XLookupString (&event.xkey, copy_buffer,
3672 80, &keysym, &compose_status);
3673 #endif
3674
3675 orig_keysym = keysym;
3676
3677 if (numchars > 1)
3678 {
3679 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
3680 || keysym == XK_Delete
3681 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
3682 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
3683 #ifdef HPUX
3684 /* This recognizes the "extended function keys".
3685 It seems there's no cleaner way.
3686 Test IsModifierKey to avoid handling mode_switch
3687 incorrectly. */
3688 || ((unsigned) (keysym) >= XK_Select
3689 && (unsigned)(keysym) < XK_KP_Space)
3690 #endif
3691 #ifdef XK_dead_circumflex
3692 || orig_keysym == XK_dead_circumflex
3693 #endif
3694 #ifdef XK_dead_grave
3695 || orig_keysym == XK_dead_grave
3696 #endif
3697 #ifdef XK_dead_tilde
3698 || orig_keysym == XK_dead_tilde
3699 #endif
3700 #ifdef XK_dead_diaeresis
3701 || orig_keysym == XK_dead_diaeresis
3702 #endif
3703 #ifdef XK_dead_macron
3704 || orig_keysym == XK_dead_macron
3705 #endif
3706 #ifdef XK_dead_degree
3707 || orig_keysym == XK_dead_degree
3708 #endif
3709 #ifdef XK_dead_acute
3710 || orig_keysym == XK_dead_acute
3711 #endif
3712 #ifdef XK_dead_cedilla
3713 || orig_keysym == XK_dead_cedilla
3714 #endif
3715 #ifdef XK_dead_breve
3716 || orig_keysym == XK_dead_breve
3717 #endif
3718 #ifdef XK_dead_ogonek
3719 || orig_keysym == XK_dead_ogonek
3720 #endif
3721 #ifdef XK_dead_caron
3722 || orig_keysym == XK_dead_caron
3723 #endif
3724 #ifdef XK_dead_doubleacute
3725 || orig_keysym == XK_dead_doubleacute
3726 #endif
3727 #ifdef XK_dead_abovedot
3728 || orig_keysym == XK_dead_abovedot
3729 #endif
3730 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
3731 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
3732 /* Any "vendor-specific" key is ok. */
3733 || (orig_keysym & (1 << 28)))
3734 && ! (IsModifierKey (orig_keysym)
3735 #ifndef HAVE_X11R5
3736 #ifdef XK_Mode_switch
3737 || ((unsigned)(orig_keysym) == XK_Mode_switch)
3738 #endif
3739 #ifdef XK_Num_Lock
3740 || ((unsigned)(orig_keysym) == XK_Num_Lock)
3741 #endif
3742 #endif /* not HAVE_X11R5 */
3743 ))
3744 {
3745 if (temp_index == sizeof temp_buffer / sizeof (short))
3746 temp_index = 0;
3747 temp_buffer[temp_index++] = keysym;
3748 bufp->kind = non_ascii_keystroke;
3749 bufp->code = keysym;
3750 XSETFRAME (bufp->frame_or_window, f);
3751 bufp->modifiers
3752 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3753 modifiers);
3754 bufp->timestamp = event.xkey.time;
3755 bufp++;
3756 count++;
3757 numchars--;
3758 }
3759 else if (numchars > nbytes)
3760 {
3761 register int i;
3762
3763 for (i = 0; i < nbytes; i++)
3764 {
3765 if (temp_index == sizeof temp_buffer / sizeof (short))
3766 temp_index = 0;
3767 temp_buffer[temp_index++] = copy_buffer[i];
3768 bufp->kind = ascii_keystroke;
3769 bufp->code = copy_buffer[i];
3770 XSETFRAME (bufp->frame_or_window, f);
3771 bufp->modifiers
3772 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3773 modifiers);
3774 bufp->timestamp = event.xkey.time;
3775 bufp++;
3776 }
3777
3778 count += nbytes;
3779 numchars -= nbytes;
3780 }
3781 else
3782 abort ();
3783 }
3784 else
3785 abort ();
3786 }
3787 goto OTHER;
3788
3789 /* Here's a possible interpretation of the whole
3790 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3791 FocusIn event, you have to get a FocusOut event before you
3792 relinquish the focus. If you haven't received a FocusIn event,
3793 then a mere LeaveNotify is enough to free you. */
3794
3795 case EnterNotify:
3796 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
3797
3798 if (event.xcrossing.focus) /* Entered Window */
3799 {
3800 /* Avoid nasty pop/raise loops. */
3801 if (f && (!(f->auto_raise)
3802 || !(f->auto_lower)
3803 || (event.xcrossing.time - enter_timestamp) > 500))
3804 {
3805 x_new_focus_frame (dpyinfo, f);
3806 enter_timestamp = event.xcrossing.time;
3807 }
3808 }
3809 else if (f == dpyinfo->x_focus_frame)
3810 x_new_focus_frame (dpyinfo, 0);
3811 /* EnterNotify counts as mouse movement,
3812 so update things that depend on mouse position. */
3813 if (f)
3814 note_mouse_movement (f, &event.xmotion);
3815 goto OTHER;
3816
3817 case FocusIn:
3818 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
3819 if (event.xfocus.detail != NotifyPointer)
3820 dpyinfo->x_focus_event_frame = f;
3821 if (f)
3822 x_new_focus_frame (dpyinfo, f);
3823
3824 #ifdef HAVE_X_I18N
3825 if (f && FRAME_XIC (f))
3826 XSetICFocus (FRAME_XIC (f));
3827 #endif
3828
3829 goto OTHER;
3830
3831 case LeaveNotify:
3832 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
3833 if (f)
3834 {
3835 if (f == dpyinfo->mouse_face_mouse_frame)
3836 /* If we move outside the frame,
3837 then we're certainly no longer on any text in the frame. */
3838 clear_mouse_face (dpyinfo);
3839
3840 if (event.xcrossing.focus)
3841 x_mouse_leave (dpyinfo);
3842 else
3843 {
3844 if (f == dpyinfo->x_focus_event_frame)
3845 dpyinfo->x_focus_event_frame = 0;
3846 if (f == dpyinfo->x_focus_frame)
3847 x_new_focus_frame (dpyinfo, 0);
3848 }
3849 }
3850 goto OTHER;
3851
3852 case FocusOut:
3853 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
3854 if (event.xfocus.detail != NotifyPointer
3855 && f == dpyinfo->x_focus_event_frame)
3856 dpyinfo->x_focus_event_frame = 0;
3857 if (f && f == dpyinfo->x_focus_frame)
3858 x_new_focus_frame (dpyinfo, 0);
3859
3860 #ifdef HAVE_X_I18N
3861 if (f && FRAME_XIC (f))
3862 XUnsetICFocus (FRAME_XIC (f));
3863 #endif
3864
3865 goto OTHER;
3866
3867 case MotionNotify:
3868 {
3869 if (dpyinfo->grabbed && last_mouse_frame
3870 && FRAME_LIVE_P (last_mouse_frame))
3871 f = last_mouse_frame;
3872 else
3873 f = x_window_to_frame (dpyinfo, event.xmotion.window);
3874 if (f)
3875 note_mouse_movement (f, &event.xmotion);
3876 else
3877 {
3878 struct scroll_bar *bar
3879 = x_window_to_scroll_bar (event.xmotion.window);
3880
3881 if (bar)
3882 x_scroll_bar_note_movement (bar, &event);
3883
3884 /* If we move outside the frame,
3885 then we're certainly no longer on any text in the frame. */
3886 clear_mouse_face (dpyinfo);
3887 }
3888 }
3889 goto OTHER;
3890
3891 case ConfigureNotify:
3892 f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
3893 if (f
3894 #ifdef USE_X_TOOLKIT
3895 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
3896 #endif
3897 )
3898 {
3899 #ifndef USE_X_TOOLKIT
3900 /* In the toolkit version, change_frame_size
3901 is called by the code that handles resizing
3902 of the EmacsFrame widget. */
3903
3904 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3905 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3906
3907 /* Even if the number of character rows and columns has
3908 not changed, the font size may have changed, so we need
3909 to check the pixel dimensions as well. */
3910 if (columns != f->width
3911 || rows != f->height
3912 || event.xconfigure.width != f->output_data.x->pixel_width
3913 || event.xconfigure.height != f->output_data.x->pixel_height)
3914 {
3915 change_frame_size (f, rows, columns, 0, 1);
3916 SET_FRAME_GARBAGED (f);
3917 }
3918 #endif
3919
3920 /* Formerly, in the USE_X_TOOLKIT version,
3921 we did not test send_event here. */
3922 if (1
3923 #ifndef USE_X_TOOLKIT
3924 && ! event.xconfigure.send_event
3925 #endif
3926 )
3927 {
3928 Window win, child;
3929 int win_x, win_y;
3930
3931 /* Find the position of the outside upper-left corner of
3932 the window, in the root coordinate system. Don't
3933 refer to the parent window here; we may be processing
3934 this event after the window manager has changed our
3935 parent, but before we have reached the ReparentNotify. */
3936 XTranslateCoordinates (FRAME_X_DISPLAY (f),
3937
3938 /* From-window, to-window. */
3939 event.xconfigure.window,
3940 FRAME_X_DISPLAY_INFO (f)->root_window,
3941
3942 /* From-position, to-position. */
3943 -event.xconfigure.border_width,
3944 -event.xconfigure.border_width,
3945 &win_x, &win_y,
3946
3947 /* Child of win. */
3948 &child);
3949 event.xconfigure.x = win_x;
3950 event.xconfigure.y = win_y;
3951 }
3952
3953 f->output_data.x->pixel_width = event.xconfigure.width;
3954 f->output_data.x->pixel_height = event.xconfigure.height;
3955 f->output_data.x->left_pos = event.xconfigure.x;
3956 f->output_data.x->top_pos = event.xconfigure.y;
3957
3958 /* What we have now is the position of Emacs's own window.
3959 Convert that to the position of the window manager window. */
3960 {
3961 int x, y;
3962 x_real_positions (f, &x, &y);
3963 f->output_data.x->left_pos = x;
3964 f->output_data.x->top_pos = y;
3965 /* Formerly we did not do this in the USE_X_TOOLKIT
3966 version. Let's try making them the same. */
3967 /* #ifndef USE_X_TOOLKIT */
3968 if (y != event.xconfigure.y)
3969 {
3970 /* Since the WM decorations come below top_pos now,
3971 we must put them below top_pos in the future. */
3972 f->output_data.x->win_gravity = NorthWestGravity;
3973 x_wm_set_size_hint (f, (long) 0, 0);
3974 }
3975 /* #endif */
3976 }
3977 }
3978 goto OTHER;
3979
3980 case ButtonPress:
3981 case ButtonRelease:
3982 {
3983 /* If we decide we want to generate an event to be seen
3984 by the rest of Emacs, we put it here. */
3985 struct input_event emacs_event;
3986 emacs_event.kind = no_event;
3987
3988 bzero (&compose_status, sizeof (compose_status));
3989
3990 if (dpyinfo->grabbed && last_mouse_frame
3991 && FRAME_LIVE_P (last_mouse_frame))
3992 f = last_mouse_frame;
3993 else
3994 f = x_window_to_frame (dpyinfo, event.xbutton.window);
3995
3996 if (f)
3997 {
3998 if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
3999 construct_mouse_click (&emacs_event, &event, f);
4000 }
4001 else
4002 {
4003 struct scroll_bar *bar
4004 = x_window_to_scroll_bar (event.xbutton.window);
4005
4006 if (bar)
4007 x_scroll_bar_handle_click (bar, &event, &emacs_event);
4008 }
4009
4010 if (event.type == ButtonPress)
4011 {
4012 dpyinfo->grabbed |= (1 << event.xbutton.button);
4013 last_mouse_frame = f;
4014 }
4015 else
4016 {
4017 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
4018 }
4019
4020 if (numchars >= 1 && emacs_event.kind != no_event)
4021 {
4022 bcopy (&emacs_event, bufp, sizeof (struct input_event));
4023 bufp++;
4024 count++;
4025 numchars--;
4026 }
4027
4028 #ifdef USE_X_TOOLKIT
4029 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
4030 /* For a down-event in the menu bar,
4031 don't pass it to Xt right now.
4032 Instead, save it away
4033 and we will pass it to Xt from kbd_buffer_get_event.
4034 That way, we can run some Lisp code first. */
4035 if (f && event.type == ButtonPress
4036 /* Verify the event is really within the menu bar
4037 and not just sent to it due to grabbing. */
4038 && event.xbutton.x >= 0
4039 && event.xbutton.x < f->output_data.x->pixel_width
4040 && event.xbutton.y >= 0
4041 && event.xbutton.y < f->output_data.x->menubar_height
4042 && event.xbutton.same_screen)
4043 {
4044 if (f->output_data.x->saved_button_event == 0)
4045 f->output_data.x->saved_button_event
4046 = (XButtonEvent *) xmalloc (sizeof (XButtonEvent));
4047 bcopy (&event, f->output_data.x->saved_button_event,
4048 sizeof (XButtonEvent));
4049 if (numchars >= 1)
4050 {
4051 bufp->kind = menu_bar_activate_event;
4052 XSETFRAME (bufp->frame_or_window, f);
4053 bufp++;
4054 count++;
4055 numchars--;
4056 }
4057 }
4058 else
4059 goto OTHER;
4060 #endif /* USE_X_TOOLKIT */
4061 }
4062 break;
4063
4064 case CirculateNotify:
4065 break;
4066 case CirculateRequest:
4067 break;
4068
4069 case MappingNotify:
4070 /* Someone has changed the keyboard mapping - update the
4071 local cache. */
4072 switch (event.xmapping.request)
4073 {
4074 case MappingModifier:
4075 x_find_modifier_meanings (dpyinfo);
4076 /* This is meant to fall through. */
4077 case MappingKeyboard:
4078 XRefreshKeyboardMapping (&event.xmapping);
4079 }
4080 goto OTHER;
4081
4082 default:
4083 OTHER:
4084 #ifdef USE_X_TOOLKIT
4085 BLOCK_INPUT;
4086 XtDispatchEvent (&event);
4087 UNBLOCK_INPUT;
4088 #endif /* USE_X_TOOLKIT */
4089 break;
4090 }
4091 }
4092 }
4093
4094 /* On some systems, an X bug causes Emacs to get no more events
4095 when the window is destroyed. Detect that. (1994.) */
4096 if (! event_found)
4097 {
4098 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4099 One XNOOP in 100 loops will make Emacs terminate.
4100 B. Bretthauer, 1994 */
4101 x_noop_count++;
4102 if (x_noop_count >= 100)
4103 {
4104 x_noop_count=0;
4105
4106 if (next_noop_dpyinfo == 0)
4107 next_noop_dpyinfo = x_display_list;
4108
4109 XNoOp (next_noop_dpyinfo->display);
4110
4111 /* Each time we get here, cycle through the displays now open. */
4112 next_noop_dpyinfo = next_noop_dpyinfo->next;
4113 }
4114 }
4115
4116 /* If the focus was just given to an autoraising frame,
4117 raise it now. */
4118 /* ??? This ought to be able to handle more than one such frame. */
4119 if (pending_autoraise_frame)
4120 {
4121 x_raise_frame (pending_autoraise_frame);
4122 pending_autoraise_frame = 0;
4123 }
4124
4125 UNBLOCK_INPUT;
4126 return count;
4127 }
4128 \f
4129 /* Drawing the cursor. */
4130
4131
4132 /* Draw a hollow box cursor on frame F at X, Y.
4133 Don't change the inside of the box. */
4134
4135 static void
4136 x_draw_box (f, x, y)
4137 struct frame *f;
4138 int x, y;
4139 {
4140 int left = CHAR_TO_PIXEL_COL (f, x);
4141 int top = CHAR_TO_PIXEL_ROW (f, y);
4142 int width = FONT_WIDTH (f->output_data.x->font);
4143 int height = f->output_data.x->line_height;
4144
4145 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4146 f->output_data.x->cursor_gc,
4147 left, top, width - 1, height - 1);
4148 }
4149
4150 /* Clear the cursor of frame F to background color,
4151 and mark the cursor as not shown.
4152 This is used when the text where the cursor is
4153 is about to be rewritten. */
4154
4155 static void
4156 clear_cursor (f)
4157 struct frame *f;
4158 {
4159 int mask;
4160
4161 if (! FRAME_VISIBLE_P (f)
4162 || f->phys_cursor_x < 0)
4163 return;
4164
4165 x_display_cursor (f, 0);
4166 f->phys_cursor_x = -1;
4167 }
4168
4169 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4170 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4171 glyph drawn. */
4172
4173 static void
4174 x_draw_single_glyph (f, row, column, glyph, highlight)
4175 struct frame *f;
4176 int row, column;
4177 GLYPH glyph;
4178 int highlight;
4179 {
4180 dumpglyphs (f,
4181 CHAR_TO_PIXEL_COL (f, column),
4182 CHAR_TO_PIXEL_ROW (f, row),
4183 &glyph, 1, highlight, 0);
4184 }
4185
4186 static void
4187 x_display_bar_cursor (f, on, x, y)
4188 struct frame *f;
4189 int on;
4190 int x, y;
4191 {
4192 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4193
4194 /* This is pointless on invisible frames, and dangerous on garbaged
4195 frames; in the latter case, the frame may be in the midst of
4196 changing its size, and x and y may be off the frame. */
4197 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4198 return;
4199
4200 if (! on && f->phys_cursor_x < 0)
4201 return;
4202
4203 /* If there is anything wrong with the current cursor state, remove it. */
4204 if (f->phys_cursor_x >= 0
4205 && (!on
4206 || f->phys_cursor_x != x
4207 || f->phys_cursor_y != y
4208 || f->output_data.x->current_cursor != bar_cursor))
4209 {
4210 /* Erase the cursor by redrawing the character underneath it. */
4211 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4212 f->phys_cursor_glyph,
4213 current_glyphs->highlight[f->phys_cursor_y]);
4214 f->phys_cursor_x = -1;
4215 }
4216
4217 /* If we now need a cursor in the new place or in the new form, do it so. */
4218 if (on
4219 && (f->phys_cursor_x < 0
4220 || (f->output_data.x->current_cursor != bar_cursor)))
4221 {
4222 f->phys_cursor_glyph
4223 = ((current_glyphs->enable[y]
4224 && x < current_glyphs->used[y])
4225 ? current_glyphs->glyphs[y][x]
4226 : SPACEGLYPH);
4227 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4228 f->output_data.x->cursor_gc,
4229 CHAR_TO_PIXEL_COL (f, x),
4230 CHAR_TO_PIXEL_ROW (f, y),
4231 max (f->output_data.x->cursor_width, 1),
4232 f->output_data.x->line_height);
4233
4234 f->phys_cursor_x = x;
4235 f->phys_cursor_y = y;
4236
4237 f->output_data.x->current_cursor = bar_cursor;
4238 }
4239
4240 if (updating_frame != f)
4241 XFlush (FRAME_X_DISPLAY (f));
4242 }
4243
4244
4245 /* Turn the displayed cursor of frame F on or off according to ON.
4246 If ON is nonzero, where to put the cursor is specified by X and Y. */
4247
4248 static void
4249 x_display_box_cursor (f, on, x, y)
4250 struct frame *f;
4251 int on;
4252 int x, y;
4253 {
4254 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4255
4256 /* This is pointless on invisible frames, and dangerous on garbaged
4257 frames; in the latter case, the frame may be in the midst of
4258 changing its size, and x and y may be off the frame. */
4259 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4260 return;
4261
4262 /* If cursor is off and we want it off, return quickly. */
4263 if (!on && f->phys_cursor_x < 0)
4264 return;
4265
4266 /* If cursor is currently being shown and we don't want it to be
4267 or it is in the wrong place,
4268 or we want a hollow box and it's not so, (pout!)
4269 erase it. */
4270 if (f->phys_cursor_x >= 0
4271 && (!on
4272 || f->phys_cursor_x != x
4273 || f->phys_cursor_y != y
4274 || (f->output_data.x->current_cursor != hollow_box_cursor
4275 && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
4276 {
4277 int mouse_face_here = 0;
4278 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
4279
4280 /* If the cursor is in the mouse face area, redisplay that when
4281 we clear the cursor. */
4282 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame
4283 &&
4284 (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4285 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4286 && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col))
4287 &&
4288 (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4289 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4290 && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))
4291 /* Don't redraw the cursor's spot in mouse face
4292 if it is at the end of a line (on a newline).
4293 The cursor appears there, but mouse highlighting does not. */
4294 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
4295 mouse_face_here = 1;
4296
4297 /* If the font is not as tall as a whole line,
4298 we must explicitly clear the line's whole height. */
4299 if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
4300 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4301 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4302 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4303 FONT_WIDTH (f->output_data.x->font),
4304 f->output_data.x->line_height, False);
4305 /* Erase the cursor by redrawing the character underneath it. */
4306 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4307 f->phys_cursor_glyph,
4308 (mouse_face_here
4309 ? 3
4310 : current_glyphs->highlight[f->phys_cursor_y]));
4311 f->phys_cursor_x = -1;
4312 }
4313
4314 /* If we want to show a cursor,
4315 or we want a box cursor and it's not so,
4316 write it in the right place. */
4317 if (on
4318 && (f->phys_cursor_x < 0
4319 || (f->output_data.x->current_cursor != filled_box_cursor
4320 && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
4321 {
4322 f->phys_cursor_glyph
4323 = ((current_glyphs->enable[y]
4324 && x < current_glyphs->used[y])
4325 ? current_glyphs->glyphs[y][x]
4326 : SPACEGLYPH);
4327 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
4328 {
4329 x_draw_box (f, x, y);
4330 f->output_data.x->current_cursor = hollow_box_cursor;
4331 }
4332 else
4333 {
4334 x_draw_single_glyph (f, y, x,
4335 f->phys_cursor_glyph, 2);
4336 f->output_data.x->current_cursor = filled_box_cursor;
4337 }
4338
4339 f->phys_cursor_x = x;
4340 f->phys_cursor_y = y;
4341 }
4342
4343 if (updating_frame != f)
4344 XFlush (FRAME_X_DISPLAY (f));
4345 }
4346
4347 /* Display the cursor on frame F, or clear it, according to ON.
4348 Use the position specified by curs_x and curs_y
4349 if we are doing an update of frame F now.
4350 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4351 of F. */
4352
4353 x_display_cursor (f, on)
4354 struct frame *f;
4355 int on;
4356 {
4357 BLOCK_INPUT;
4358
4359 /* If we're not updating, then don't change the physical cursor
4360 position. Just change (if appropriate) the style of display. */
4361 if (f != updating_frame)
4362 {
4363 curs_x = FRAME_CURSOR_X (f);
4364 curs_y = FRAME_CURSOR_Y (f);
4365 }
4366
4367 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4368 x_display_box_cursor (f, on, curs_x, curs_y);
4369 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4370 x_display_bar_cursor (f, on, curs_x, curs_y);
4371 else
4372 /* Those are the only two we have implemented! */
4373 abort ();
4374
4375 UNBLOCK_INPUT;
4376 }
4377
4378 /* Display the cursor on frame F, or clear it, according to ON.
4379 Don't change the cursor's position. */
4380
4381 x_update_cursor (f, on)
4382 struct frame *f;
4383 int on;
4384 {
4385 BLOCK_INPUT;
4386
4387 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4388 x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
4389 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4390 x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
4391 else
4392 /* Those are the only two we have implemented! */
4393 abort ();
4394
4395 UNBLOCK_INPUT;
4396 }
4397 \f
4398 /* Icons. */
4399
4400 /* Refresh bitmap kitchen sink icon for frame F
4401 when we get an expose event for it. */
4402
4403 refreshicon (f)
4404 struct frame *f;
4405 {
4406 /* Normally, the window manager handles this function. */
4407 }
4408
4409 /* Make the x-window of frame F use the gnu icon bitmap. */
4410
4411 int
4412 x_bitmap_icon (f, file)
4413 struct frame *f;
4414 Lisp_Object file;
4415 {
4416 int mask, bitmap_id;
4417 Window icon_window;
4418
4419 if (FRAME_X_WINDOW (f) == 0)
4420 return 1;
4421
4422 /* Free up our existing icon bitmap if any. */
4423 if (f->output_data.x->icon_bitmap > 0)
4424 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4425 f->output_data.x->icon_bitmap = 0;
4426
4427 if (STRINGP (file))
4428 bitmap_id = x_create_bitmap_from_file (f, file);
4429 else
4430 {
4431 /* Create the GNU bitmap if necessary. */
4432 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
4433 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
4434 = x_create_bitmap_from_data (f, gnu_bits,
4435 gnu_width, gnu_height);
4436
4437 /* The first time we create the GNU bitmap,
4438 this increments the refcount one extra time.
4439 As a result, the GNU bitmap is never freed.
4440 That way, we don't have to worry about allocating it again. */
4441 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
4442
4443 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
4444 }
4445
4446 x_wm_set_icon_pixmap (f, bitmap_id);
4447 f->output_data.x->icon_bitmap = bitmap_id;
4448
4449 return 0;
4450 }
4451
4452
4453 /* Make the x-window of frame F use a rectangle with text.
4454 Use ICON_NAME as the text. */
4455
4456 int
4457 x_text_icon (f, icon_name)
4458 struct frame *f;
4459 char *icon_name;
4460 {
4461 if (FRAME_X_WINDOW (f) == 0)
4462 return 1;
4463
4464 #ifdef HAVE_X11R4
4465 {
4466 XTextProperty text;
4467 text.value = (unsigned char *) icon_name;
4468 text.encoding = XA_STRING;
4469 text.format = 8;
4470 text.nitems = strlen (icon_name);
4471 #ifdef USE_X_TOOLKIT
4472 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4473 &text);
4474 #else /* not USE_X_TOOLKIT */
4475 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
4476 #endif /* not USE_X_TOOLKIT */
4477 }
4478 #else /* not HAVE_X11R4 */
4479 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
4480 #endif /* not HAVE_X11R4 */
4481
4482 if (f->output_data.x->icon_bitmap > 0)
4483 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4484 f->output_data.x->icon_bitmap = 0;
4485 x_wm_set_icon_pixmap (f, 0);
4486
4487 return 0;
4488 }
4489 \f
4490 /* Handling X errors. */
4491
4492 /* Handle the loss of connection to display DISPLAY. */
4493
4494 static SIGTYPE
4495 x_connection_closed (display, error_message)
4496 Display *display;
4497 char *error_message;
4498 {
4499 struct x_display_info *dpyinfo = x_display_info_for_display (display);
4500 Lisp_Object frame, tail;
4501
4502 /* Whatever we were in the middle of, we are going to throw out of it,
4503 so reassure various things that have error checks about being
4504 called with input blocked. */
4505 TOTALLY_UNBLOCK_INPUT;
4506
4507 if (_Xdebug)
4508 abort ();
4509
4510 /* First delete frames whose minibuffers are on frames
4511 that are on the dead display. */
4512 FOR_EACH_FRAME (tail, frame)
4513 {
4514 Lisp_Object minibuf_frame;
4515 minibuf_frame
4516 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
4517 if (FRAME_X_P (XFRAME (frame))
4518 && FRAME_X_P (XFRAME (minibuf_frame))
4519 && ! EQ (frame, minibuf_frame)
4520 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
4521 Fdelete_frame (frame, Qt);
4522 }
4523
4524 /* Now delete all remaining frames on the dead display.
4525 We are now sure none of these is used as the minibuffer
4526 for another frame that we need to delete. */
4527 FOR_EACH_FRAME (tail, frame)
4528 if (FRAME_X_P (XFRAME (frame))
4529 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
4530 {
4531 /* Set this to t so that Fdelete_frame won't get confused
4532 trying to find a replacement. */
4533 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
4534 Fdelete_frame (frame, Qt);
4535 }
4536
4537 if (dpyinfo)
4538 x_delete_display (dpyinfo);
4539
4540 if (x_display_list == 0)
4541 {
4542 fprintf (stderr, "%s", error_message);
4543 shut_down_emacs (0, 0, Qnil);
4544 exit (70);
4545 }
4546
4547 /* Ordinary stack unwind doesn't deal with these. */
4548 #ifdef SIGIO
4549 sigunblock (sigmask (SIGIO));
4550 #endif
4551 sigunblock (sigmask (SIGALRM));
4552 TOTALLY_UNBLOCK_INPUT;
4553
4554 error ("%s", error_message);
4555 }
4556
4557 /* This is the usual handler for X protocol errors.
4558 It kills all frames on the display that we got the error for.
4559 If that was the only one, it prints an error message and kills Emacs. */
4560
4561 static int
4562 x_error_quitter (display, error)
4563 Display *display;
4564 XErrorEvent *error;
4565 {
4566 char buf[256], buf1[356];
4567
4568 /* Note that there is no real way portable across R3/R4 to get the
4569 original error handler. */
4570
4571 XGetErrorText (display, error->error_code, buf, sizeof (buf));
4572 sprintf (buf1, "X protocol error: %s on protocol request %d",
4573 buf, error->request_code);
4574 x_connection_closed (display, buf1);
4575 }
4576
4577 /* This is the handler for X IO errors, always.
4578 It kills all frames on the display that we lost touch with.
4579 If that was the only one, it prints an error message and kills Emacs. */
4580
4581 static int
4582 x_io_error_quitter (display)
4583 Display *display;
4584 {
4585 char buf[256];
4586
4587 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
4588 x_connection_closed (display, buf);
4589 }
4590 \f
4591 /* Handle SIGPIPE, which can happen when the connection to a server
4592 simply goes away. SIGPIPE is handled by x_connection_signal.
4593 It works by sending a no-op command to each X server connection.
4594 When we try a connection that has closed, we get SIGPIPE again.
4595 But this time, it is handled by x_connection_signal_1.
4596 That function knows which connection we were testing,
4597 so it closes that one.
4598
4599 x_connection_closed never returns,
4600 so if more than one connection was lost at once,
4601 we only find one. But XTread_socket keeps trying them all,
4602 so it will notice the other closed one sooner or later. */
4603
4604
4605 static struct x_display_info *x_connection_signal_dpyinfo;
4606
4607 static SIGTYPE x_connection_signal ();
4608
4609 static SIGTYPE
4610 x_connection_signal_1 (signalnum) /* If we don't have an argument, */
4611 int signalnum; /* some compilers complain in signal calls. */
4612 {
4613 signal (SIGPIPE, x_connection_signal);
4614 x_connection_closed (x_connection_signal_dpyinfo,
4615 "connection was lost");
4616 }
4617
4618 static SIGTYPE
4619 x_connection_signal (signalnum) /* If we don't have an argument, */
4620 int signalnum; /* some compilers complain in signal calls. */
4621 {
4622 x_connection_signal_dpyinfo = x_display_list;
4623
4624 stop_polling ();
4625 sigunblock (SIGPIPE);
4626
4627 while (x_connection_signal_dpyinfo)
4628 {
4629 signal (SIGPIPE, x_connection_signal_1);
4630 signal (SIGALRM, x_connection_signal_1);
4631
4632 /* According to Jim Campbell <jec@murzim.ca.boeing.com>,
4633 On Solaris 2.4, XNoOp can hang when the connection
4634 has already died. Since XNoOp should not wait,
4635 let's assume that if it hangs for 3 seconds
4636 that means the connection is dead.
4637 This is a kludge, but I don't see any other way that works. */
4638 alarm (3);
4639 XNoOp (x_connection_signal_dpyinfo->display);
4640 alarm (0);
4641
4642 XSync (x_connection_signal_dpyinfo->display, False);
4643
4644 /* Each time we get here, cycle through the displays now open. */
4645 x_connection_signal_dpyinfo = x_connection_signal_dpyinfo->next;
4646 }
4647
4648 /* We should have found some closed connection. */
4649 abort ();
4650 }
4651 \f
4652 /* A buffer for storing X error messages. */
4653 static char *x_caught_error_message;
4654 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4655
4656 /* An X error handler which stores the error message in
4657 x_caught_error_message. This is what's installed when
4658 x_catch_errors is in effect. */
4659
4660 static int
4661 x_error_catcher (display, error)
4662 Display *display;
4663 XErrorEvent *error;
4664 {
4665 XGetErrorText (display, error->error_code,
4666 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
4667 }
4668
4669
4670 /* Begin trapping X errors for display DPY. Actually we trap X errors
4671 for all displays, but DPY should be the display you are actually
4672 operating on.
4673
4674 After calling this function, X protocol errors no longer cause
4675 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4676
4677 Calling x_check_errors signals an Emacs error if an X error has
4678 occurred since the last call to x_catch_errors or x_check_errors.
4679
4680 Calling x_uncatch_errors resumes the normal error handling. */
4681
4682 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4683
4684 void
4685 x_catch_errors (dpy)
4686 Display *dpy;
4687 {
4688 /* Make sure any errors from previous requests have been dealt with. */
4689 XSync (dpy, False);
4690
4691 /* Set up the error buffer. */
4692 x_caught_error_message
4693 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
4694 x_caught_error_message[0] = '\0';
4695
4696 /* Install our little error handler. */
4697 XSetErrorHandler (x_error_catcher);
4698 }
4699
4700 /* If any X protocol errors have arrived since the last call to
4701 x_catch_errors or x_check_errors, signal an Emacs error using
4702 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4703
4704 void
4705 x_check_errors (dpy, format)
4706 Display *dpy;
4707 char *format;
4708 {
4709 /* Make sure to catch any errors incurred so far. */
4710 XSync (dpy, False);
4711
4712 if (x_caught_error_message[0])
4713 {
4714 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
4715
4716 sprintf (buf, format, x_caught_error_message);
4717 x_uncatch_errors (dpy);
4718 error (buf);
4719 }
4720 }
4721
4722 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4723
4724 int
4725 x_had_errors_p (dpy)
4726 Display *dpy;
4727 {
4728 /* Make sure to catch any errors incurred so far. */
4729 XSync (dpy, False);
4730
4731 return x_caught_error_message[0] != 0;
4732 }
4733
4734 /* Stop catching X protocol errors and let them make Emacs die. */
4735
4736 void
4737 x_uncatch_errors (dpy)
4738 Display *dpy;
4739 {
4740 xfree (x_caught_error_message);
4741 x_caught_error_message = 0;
4742 XSetErrorHandler (x_error_quitter);
4743 }
4744
4745 #if 0
4746 static unsigned int x_wire_count;
4747 x_trace_wire ()
4748 {
4749 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
4750 }
4751 #endif /* ! 0 */
4752
4753 \f
4754 /* Changing the font of the frame. */
4755
4756 /* Give frame F the font named FONTNAME as its default font, and
4757 return the full name of that font. FONTNAME may be a wildcard
4758 pattern; in that case, we choose some font that fits the pattern.
4759 The return value shows which font we chose. */
4760
4761 Lisp_Object
4762 x_new_font (f, fontname)
4763 struct frame *f;
4764 register char *fontname;
4765 {
4766 int already_loaded;
4767 int n_matching_fonts;
4768 XFontStruct *font_info;
4769 char **font_names;
4770
4771 /* Get a list of all the fonts that match this name. Once we
4772 have a list of matching fonts, we compare them against the fonts
4773 we already have by comparing font ids. */
4774 font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname,
4775 1024, &n_matching_fonts);
4776 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4777 find any matches; font_names == 0 is the only clue. */
4778 if (! font_names)
4779 n_matching_fonts = 0;
4780
4781 /* Don't just give up if n_matching_fonts is 0.
4782 Apparently there's a bug on Suns: XListFontsWithInfo can
4783 fail to find a font, but XLoadQueryFont may still find it. */
4784
4785 /* See if we've already loaded a matching font. */
4786 already_loaded = -1;
4787 if (n_matching_fonts != 0)
4788 {
4789 int i, j;
4790
4791 for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++)
4792 for (j = 0; j < n_matching_fonts; j++)
4793 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j])
4794 || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j]))
4795 {
4796 already_loaded = i;
4797 fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name;
4798 goto found_font;
4799 }
4800 }
4801 found_font:
4802
4803 /* If we have, just return it from the table. */
4804 if (already_loaded >= 0)
4805 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
4806 /* Otherwise, load the font and add it to the table. */
4807 else
4808 {
4809 int i;
4810 char *full_name;
4811 XFontStruct *font;
4812 int n_fonts;
4813
4814 /* Try to find a character-cell font in the list. */
4815 #if 0
4816 /* A laudable goal, but this isn't how to do it. */
4817 for (i = 0; i < n_matching_fonts; i++)
4818 if (! font_info[i].per_char)
4819 break;
4820 #else
4821 i = 0;
4822 #endif
4823
4824 /* See comment above. */
4825 if (n_matching_fonts != 0)
4826 fontname = font_names[i];
4827
4828 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
4829 if (! font)
4830 {
4831 /* Free the information from XListFonts. */
4832 if (n_matching_fonts)
4833 XFreeFontNames (font_names);
4834 return Qnil;
4835 }
4836
4837 /* Do we need to create the table? */
4838 if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0)
4839 {
4840 FRAME_X_DISPLAY_INFO (f)->font_table_size = 16;
4841 FRAME_X_DISPLAY_INFO (f)->font_table
4842 = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size
4843 * sizeof (struct font_info));
4844 }
4845 /* Do we need to grow the table? */
4846 else if (FRAME_X_DISPLAY_INFO (f)->n_fonts
4847 >= FRAME_X_DISPLAY_INFO (f)->font_table_size)
4848 {
4849 FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2;
4850 FRAME_X_DISPLAY_INFO (f)->font_table
4851 = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table,
4852 (FRAME_X_DISPLAY_INFO (f)->font_table_size
4853 * sizeof (struct font_info)));
4854 }
4855
4856 /* Try to get the full name of FONT. Put it in full_name. */
4857 full_name = 0;
4858 for (i = 0; i < font->n_properties; i++)
4859 {
4860 char *atom
4861 = XGetAtomName (FRAME_X_DISPLAY (f), font->properties[i].name);
4862 if (!strcmp (atom, "FONT"))
4863 {
4864 char *name = XGetAtomName (FRAME_X_DISPLAY (f),
4865 (Atom) (font->properties[i].card32));
4866 char *p = name;
4867 int dashes = 0;
4868
4869 /* Count the number of dashes in the "full name".
4870 If it is too few, this isn't really the font's full name,
4871 so don't use it.
4872 In X11R4, the fonts did not come with their canonical names
4873 stored in them. */
4874 while (*p)
4875 {
4876 if (*p == '-')
4877 dashes++;
4878 p++;
4879 }
4880
4881 if (dashes >= 13)
4882 full_name = name;
4883
4884 break;
4885 }
4886
4887 XFree (atom);
4888 }
4889
4890 n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts;
4891 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
4892 bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
4893 if (full_name != 0)
4894 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name;
4895 else
4896 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name;
4897 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
4898 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
4899
4900 if (full_name)
4901 fontname = full_name;
4902 }
4903
4904 /* Compute the scroll bar width in character columns. */
4905 if (f->scroll_bar_pixel_width > 0)
4906 {
4907 int wid = FONT_WIDTH (f->output_data.x->font);
4908 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
4909 }
4910 else
4911 f->scroll_bar_cols = 2;
4912
4913 /* Now make the frame display the given font. */
4914 if (FRAME_X_WINDOW (f) != 0)
4915 {
4916 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
4917 f->output_data.x->font->fid);
4918 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
4919 f->output_data.x->font->fid);
4920 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
4921 f->output_data.x->font->fid);
4922
4923 frame_update_line_height (f);
4924 x_set_window_size (f, 0, f->width, f->height);
4925 }
4926 else
4927 /* If we are setting a new frame's font for the first time,
4928 there are no faces yet, so this font's height is the line height. */
4929 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
4930
4931 {
4932 Lisp_Object lispy_name;
4933
4934 lispy_name = build_string (fontname);
4935
4936 /* Free the information from XListFonts. The data
4937 we actually retain comes from XLoadQueryFont. */
4938 XFreeFontNames (font_names);
4939
4940 return lispy_name;
4941 }
4942 }
4943 \f
4944 x_calc_absolute_position (f)
4945 struct frame *f;
4946 {
4947 Window win, child;
4948 int win_x = 0, win_y = 0;
4949 int flags = f->output_data.x->size_hint_flags;
4950 int this_window;
4951
4952 #ifdef USE_X_TOOLKIT
4953 this_window = XtWindow (f->output_data.x->widget);
4954 #else
4955 this_window = FRAME_X_WINDOW (f);
4956 #endif
4957
4958 /* Find the position of the outside upper-left corner of
4959 the inner window, with respect to the outer window. */
4960 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
4961 {
4962 BLOCK_INPUT;
4963 XTranslateCoordinates (FRAME_X_DISPLAY (f),
4964
4965 /* From-window, to-window. */
4966 this_window,
4967 f->output_data.x->parent_desc,
4968
4969 /* From-position, to-position. */
4970 0, 0, &win_x, &win_y,
4971
4972 /* Child of win. */
4973 &child);
4974 UNBLOCK_INPUT;
4975 }
4976
4977 /* Treat negative positions as relative to the leftmost bottommost
4978 position that fits on the screen. */
4979 if (flags & XNegative)
4980 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
4981 - 2 * f->output_data.x->border_width - win_x
4982 - PIXEL_WIDTH (f)
4983 + f->output_data.x->left_pos);
4984
4985 if (flags & YNegative)
4986 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
4987 - 2 * f->output_data.x->border_width - win_y
4988 - PIXEL_HEIGHT (f)
4989 - (FRAME_EXTERNAL_MENU_BAR (f)
4990 ? f->output_data.x->menubar_height : 0)
4991 + f->output_data.x->top_pos);
4992 /* The left_pos and top_pos
4993 are now relative to the top and left screen edges,
4994 so the flags should correspond. */
4995 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
4996 }
4997
4998 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4999 to really change the position, and 0 when calling from
5000 x_make_frame_visible (in that case, XOFF and YOFF are the current
5001 position values). It is -1 when calling from x_set_frame_parameters,
5002 which means, do adjust for borders but don't change the gravity. */
5003
5004 x_set_offset (f, xoff, yoff, change_gravity)
5005 struct frame *f;
5006 register int xoff, yoff;
5007 int change_gravity;
5008 {
5009 int modified_top, modified_left;
5010
5011 if (change_gravity > 0)
5012 {
5013 f->output_data.x->top_pos = yoff;
5014 f->output_data.x->left_pos = xoff;
5015 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
5016 if (xoff < 0)
5017 f->output_data.x->size_hint_flags |= XNegative;
5018 if (yoff < 0)
5019 f->output_data.x->size_hint_flags |= YNegative;
5020 f->output_data.x->win_gravity = NorthWestGravity;
5021 }
5022 x_calc_absolute_position (f);
5023
5024 BLOCK_INPUT;
5025 x_wm_set_size_hint (f, (long) 0, 0);
5026
5027 /* It is a mystery why we need to add the border_width here
5028 when the frame is already visible, but experiment says we do. */
5029 modified_left = f->output_data.x->left_pos;
5030 modified_top = f->output_data.x->top_pos;
5031 if (change_gravity != 0)
5032 {
5033 modified_left += f->output_data.x->border_width;
5034 modified_top += f->output_data.x->border_width;
5035 }
5036
5037 #ifdef USE_X_TOOLKIT
5038 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
5039 modified_left, modified_top);
5040 #else /* not USE_X_TOOLKIT */
5041 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5042 modified_left, modified_top);
5043 #endif /* not USE_X_TOOLKIT */
5044 UNBLOCK_INPUT;
5045 }
5046
5047 /* Call this to change the size of frame F's x-window.
5048 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5049 for this size change and subsequent size changes.
5050 Otherwise we leave the window gravity unchanged. */
5051
5052 x_set_window_size (f, change_gravity, cols, rows)
5053 struct frame *f;
5054 int change_gravity;
5055 int cols, rows;
5056 {
5057 int pixelwidth, pixelheight;
5058 int mask;
5059
5060 #ifdef USE_X_TOOLKIT
5061 BLOCK_INPUT;
5062 {
5063 /* The x and y position of the widget is clobbered by the
5064 call to XtSetValues within EmacsFrameSetCharSize.
5065 This is a real kludge, but I don't understand Xt so I can't
5066 figure out a correct fix. Can anyone else tell me? -- rms. */
5067 int xpos = f->output_data.x->widget->core.x;
5068 int ypos = f->output_data.x->widget->core.y;
5069 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
5070 f->output_data.x->widget->core.x = xpos;
5071 f->output_data.x->widget->core.y = ypos;
5072 }
5073 UNBLOCK_INPUT;
5074
5075 #else /* not USE_X_TOOLKIT */
5076
5077 BLOCK_INPUT;
5078
5079 check_frame_size (f, &rows, &cols);
5080 f->output_data.x->vertical_scroll_bar_extra
5081 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5082 ? 0
5083 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
5084 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
5085 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
5086 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
5087 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
5088
5089 f->output_data.x->win_gravity = NorthWestGravity;
5090 x_wm_set_size_hint (f, (long) 0, 0);
5091
5092 XSync (FRAME_X_DISPLAY (f), False);
5093 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5094 pixelwidth, pixelheight);
5095
5096 /* Now, strictly speaking, we can't be sure that this is accurate,
5097 but the window manager will get around to dealing with the size
5098 change request eventually, and we'll hear how it went when the
5099 ConfigureNotify event gets here.
5100
5101 We could just not bother storing any of this information here,
5102 and let the ConfigureNotify event set everything up, but that
5103 might be kind of confusing to the lisp code, since size changes
5104 wouldn't be reported in the frame parameters until some random
5105 point in the future when the ConfigureNotify event arrives. */
5106 change_frame_size (f, rows, cols, 0, 0);
5107 PIXEL_WIDTH (f) = pixelwidth;
5108 PIXEL_HEIGHT (f) = pixelheight;
5109
5110 /* If cursor was outside the new size, mark it as off. */
5111 if (f->phys_cursor_y >= rows
5112 || f->phys_cursor_x >= cols)
5113 {
5114 f->phys_cursor_x = -1;
5115 f->phys_cursor_y = -1;
5116 }
5117
5118 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5119 receive in the ConfigureNotify event; if we get what we asked
5120 for, then the event won't cause the screen to become garbaged, so
5121 we have to make sure to do it here. */
5122 SET_FRAME_GARBAGED (f);
5123
5124 XFlush (FRAME_X_DISPLAY (f));
5125 UNBLOCK_INPUT;
5126 #endif /* not USE_X_TOOLKIT */
5127 }
5128 \f
5129 /* Mouse warping. */
5130
5131 void
5132 x_set_mouse_position (f, x, y)
5133 struct frame *f;
5134 int x, y;
5135 {
5136 int pix_x, pix_y;
5137
5138 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
5139 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
5140
5141 if (pix_x < 0) pix_x = 0;
5142 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
5143
5144 if (pix_y < 0) pix_y = 0;
5145 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
5146
5147 BLOCK_INPUT;
5148
5149 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5150 0, 0, 0, 0, pix_x, pix_y);
5151 UNBLOCK_INPUT;
5152 }
5153
5154 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5155
5156 void
5157 x_set_mouse_pixel_position (f, pix_x, pix_y)
5158 struct frame *f;
5159 int pix_x, pix_y;
5160 {
5161 BLOCK_INPUT;
5162
5163 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5164 0, 0, 0, 0, pix_x, pix_y);
5165 UNBLOCK_INPUT;
5166 }
5167 \f
5168 /* focus shifting, raising and lowering. */
5169
5170 x_focus_on_frame (f)
5171 struct frame *f;
5172 {
5173 #if 0 /* This proves to be unpleasant. */
5174 x_raise_frame (f);
5175 #endif
5176 #if 0
5177 /* I don't think that the ICCCM allows programs to do things like this
5178 without the interaction of the window manager. Whatever you end up
5179 doing with this code, do it to x_unfocus_frame too. */
5180 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5181 RevertToPointerRoot, CurrentTime);
5182 #endif /* ! 0 */
5183 }
5184
5185 x_unfocus_frame (f)
5186 struct frame *f;
5187 {
5188 #if 0
5189 /* Look at the remarks in x_focus_on_frame. */
5190 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
5191 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
5192 RevertToPointerRoot, CurrentTime);
5193 #endif /* ! 0 */
5194 }
5195
5196 /* Raise frame F. */
5197
5198 x_raise_frame (f)
5199 struct frame *f;
5200 {
5201 if (f->async_visible)
5202 {
5203 BLOCK_INPUT;
5204 #ifdef USE_X_TOOLKIT
5205 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
5206 #else /* not USE_X_TOOLKIT */
5207 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5208 #endif /* not USE_X_TOOLKIT */
5209 XFlush (FRAME_X_DISPLAY (f));
5210 UNBLOCK_INPUT;
5211 }
5212 }
5213
5214 /* Lower frame F. */
5215
5216 x_lower_frame (f)
5217 struct frame *f;
5218 {
5219 if (f->async_visible)
5220 {
5221 BLOCK_INPUT;
5222 #ifdef USE_X_TOOLKIT
5223 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
5224 #else /* not USE_X_TOOLKIT */
5225 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5226 #endif /* not USE_X_TOOLKIT */
5227 XFlush (FRAME_X_DISPLAY (f));
5228 UNBLOCK_INPUT;
5229 }
5230 }
5231
5232 static void
5233 XTframe_raise_lower (f, raise)
5234 FRAME_PTR f;
5235 int raise;
5236 {
5237 if (raise)
5238 x_raise_frame (f);
5239 else
5240 x_lower_frame (f);
5241 }
5242 \f
5243 /* Change of visibility. */
5244
5245 /* This tries to wait until the frame is really visible.
5246 However, if the window manager asks the user where to position
5247 the frame, this will return before the user finishes doing that.
5248 The frame will not actually be visible at that time,
5249 but it will become visible later when the window manager
5250 finishes with it. */
5251
5252 x_make_frame_visible (f)
5253 struct frame *f;
5254 {
5255 int mask;
5256 Lisp_Object type;
5257
5258 BLOCK_INPUT;
5259
5260 type = x_icon_type (f);
5261 if (!NILP (type))
5262 x_bitmap_icon (f, type);
5263
5264 if (! FRAME_VISIBLE_P (f))
5265 {
5266 /* We test FRAME_GARBAGED_P here to make sure we don't
5267 call x_set_offset a second time
5268 if we get to x_make_frame_visible a second time
5269 before the window gets really visible. */
5270 if (! FRAME_ICONIFIED_P (f)
5271 && ! f->output_data.x->asked_for_visible)
5272 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
5273
5274 f->output_data.x->asked_for_visible = 1;
5275
5276 if (! EQ (Vx_no_window_manager, Qt))
5277 x_wm_set_window_state (f, NormalState);
5278 #ifdef USE_X_TOOLKIT
5279 /* This was XtPopup, but that did nothing for an iconified frame. */
5280 XtMapWidget (f->output_data.x->widget);
5281 #else /* not USE_X_TOOLKIT */
5282 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5283 #endif /* not USE_X_TOOLKIT */
5284 #if 0 /* This seems to bring back scroll bars in the wrong places
5285 if the window configuration has changed. They seem
5286 to come back ok without this. */
5287 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5288 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5289 #endif
5290 }
5291
5292 XFlush (FRAME_X_DISPLAY (f));
5293
5294 /* Synchronize to ensure Emacs knows the frame is visible
5295 before we do anything else. We do this loop with input not blocked
5296 so that incoming events are handled. */
5297 {
5298 Lisp_Object frame;
5299 int count = input_signal_count;
5300
5301 /* This must come after we set COUNT. */
5302 UNBLOCK_INPUT;
5303
5304 XSETFRAME (frame, f);
5305
5306 while (1)
5307 {
5308 x_sync (f);
5309 /* Once we have handled input events,
5310 we should have received the MapNotify if one is coming.
5311 So if we have not got it yet, stop looping.
5312 Some window managers make their own decisions
5313 about visibility. */
5314 if (input_signal_count != count)
5315 break;
5316 /* Machines that do polling rather than SIGIO have been observed
5317 to go into a busy-wait here. So we'll fake an alarm signal
5318 to let the handler know that there's something to be read.
5319 We used to raise a real alarm, but it seems that the handler
5320 isn't always enabled here. This is probably a bug. */
5321 if (input_polling_used ())
5322 {
5323 /* It could be confusing if a real alarm arrives while processing
5324 the fake one. Turn it off and let the handler reset it. */
5325 alarm (0);
5326 input_poll_signal ();
5327 }
5328 /* Once we have handled input events,
5329 we should have received the MapNotify if one is coming.
5330 So if we have not got it yet, stop looping.
5331 Some window managers make their own decisions
5332 about visibility. */
5333 if (input_signal_count != count)
5334 break;
5335 }
5336 FRAME_SAMPLE_VISIBILITY (f);
5337 }
5338 }
5339
5340 /* Change from mapped state to withdrawn state. */
5341
5342 /* Make the frame visible (mapped and not iconified). */
5343
5344 x_make_frame_invisible (f)
5345 struct frame *f;
5346 {
5347 int mask;
5348 Window window;
5349
5350 #ifdef USE_X_TOOLKIT
5351 /* Use the frame's outermost window, not the one we normally draw on. */
5352 window = XtWindow (f->output_data.x->widget);
5353 #else /* not USE_X_TOOLKIT */
5354 window = FRAME_X_WINDOW (f);
5355 #endif /* not USE_X_TOOLKIT */
5356
5357 /* Don't keep the highlight on an invisible frame. */
5358 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5359 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
5360
5361 #if 0/* This might add unreliability; I don't trust it -- rms. */
5362 if (! f->async_visible && ! f->async_iconified)
5363 return;
5364 #endif
5365
5366 BLOCK_INPUT;
5367
5368 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5369 that the current position of the window is user-specified, rather than
5370 program-specified, so that when the window is mapped again, it will be
5371 placed at the same location, without forcing the user to position it
5372 by hand again (they have already done that once for this window.) */
5373 x_wm_set_size_hint (f, (long) 0, 1);
5374
5375 #ifdef HAVE_X11R4
5376
5377 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
5378 DefaultScreen (FRAME_X_DISPLAY (f))))
5379 {
5380 UNBLOCK_INPUT_RESIGNAL;
5381 error ("Can't notify window manager of window withdrawal");
5382 }
5383 #else /* ! defined (HAVE_X11R4) */
5384
5385 /* Tell the window manager what we're going to do. */
5386 if (! EQ (Vx_no_window_manager, Qt))
5387 {
5388 XEvent unmap;
5389
5390 unmap.xunmap.type = UnmapNotify;
5391 unmap.xunmap.window = window;
5392 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
5393 unmap.xunmap.from_configure = False;
5394 if (! XSendEvent (FRAME_X_DISPLAY (f),
5395 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5396 False,
5397 SubstructureRedirectMask|SubstructureNotifyMask,
5398 &unmap))
5399 {
5400 UNBLOCK_INPUT_RESIGNAL;
5401 error ("Can't notify window manager of withdrawal");
5402 }
5403 }
5404
5405 /* Unmap the window ourselves. Cheeky! */
5406 XUnmapWindow (FRAME_X_DISPLAY (f), window);
5407 #endif /* ! defined (HAVE_X11R4) */
5408
5409 /* We can't distinguish this from iconification
5410 just by the event that we get from the server.
5411 So we can't win using the usual strategy of letting
5412 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5413 and synchronize with the server to make sure we agree. */
5414 f->visible = 0;
5415 FRAME_ICONIFIED_P (f) = 0;
5416 f->async_visible = 0;
5417 f->async_iconified = 0;
5418
5419 x_sync (f);
5420
5421 UNBLOCK_INPUT;
5422 }
5423
5424 /* Change window state from mapped to iconified. */
5425
5426 x_iconify_frame (f)
5427 struct frame *f;
5428 {
5429 int mask;
5430 int result;
5431 Lisp_Object type;
5432
5433 /* Don't keep the highlight on an invisible frame. */
5434 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5435 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
5436
5437 if (f->async_iconified)
5438 return;
5439
5440 BLOCK_INPUT;
5441
5442 FRAME_SAMPLE_VISIBILITY (f);
5443
5444 type = x_icon_type (f);
5445 if (!NILP (type))
5446 x_bitmap_icon (f, type);
5447
5448 #ifdef USE_X_TOOLKIT
5449
5450 if (! FRAME_VISIBLE_P (f))
5451 {
5452 if (! EQ (Vx_no_window_manager, Qt))
5453 x_wm_set_window_state (f, IconicState);
5454 /* This was XtPopup, but that did nothing for an iconified frame. */
5455 XtMapWidget (f->output_data.x->widget);
5456 UNBLOCK_INPUT;
5457 return;
5458 }
5459
5460 result = XIconifyWindow (FRAME_X_DISPLAY (f),
5461 XtWindow (f->output_data.x->widget),
5462 DefaultScreen (FRAME_X_DISPLAY (f)));
5463 UNBLOCK_INPUT;
5464
5465 if (!result)
5466 error ("Can't notify window manager of iconification");
5467
5468 f->async_iconified = 1;
5469
5470 BLOCK_INPUT;
5471 XFlush (FRAME_X_DISPLAY (f));
5472 UNBLOCK_INPUT;
5473 #else /* not USE_X_TOOLKIT */
5474
5475 /* Make sure the X server knows where the window should be positioned,
5476 in case the user deiconifies with the window manager. */
5477 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
5478 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
5479
5480 /* Since we don't know which revision of X we're running, we'll use both
5481 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5482
5483 /* X11R4: send a ClientMessage to the window manager using the
5484 WM_CHANGE_STATE type. */
5485 {
5486 XEvent message;
5487
5488 message.xclient.window = FRAME_X_WINDOW (f);
5489 message.xclient.type = ClientMessage;
5490 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
5491 message.xclient.format = 32;
5492 message.xclient.data.l[0] = IconicState;
5493
5494 if (! XSendEvent (FRAME_X_DISPLAY (f),
5495 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5496 False,
5497 SubstructureRedirectMask | SubstructureNotifyMask,
5498 &message))
5499 {
5500 UNBLOCK_INPUT_RESIGNAL;
5501 error ("Can't notify window manager of iconification");
5502 }
5503 }
5504
5505 /* X11R3: set the initial_state field of the window manager hints to
5506 IconicState. */
5507 x_wm_set_window_state (f, IconicState);
5508
5509 if (!FRAME_VISIBLE_P (f))
5510 {
5511 /* If the frame was withdrawn, before, we must map it. */
5512 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5513 }
5514
5515 f->async_iconified = 1;
5516
5517 XFlush (FRAME_X_DISPLAY (f));
5518 UNBLOCK_INPUT;
5519 #endif /* not USE_X_TOOLKIT */
5520 }
5521 \f
5522 /* Destroy the X window of frame F. */
5523
5524 x_destroy_window (f)
5525 struct frame *f;
5526 {
5527 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5528
5529 BLOCK_INPUT;
5530
5531 if (f->output_data.x->icon_desc != 0)
5532 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
5533 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
5534 #ifdef USE_X_TOOLKIT
5535 XtDestroyWidget (f->output_data.x->widget);
5536 free_frame_menubar (f);
5537 #endif /* USE_X_TOOLKIT */
5538
5539 free_frame_faces (f);
5540 XFlush (FRAME_X_DISPLAY (f));
5541
5542 xfree (f->output_data.x);
5543 f->output_data.x = 0;
5544 if (f == dpyinfo->x_focus_frame)
5545 dpyinfo->x_focus_frame = 0;
5546 if (f == dpyinfo->x_focus_event_frame)
5547 dpyinfo->x_focus_event_frame = 0;
5548 if (f == dpyinfo->x_highlight_frame)
5549 dpyinfo->x_highlight_frame = 0;
5550
5551 dpyinfo->reference_count--;
5552
5553 if (f == dpyinfo->mouse_face_mouse_frame)
5554 {
5555 dpyinfo->mouse_face_beg_row
5556 = dpyinfo->mouse_face_beg_col = -1;
5557 dpyinfo->mouse_face_end_row
5558 = dpyinfo->mouse_face_end_col = -1;
5559 dpyinfo->mouse_face_window = Qnil;
5560 }
5561
5562 UNBLOCK_INPUT;
5563 }
5564 \f
5565 /* Setting window manager hints. */
5566
5567 /* Set the normal size hints for the window manager, for frame F.
5568 FLAGS is the flags word to use--or 0 meaning preserve the flags
5569 that the window now has.
5570 If USER_POSITION is nonzero, we set the USPosition
5571 flag (this is useful when FLAGS is 0). */
5572
5573 x_wm_set_size_hint (f, flags, user_position)
5574 struct frame *f;
5575 long flags;
5576 int user_position;
5577 {
5578 XSizeHints size_hints;
5579
5580 #ifdef USE_X_TOOLKIT
5581 Arg al[2];
5582 int ac = 0;
5583 Dimension widget_width, widget_height;
5584 Window window = XtWindow (f->output_data.x->widget);
5585 #else /* not USE_X_TOOLKIT */
5586 Window window = FRAME_X_WINDOW (f);
5587 #endif /* not USE_X_TOOLKIT */
5588
5589 /* Setting PMaxSize caused various problems. */
5590 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5591
5592 flexlines = f->height;
5593
5594 size_hints.x = f->output_data.x->left_pos;
5595 size_hints.y = f->output_data.x->top_pos;
5596
5597 #ifdef USE_X_TOOLKIT
5598 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5599 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5600 XtGetValues (f->output_data.x->widget, al, ac);
5601 size_hints.height = widget_height;
5602 size_hints.width = widget_width;
5603 #else /* not USE_X_TOOLKIT */
5604 size_hints.height = PIXEL_HEIGHT (f);
5605 size_hints.width = PIXEL_WIDTH (f);
5606 #endif /* not USE_X_TOOLKIT */
5607
5608 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
5609 size_hints.height_inc = f->output_data.x->line_height;
5610 size_hints.max_width
5611 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
5612 size_hints.max_height
5613 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
5614
5615 /* Calculate the base and minimum sizes.
5616
5617 (When we use the X toolkit, we don't do it here.
5618 Instead we copy the values that the widgets are using, below.) */
5619 #ifndef USE_X_TOOLKIT
5620 {
5621 int base_width, base_height;
5622 int min_rows = 0, min_cols = 0;
5623
5624 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5625 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
5626
5627 check_frame_size (f, &min_rows, &min_cols);
5628
5629 /* The window manager uses the base width hints to calculate the
5630 current number of rows and columns in the frame while
5631 resizing; min_width and min_height aren't useful for this
5632 purpose, since they might not give the dimensions for a
5633 zero-row, zero-column frame.
5634
5635 We use the base_width and base_height members if we have
5636 them; otherwise, we set the min_width and min_height members
5637 to the size for a zero x zero frame. */
5638
5639 #ifdef HAVE_X11R4
5640 size_hints.flags |= PBaseSize;
5641 size_hints.base_width = base_width;
5642 size_hints.base_height = base_height;
5643 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5644 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5645 #else
5646 size_hints.min_width = base_width;
5647 size_hints.min_height = base_height;
5648 #endif
5649 }
5650
5651 /* If we don't need the old flags, we don't need the old hint at all. */
5652 if (flags)
5653 {
5654 size_hints.flags |= flags;
5655 goto no_read;
5656 }
5657 #endif /* not USE_X_TOOLKIT */
5658
5659 {
5660 XSizeHints hints; /* Sometimes I hate X Windows... */
5661 long supplied_return;
5662 int value;
5663
5664 #ifdef HAVE_X11R4
5665 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5666 &supplied_return);
5667 #else
5668 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5669 #endif
5670
5671 #ifdef USE_X_TOOLKIT
5672 size_hints.base_height = hints.base_height;
5673 size_hints.base_width = hints.base_width;
5674 size_hints.min_height = hints.min_height;
5675 size_hints.min_width = hints.min_width;
5676 #endif
5677
5678 if (flags)
5679 size_hints.flags |= flags;
5680 else
5681 {
5682 if (value == 0)
5683 hints.flags = 0;
5684 if (hints.flags & PSize)
5685 size_hints.flags |= PSize;
5686 if (hints.flags & PPosition)
5687 size_hints.flags |= PPosition;
5688 if (hints.flags & USPosition)
5689 size_hints.flags |= USPosition;
5690 if (hints.flags & USSize)
5691 size_hints.flags |= USSize;
5692 }
5693 }
5694
5695 no_read:
5696
5697 #ifdef PWinGravity
5698 size_hints.win_gravity = f->output_data.x->win_gravity;
5699 size_hints.flags |= PWinGravity;
5700
5701 if (user_position)
5702 {
5703 size_hints.flags &= ~ PPosition;
5704 size_hints.flags |= USPosition;
5705 }
5706 #endif /* PWinGravity */
5707
5708 #ifdef HAVE_X11R4
5709 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5710 #else
5711 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5712 #endif
5713 }
5714
5715 /* Used for IconicState or NormalState */
5716 x_wm_set_window_state (f, state)
5717 struct frame *f;
5718 int state;
5719 {
5720 #ifdef USE_X_TOOLKIT
5721 Arg al[1];
5722
5723 XtSetArg (al[0], XtNinitialState, state);
5724 XtSetValues (f->output_data.x->widget, al, 1);
5725 #else /* not USE_X_TOOLKIT */
5726 Window window = FRAME_X_WINDOW (f);
5727
5728 f->output_data.x->wm_hints.flags |= StateHint;
5729 f->output_data.x->wm_hints.initial_state = state;
5730
5731 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5732 #endif /* not USE_X_TOOLKIT */
5733 }
5734
5735 x_wm_set_icon_pixmap (f, pixmap_id)
5736 struct frame *f;
5737 int pixmap_id;
5738 {
5739 #ifdef USE_X_TOOLKIT
5740 Window window = XtWindow (f->output_data.x->widget);
5741 #else
5742 Window window = FRAME_X_WINDOW (f);
5743 #endif
5744
5745 if (pixmap_id > 0)
5746 {
5747 Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5748 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5749 }
5750 else
5751 {
5752 /* It seems there is no way to turn off use of an icon pixmap.
5753 The following line does it, only if no icon has yet been created,
5754 for some window managers. But with mwm it crashes.
5755 Some people say it should clear the IconPixmapHint bit in this case,
5756 but that doesn't work, and the X consortium said it isn't the
5757 right thing at all. Since there is no way to win,
5758 best to explicitly give up. */
5759 #if 0
5760 f->output_data.x->wm_hints.icon_pixmap = None;
5761 #else
5762 return;
5763 #endif
5764 }
5765
5766 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5767 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5768 }
5769
5770 x_wm_set_icon_position (f, icon_x, icon_y)
5771 struct frame *f;
5772 int icon_x, icon_y;
5773 {
5774 #ifdef USE_X_TOOLKIT
5775 Window window = XtWindow (f->output_data.x->widget);
5776 #else
5777 Window window = FRAME_X_WINDOW (f);
5778 #endif
5779
5780 f->output_data.x->wm_hints.flags |= IconPositionHint;
5781 f->output_data.x->wm_hints.icon_x = icon_x;
5782 f->output_data.x->wm_hints.icon_y = icon_y;
5783
5784 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5785 }
5786
5787 \f
5788 /* Initialization. */
5789
5790 #ifdef USE_X_TOOLKIT
5791 static XrmOptionDescRec emacs_options[] = {
5792 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
5793 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
5794
5795 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5796 XrmoptionSepArg, NULL},
5797 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
5798
5799 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5800 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5801 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5802 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5803 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5804 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
5805 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
5806 };
5807 #endif /* USE_X_TOOLKIT */
5808
5809 static int x_initialized;
5810
5811 #ifdef MULTI_KBOARD
5812 /* Test whether two display-name strings agree up to the dot that separates
5813 the screen number from the server number. */
5814 static int
5815 same_x_server (name1, name2)
5816 char *name1, *name2;
5817 {
5818 int seen_colon = 0;
5819 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
5820 {
5821 if (*name1 == ':')
5822 seen_colon++;
5823 if (seen_colon && *name1 == '.')
5824 return 1;
5825 }
5826 return (seen_colon
5827 && (*name1 == '.' || *name1 == '\0')
5828 && (*name2 == '.' || *name2 == '\0'));
5829 }
5830 #endif
5831
5832 struct x_display_info *
5833 x_term_init (display_name, xrm_option, resource_name)
5834 Lisp_Object display_name;
5835 char *xrm_option;
5836 char *resource_name;
5837 {
5838 Lisp_Object frame;
5839 char *defaultvalue;
5840 int connection;
5841 Display *dpy;
5842 struct x_display_info *dpyinfo;
5843 XrmDatabase xrdb;
5844
5845 BLOCK_INPUT;
5846
5847 if (!x_initialized)
5848 {
5849 x_initialize ();
5850 x_initialized = 1;
5851 }
5852
5853 #ifdef HAVE_X_I18N
5854 setlocale (LC_ALL, NULL);
5855 #endif
5856
5857 #ifdef USE_X_TOOLKIT
5858 /* weiner@footloose.sps.mot.com reports that this causes
5859 errors with X11R5:
5860 X protocol error: BadAtom (invalid Atom parameter)
5861 on protocol request 18skiloaf.
5862 So let's not use it until R6. */
5863 #ifdef HAVE_X11XTR6
5864 XtSetLanguageProc (NULL, NULL, NULL);
5865 #endif
5866
5867 {
5868 int argc = 0;
5869 char *argv[3];
5870
5871 argv[0] = "";
5872 argc = 1;
5873 if (xrm_option)
5874 {
5875 argv[argc++] = "-xrm";
5876 argv[argc++] = xrm_option;
5877 }
5878 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
5879 resource_name, EMACS_CLASS,
5880 emacs_options, XtNumber (emacs_options),
5881 &argc, argv);
5882
5883 #ifdef HAVE_X11XTR6
5884 setlocale (LC_NUMERIC, "C");
5885 setlocale (LC_TIME, "C");
5886 #endif
5887 }
5888
5889 #else /* not USE_X_TOOLKIT */
5890 #ifdef HAVE_X11R5
5891 XSetLocaleModifiers ("");
5892 #endif
5893 dpy = XOpenDisplay (XSTRING (display_name)->data);
5894 #endif /* not USE_X_TOOLKIT */
5895
5896 /* Detect failure. */
5897 if (dpy == 0)
5898 {
5899 UNBLOCK_INPUT;
5900 return 0;
5901 }
5902
5903 /* We have definitely succeeded. Record the new connection. */
5904
5905 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
5906
5907 #ifdef MULTI_KBOARD
5908 {
5909 struct x_display_info *share;
5910 Lisp_Object tail;
5911
5912 for (share = x_display_list, tail = x_display_name_list; share;
5913 share = share->next, tail = XCONS (tail)->cdr)
5914 if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
5915 XSTRING (display_name)->data))
5916 break;
5917 if (share)
5918 dpyinfo->kboard = share->kboard;
5919 else
5920 {
5921 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
5922 init_kboard (dpyinfo->kboard);
5923 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
5924 {
5925 char *vendor = ServerVendor (dpy);
5926 dpyinfo->kboard->Vsystem_key_alist
5927 = call1 (Qvendor_specific_keysyms,
5928 build_string (vendor ? vendor : ""));
5929 }
5930
5931 dpyinfo->kboard->next_kboard = all_kboards;
5932 all_kboards = dpyinfo->kboard;
5933 /* Don't let the initial kboard remain current longer than necessary.
5934 That would cause problems if a file loaded on startup tries to
5935 prompt in the minibuffer. */
5936 if (current_kboard == initial_kboard)
5937 current_kboard = dpyinfo->kboard;
5938 }
5939 dpyinfo->kboard->reference_count++;
5940 }
5941 #endif
5942
5943 /* Put this display on the chain. */
5944 dpyinfo->next = x_display_list;
5945 x_display_list = dpyinfo;
5946
5947 /* Put it on x_display_name_list as well, to keep them parallel. */
5948 x_display_name_list = Fcons (Fcons (display_name, Qnil),
5949 x_display_name_list);
5950 dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
5951
5952 dpyinfo->display = dpy;
5953
5954 #if 0
5955 XSetAfterFunction (x_current_display, x_trace_wire);
5956 #endif /* ! 0 */
5957
5958 dpyinfo->x_id_name
5959 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
5960 + XSTRING (Vsystem_name)->size
5961 + 2);
5962 sprintf (dpyinfo->x_id_name, "%s@%s",
5963 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
5964
5965 /* Figure out which modifier bits mean what. */
5966 x_find_modifier_meanings (dpyinfo);
5967
5968 /* Get the scroll bar cursor. */
5969 dpyinfo->vertical_scroll_bar_cursor
5970 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
5971
5972 xrdb = x_load_resources (dpyinfo->display, xrm_option,
5973 resource_name, EMACS_CLASS);
5974 #ifdef HAVE_XRMSETDATABASE
5975 XrmSetDatabase (dpyinfo->display, xrdb);
5976 #else
5977 dpyinfo->display->db = xrdb;
5978 #endif
5979 /* Put the rdb where we can find it in a way that works on
5980 all versions. */
5981 dpyinfo->xrdb = xrdb;
5982
5983 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
5984 DefaultScreen (dpyinfo->display));
5985 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
5986 &dpyinfo->n_planes);
5987 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
5988 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
5989 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
5990 dpyinfo->grabbed = 0;
5991 dpyinfo->reference_count = 0;
5992 dpyinfo->icon_bitmap_id = -1;
5993 dpyinfo->n_fonts = 0;
5994 dpyinfo->font_table_size = 0;
5995 dpyinfo->bitmaps = 0;
5996 dpyinfo->bitmaps_size = 0;
5997 dpyinfo->bitmaps_last = 0;
5998 dpyinfo->scratch_cursor_gc = 0;
5999 dpyinfo->mouse_face_mouse_frame = 0;
6000 dpyinfo->mouse_face_deferred_gc = 0;
6001 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6002 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6003 dpyinfo->mouse_face_face_id = 0;
6004 dpyinfo->mouse_face_window = Qnil;
6005 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
6006 dpyinfo->mouse_face_defer = 0;
6007 dpyinfo->x_focus_frame = 0;
6008 dpyinfo->x_focus_event_frame = 0;
6009 dpyinfo->x_highlight_frame = 0;
6010
6011 dpyinfo->Xatom_wm_protocols
6012 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
6013 dpyinfo->Xatom_wm_take_focus
6014 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
6015 dpyinfo->Xatom_wm_save_yourself
6016 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
6017 dpyinfo->Xatom_wm_delete_window
6018 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
6019 dpyinfo->Xatom_wm_change_state
6020 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
6021 dpyinfo->Xatom_wm_configure_denied
6022 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
6023 dpyinfo->Xatom_wm_window_moved
6024 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
6025 dpyinfo->Xatom_editres
6026 = XInternAtom (dpyinfo->display, "Editres", False);
6027 dpyinfo->Xatom_CLIPBOARD
6028 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
6029 dpyinfo->Xatom_TIMESTAMP
6030 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
6031 dpyinfo->Xatom_TEXT
6032 = XInternAtom (dpyinfo->display, "TEXT", False);
6033 dpyinfo->Xatom_DELETE
6034 = XInternAtom (dpyinfo->display, "DELETE", False);
6035 dpyinfo->Xatom_MULTIPLE
6036 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
6037 dpyinfo->Xatom_INCR
6038 = XInternAtom (dpyinfo->display, "INCR", False);
6039 dpyinfo->Xatom_EMACS_TMP
6040 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
6041 dpyinfo->Xatom_TARGETS
6042 = XInternAtom (dpyinfo->display, "TARGETS", False);
6043 dpyinfo->Xatom_NULL
6044 = XInternAtom (dpyinfo->display, "NULL", False);
6045 dpyinfo->Xatom_ATOM_PAIR
6046 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
6047
6048 dpyinfo->cut_buffers_initialized = 0;
6049
6050 connection = ConnectionNumber (dpyinfo->display);
6051 dpyinfo->connection = connection;
6052
6053 #ifdef subprocesses
6054 /* This is only needed for distinguishing keyboard and process input. */
6055 if (connection != 0)
6056 add_keyboard_wait_descriptor (connection);
6057 #endif
6058
6059 #ifndef F_SETOWN_BUG
6060 #ifdef F_SETOWN
6061 #ifdef F_SETOWN_SOCK_NEG
6062 /* stdin is a socket here */
6063 fcntl (connection, F_SETOWN, -getpid ());
6064 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6065 fcntl (connection, F_SETOWN, getpid ());
6066 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6067 #endif /* ! defined (F_SETOWN) */
6068 #endif /* F_SETOWN_BUG */
6069
6070 #ifdef SIGIO
6071 if (interrupt_input)
6072 init_sigio (connection);
6073 #endif /* ! defined (SIGIO) */
6074
6075 UNBLOCK_INPUT;
6076
6077 return dpyinfo;
6078 }
6079 \f
6080 /* Get rid of display DPYINFO, assuming all frames are already gone,
6081 and without sending any more commands to the X server. */
6082
6083 void
6084 x_delete_display (dpyinfo)
6085 struct x_display_info *dpyinfo;
6086 {
6087 delete_keyboard_wait_descriptor (dpyinfo->connection);
6088
6089 /* Discard this display from x_display_name_list and x_display_list.
6090 We can't use Fdelq because that can quit. */
6091 if (! NILP (x_display_name_list)
6092 && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
6093 x_display_name_list = XCONS (x_display_name_list)->cdr;
6094 else
6095 {
6096 Lisp_Object tail;
6097
6098 tail = x_display_name_list;
6099 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
6100 {
6101 if (EQ (XCONS (XCONS (tail)->cdr)->car,
6102 dpyinfo->name_list_element))
6103 {
6104 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
6105 break;
6106 }
6107 tail = XCONS (tail)->cdr;
6108 }
6109 }
6110
6111 if (x_display_list == dpyinfo)
6112 x_display_list = dpyinfo->next;
6113 else
6114 {
6115 struct x_display_info *tail;
6116
6117 for (tail = x_display_list; tail; tail = tail->next)
6118 if (tail->next == dpyinfo)
6119 tail->next = tail->next->next;
6120 }
6121
6122 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6123 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6124 XrmDestroyDatabase (dpyinfo->xrdb);
6125 #endif
6126 #endif
6127 #ifdef MULTI_KBOARD
6128 if (--dpyinfo->kboard->reference_count == 0)
6129 delete_kboard (dpyinfo->kboard);
6130 #endif
6131 xfree (dpyinfo->font_table);
6132 xfree (dpyinfo->x_id_name);
6133 xfree (dpyinfo);
6134 }
6135 \f
6136 /* Set up use of X before we make the first connection. */
6137
6138 x_initialize ()
6139 {
6140 clear_frame_hook = XTclear_frame;
6141 clear_end_of_line_hook = XTclear_end_of_line;
6142 ins_del_lines_hook = XTins_del_lines;
6143 change_line_highlight_hook = XTchange_line_highlight;
6144 insert_glyphs_hook = XTinsert_glyphs;
6145 write_glyphs_hook = XTwrite_glyphs;
6146 delete_glyphs_hook = XTdelete_glyphs;
6147 ring_bell_hook = XTring_bell;
6148 reset_terminal_modes_hook = XTreset_terminal_modes;
6149 set_terminal_modes_hook = XTset_terminal_modes;
6150 update_begin_hook = XTupdate_begin;
6151 update_end_hook = XTupdate_end;
6152 set_terminal_window_hook = XTset_terminal_window;
6153 read_socket_hook = XTread_socket;
6154 frame_up_to_date_hook = XTframe_up_to_date;
6155 cursor_to_hook = XTcursor_to;
6156 reassert_line_highlight_hook = XTreassert_line_highlight;
6157 mouse_position_hook = XTmouse_position;
6158 frame_rehighlight_hook = XTframe_rehighlight;
6159 frame_raise_lower_hook = XTframe_raise_lower;
6160 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
6161 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
6162 redeem_scroll_bar_hook = XTredeem_scroll_bar;
6163 judge_scroll_bars_hook = XTjudge_scroll_bars;
6164
6165 scroll_region_ok = 1; /* we'll scroll partial frames */
6166 char_ins_del_ok = 0; /* just as fast to write the line */
6167 line_ins_del_ok = 1; /* we'll just blt 'em */
6168 fast_clear_end_of_line = 1; /* X does this well */
6169 memory_below_frame = 0; /* we don't remember what scrolls
6170 off the bottom */
6171 baud_rate = 19200;
6172
6173 x_noop_count = 0;
6174
6175 /* Try to use interrupt input; if we can't, then start polling. */
6176 Fset_input_mode (Qt, Qnil, Qt, Qnil);
6177
6178 #ifdef USE_X_TOOLKIT
6179 XtToolkitInitialize ();
6180 Xt_app_con = XtCreateApplicationContext ();
6181 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
6182 #endif
6183
6184 /* Note that there is no real way portable across R3/R4 to get the
6185 original error handler. */
6186 XSetErrorHandler (x_error_quitter);
6187 XSetIOErrorHandler (x_io_error_quitter);
6188
6189 /* Disable Window Change signals; they are handled by X events. */
6190 #ifdef SIGWINCH
6191 signal (SIGWINCH, SIG_DFL);
6192 #endif /* ! defined (SIGWINCH) */
6193
6194 signal (SIGPIPE, x_connection_signal);
6195 }
6196
6197 void
6198 syms_of_xterm ()
6199 {
6200 staticpro (&x_display_name_list);
6201 x_display_name_list = Qnil;
6202
6203 staticpro (&last_mouse_scroll_bar);
6204 last_mouse_scroll_bar = Qnil;
6205
6206 staticpro (&Qvendor_specific_keysyms);
6207 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
6208 }
6209 #endif /* ! defined (HAVE_X_WINDOWS) */