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