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