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