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