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