At compile time, require dired.
[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;
5079};
5080
dc6f92b8 5081/* A table of all the fonts we have already loaded. */
2224a5fc 5082static struct font_info *x_font_table;
dc6f92b8
JB
5083
5084/* The current capacity of x_font_table. */
5085static int x_font_table_size;
5086
5087/* The number of fonts actually stored in x_font_table.
5088 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
5089 0 <= n_fonts <= x_font_table_size. */
5090static int n_fonts;
5091
b5cf7a0e 5092Lisp_Object
f676886a
JB
5093x_new_font (f, fontname)
5094 struct frame *f;
dc6f92b8
JB
5095 register char *fontname;
5096{
dc6f92b8
JB
5097 int already_loaded;
5098 int n_matching_fonts;
5099 XFontStruct *font_info;
5100 char **font_names;
5101
5102 /* Get a list of all the fonts that match this name. Once we
5103 have a list of matching fonts, we compare them against the fonts
5104 we already have by comparing font ids. */
2224a5fc
RS
5105 font_names = (char **) XListFonts (x_current_display, fontname,
5106 1024, &n_matching_fonts);
0c94f6ee
JB
5107 /* Apparently it doesn't set n_matching_fonts to zero when it can't
5108 find any matches; font_names == 0 is the only clue. */
5109 if (! font_names)
5110 n_matching_fonts = 0;
5111
5835f860
RS
5112 /* Don't just give up if n_matching_fonts is 0.
5113 Apparently there's a bug on Suns: XListFontsWithInfo can
5114 fail to find a font, but XLoadQueryFont may still find it. */
dc6f92b8 5115
90e65f07 5116 /* See if we've already loaded a matching font. */
5835f860
RS
5117 already_loaded = -1;
5118 if (n_matching_fonts != 0)
5119 {
5120 int i, j;
dc6f92b8 5121
5835f860
RS
5122 for (i = 0; i < n_fonts; i++)
5123 for (j = 0; j < n_matching_fonts; j++)
2224a5fc 5124 if (!strcmp (x_font_table[i].name, font_names[j]))
5835f860
RS
5125 {
5126 already_loaded = i;
5127 fontname = font_names[j];
5128 goto found_font;
5129 }
5130 }
dc6f92b8
JB
5131 found_font:
5132
5133 /* If we have, just return it from the table. */
2224a5fc
RS
5134 if (already_loaded >= 0)
5135 f->display.x->font = x_font_table[already_loaded].font;
90e65f07 5136
dc6f92b8
JB
5137 /* Otherwise, load the font and add it to the table. */
5138 else
5139 {
9696f58b 5140 int i;
dc6f92b8
JB
5141 XFontStruct *font;
5142
9696f58b 5143 /* Try to find a character-cell font in the list. */
f126bd67
JB
5144#if 0
5145 /* A laudable goal, but this isn't how to do it. */
9696f58b
JB
5146 for (i = 0; i < n_matching_fonts; i++)
5147 if (! font_info[i].per_char)
5148 break;
f126bd67
JB
5149#else
5150 i = 0;
5151#endif
9696f58b 5152
5835f860
RS
5153 /* See comment above. */
5154 if (n_matching_fonts != 0)
9696f58b
JB
5155 fontname = font_names[i];
5156
dc6f92b8
JB
5157 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
5158 if (! font)
5835f860 5159 {
2224a5fc 5160 /* Free the information from XListFonts. */
5835f860 5161 if (n_matching_fonts)
2224a5fc 5162 XFreeFontNames (font_names);
5835f860
RS
5163 return Qnil;
5164 }
dc6f92b8
JB
5165
5166 /* Do we need to create the table? */
5167 if (x_font_table_size == 0)
5168 {
5169 x_font_table_size = 16;
5170 x_font_table
2224a5fc
RS
5171 = (struct font_info *) xmalloc (x_font_table_size
5172 * sizeof (x_font_table[0]));
dc6f92b8
JB
5173 }
5174 /* Do we need to grow the table? */
5175 else if (n_fonts >= x_font_table_size)
5176 {
90e65f07 5177 x_font_table_size *= 2;
dc6f92b8 5178 x_font_table
2224a5fc
RS
5179 = (struct font_info *) xrealloc (x_font_table,
5180 (x_font_table_size
5181 * sizeof (x_font_table[0])));
dc6f92b8
JB
5182 }
5183
dff815ef 5184 x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
2224a5fc
RS
5185 bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1);
5186 f->display.x->font = x_font_table[n_fonts++].font = font;
dc6f92b8 5187 }
2224a5fc 5188
f676886a 5189 /* Now make the frame display the given font. */
c118dd06 5190 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 5191 {
f676886a
JB
5192 XSetFont (x_current_display, f->display.x->normal_gc,
5193 f->display.x->font->fid);
5194 XSetFont (x_current_display, f->display.x->reverse_gc,
5195 f->display.x->font->fid);
5196 XSetFont (x_current_display, f->display.x->cursor_gc,
5197 f->display.x->font->fid);
5198
a27f9f86 5199 frame_update_line_height (f);
0134a210 5200 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 5201 }
a27f9f86
RS
5202 else
5203 /* If we are setting a new frame's font for the first time,
5204 there are no faces yet, so this font's height is the line height. */
0cdd0c9f 5205 f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
dc6f92b8 5206
b5cf7a0e 5207 {
abdda982 5208 Lisp_Object lispy_name;
b5cf7a0e 5209
abdda982 5210 lispy_name = build_string (fontname);
b5cf7a0e 5211
2224a5fc 5212 /* Free the information from XListFonts. The data
b5cf7a0e 5213 we actually retain comes from XLoadQueryFont. */
2224a5fc 5214 XFreeFontNames (font_names);
b5cf7a0e
JB
5215
5216 return lispy_name;
5217 }
dc6f92b8 5218}
c118dd06 5219#else /* ! defined (HAVE_X11) */
f676886a
JB
5220x_new_font (f, newname)
5221 struct frame *f;
dc6f92b8
JB
5222 register char *newname;
5223{
5224 FONT_TYPE *temp;
5225 int mask;
5226
5227 temp = XGetFont (newname);
5228 if (temp == (FONT_TYPE *) 0)
5229 return 1;
5230
f676886a
JB
5231 if (f->display.x->font)
5232 XLoseFont (f->display.x->font);
dc6f92b8 5233
f676886a 5234 f->display.x->font = temp;
dc6f92b8 5235
c118dd06 5236 if (FRAME_X_WINDOW (f) != 0)
bc20ebbf 5237 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8
JB
5238
5239 return 0;
5240}
c118dd06 5241#endif /* ! defined (HAVE_X11) */
dc6f92b8 5242\f
43bca5d5 5243x_calc_absolute_position (f)
f676886a 5244 struct frame *f;
dc6f92b8
JB
5245{
5246#ifdef HAVE_X11
6dba1858
RS
5247 Window win, child;
5248 int win_x = 0, win_y = 0;
43bca5d5 5249 int flags = f->display.x->size_hint_flags;
6dba1858
RS
5250
5251 /* Find the position of the outside upper-left corner of
5252 the inner window, with respect to the outer window. */
5253 if (f->display.x->parent_desc != ROOT_WINDOW)
5254 {
5255 BLOCK_INPUT;
5256 XTranslateCoordinates (x_current_display,
5257
5258 /* From-window, to-window. */
5259 f->display.x->window_desc,
5260 f->display.x->parent_desc,
5261
5262 /* From-position, to-position. */
5263 0, 0, &win_x, &win_y,
5264
5265 /* Child of win. */
5266 &child);
5267 UNBLOCK_INPUT;
5268 }
5269
5270 /* Treat negative positions as relative to the leftmost bottommost
5271 position that fits on the screen. */
20f55f9a 5272 if (flags & XNegative)
31ea78fd 5273 f->display.x->left_pos = (x_screen_width
69388238 5274 - 2 * f->display.x->border_width - win_x
31ea78fd
JB
5275 - PIXEL_WIDTH (f)
5276 + f->display.x->left_pos);
dc6f92b8 5277
20f55f9a 5278 if (flags & YNegative)
31ea78fd 5279 f->display.x->top_pos = (x_screen_height
69388238 5280 - 2 * f->display.x->border_width - win_y
31ea78fd
JB
5281 - PIXEL_HEIGHT (f)
5282 + f->display.x->top_pos);
3a35ab44
RS
5283 /* The left_pos and top_pos
5284 are now relative to the top and left screen edges,
5285 so the flags should correspond. */
5286 f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
c118dd06 5287#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
5288 WINDOWINFO_TYPE parentinfo;
5289
c118dd06 5290 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
dc6f92b8 5291
f676886a
JB
5292 if (f->display.x->left_pos < 0)
5293 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
5294 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
dc6f92b8 5295
f676886a
JB
5296 if (f->display.x->top_pos < 0)
5297 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
5298 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
c118dd06 5299#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
5300}
5301
3a35ab44
RS
5302/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5303 to really change the position, and 0 when calling from
5304 x_make_frame_visible (in that case, XOFF and YOFF are the current
5305 position values). */
5306
dc05a16b 5307x_set_offset (f, xoff, yoff, change_gravity)
f676886a 5308 struct frame *f;
dc6f92b8 5309 register int xoff, yoff;
dc05a16b 5310 int change_gravity;
dc6f92b8 5311{
3a35ab44
RS
5312 if (change_gravity)
5313 {
5314 f->display.x->top_pos = yoff;
5315 f->display.x->left_pos = xoff;
5316 f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
5317 if (xoff < 0)
5318 f->display.x->size_hint_flags |= XNegative;
5319 if (yoff < 0)
5320 f->display.x->size_hint_flags |= YNegative;
5321 f->display.x->win_gravity = NorthWestGravity;
5322 }
43bca5d5 5323 x_calc_absolute_position (f);
dc6f92b8
JB
5324
5325 BLOCK_INPUT;
3a35ab44
RS
5326 x_wm_set_size_hint (f, 0, 0);
5327
3afe33e7
RS
5328#ifdef USE_X_TOOLKIT
5329 XMoveWindow (XDISPLAY XtWindow (f->display.x->widget),
5330 f->display.x->left_pos, f->display.x->top_pos);
5331#else /* not USE_X_TOOLKIT */
c118dd06 5332 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
f676886a 5333 f->display.x->left_pos, f->display.x->top_pos);
3afe33e7 5334#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5335 UNBLOCK_INPUT;
5336}
5337
bc20ebbf
FP
5338/* Call this to change the size of frame F's x-window.
5339 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5340 for this size change and subsequent size changes.
5341 Otherwise we leave the window gravity unchanged. */
dc6f92b8 5342
bc20ebbf 5343x_set_window_size (f, change_gravity, cols, rows)
f676886a 5344 struct frame *f;
bc20ebbf 5345 int change_gravity;
b1c884c3 5346 int cols, rows;
dc6f92b8
JB
5347{
5348 int pixelwidth, pixelheight;
5349 int mask;
dc6f92b8 5350
80fd1fe2
FP
5351#ifdef USE_X_TOOLKIT
5352 BLOCK_INPUT;
3a20653d
RS
5353 {
5354 /* The x and y position of the widget is clobbered by the
5355 call to XtSetValues within EmacsFrameSetCharSize.
5356 This is a real kludge, but I don't understand Xt so I can't
5357 figure out a correct fix. Can anyone else tell me? -- rms. */
5358 int xpos = f->display.x->widget->core.x;
5359 int ypos = f->display.x->widget->core.y;
5360 EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
5361 f->display.x->widget->core.x = xpos;
5362 f->display.x->widget->core.y = ypos;
5363 }
80fd1fe2
FP
5364 UNBLOCK_INPUT;
5365
5366#else /* not USE_X_TOOLKIT */
5367
dc6f92b8
JB
5368 BLOCK_INPUT;
5369
b1c884c3 5370 check_frame_size (f, &rows, &cols);
6dba1858
RS
5371 f->display.x->vertical_scroll_bar_extra
5372 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5373 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
5374 : 0);
f451eb13
JB
5375 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
5376 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8
JB
5377
5378#ifdef HAVE_X11
af31d76f
RS
5379 f->display.x->win_gravity = NorthWestGravity;
5380 x_wm_set_size_hint (f, 0, 0);
c118dd06 5381#endif /* ! defined (HAVE_X11) */
0cdd0c9f 5382 XSync (x_current_display, False);
c118dd06 5383 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
b1c884c3
JB
5384
5385 /* Now, strictly speaking, we can't be sure that this is accurate,
5386 but the window manager will get around to dealing with the size
5387 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
5388 ConfigureNotify event gets here.
5389
5390 We could just not bother storing any of this information here,
5391 and let the ConfigureNotify event set everything up, but that
5392 might be kind of confusing to the lisp code, since size changes
5393 wouldn't be reported in the frame parameters until some random
5394 point in the future when the ConfigureNotify event arrives. */
8922af5f 5395 change_frame_size (f, rows, cols, 0, 0);
b1c884c3
JB
5396 PIXEL_WIDTH (f) = pixelwidth;
5397 PIXEL_HEIGHT (f) = pixelheight;
5398
4d73d038
RS
5399 /* If cursor was outside the new size, mark it as off. */
5400 if (f->phys_cursor_y >= rows
5401 || f->phys_cursor_x >= cols)
5402 {
5403 f->phys_cursor_x = -1;
5404 f->phys_cursor_y = -1;
5405 }
5406
dbc4e1c1
JB
5407 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5408 receive in the ConfigureNotify event; if we get what we asked
5409 for, then the event won't cause the screen to become garbaged, so
5410 we have to make sure to do it here. */
5411 SET_FRAME_GARBAGED (f);
5412
dc6f92b8
JB
5413 XFlushQueue ();
5414 UNBLOCK_INPUT;
80fd1fe2 5415#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5416}
5417
5418#ifndef HAVE_X11
f676886a
JB
5419x_set_resize_hint (f)
5420 struct frame *f;
dc6f92b8 5421{
12ba150f
JB
5422 XSetResizeHint (FRAME_X_WINDOW (f),
5423 2 * f->display.x->internal_border_width,
f676886a 5424 2 * f->display.x->internal_border_width,
12ba150f 5425 FONT_WIDTH (f->display.x->font),
a27f9f86 5426 f->display.x->line_height);
dc6f92b8 5427}
c118dd06 5428#endif /* HAVE_X11 */
dc6f92b8 5429\f
f451eb13 5430/* Mouse warping, focus shifting, raising and lowering. */
dc6f92b8 5431
9b378208 5432void
f676886a
JB
5433x_set_mouse_position (f, x, y)
5434 struct frame *f;
dc6f92b8
JB
5435 int x, y;
5436{
5437 int pix_x, pix_y;
5438
12ba150f 5439 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
a27f9f86 5440 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->display.x->line_height / 2;
f451eb13
JB
5441
5442 if (pix_x < 0) pix_x = 0;
5443 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
5444
5445 if (pix_y < 0) pix_y = 0;
5446 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
5447
5448 BLOCK_INPUT;
dc6f92b8 5449
c118dd06 5450 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
dc6f92b8
JB
5451 UNBLOCK_INPUT;
5452}
5453
9b378208
RS
5454/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5455
5456void
5457x_set_mouse_pixel_position (f, pix_x, pix_y)
5458 struct frame *f;
5459 int pix_x, pix_y;
5460{
5461 BLOCK_INPUT;
5462
5463 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
5464 UNBLOCK_INPUT;
5465}
5466
dc6f92b8 5467#ifdef HAVE_X11
f676886a
JB
5468x_focus_on_frame (f)
5469 struct frame *f;
dc6f92b8 5470{
1fb20991 5471#if 0 /* This proves to be unpleasant. */
f676886a 5472 x_raise_frame (f);
1fb20991 5473#endif
6d4238f3
JB
5474#if 0
5475 /* I don't think that the ICCCM allows programs to do things like this
5476 without the interaction of the window manager. Whatever you end up
f676886a 5477 doing with this code, do it to x_unfocus_frame too. */
c118dd06 5478 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
dc6f92b8 5479 RevertToPointerRoot, CurrentTime);
c118dd06 5480#endif /* ! 0 */
dc6f92b8
JB
5481}
5482
f676886a
JB
5483x_unfocus_frame (f)
5484 struct frame *f;
dc6f92b8 5485{
6d4238f3 5486#if 0
f676886a
JB
5487 /* Look at the remarks in x_focus_on_frame. */
5488 if (x_focus_frame == f)
dc6f92b8
JB
5489 XSetInputFocus (x_current_display, PointerRoot,
5490 RevertToPointerRoot, CurrentTime);
c118dd06 5491#endif /* ! 0 */
dc6f92b8
JB
5492}
5493
c118dd06 5494#endif /* ! defined (HAVE_X11) */
dc6f92b8 5495
f676886a 5496/* Raise frame F. */
dc6f92b8 5497
f676886a
JB
5498x_raise_frame (f)
5499 struct frame *f;
dc6f92b8 5500{
3a88c238 5501 if (f->async_visible)
dc6f92b8
JB
5502 {
5503 BLOCK_INPUT;
3afe33e7
RS
5504#ifdef USE_X_TOOLKIT
5505 XRaiseWindow (XDISPLAY XtWindow (f->display.x->widget));
5506#else /* not USE_X_TOOLKIT */
c118dd06 5507 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
3afe33e7 5508#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5509 XFlushQueue ();
5510 UNBLOCK_INPUT;
5511 }
5512}
5513
f676886a 5514/* Lower frame F. */
dc6f92b8 5515
f676886a
JB
5516x_lower_frame (f)
5517 struct frame *f;
dc6f92b8 5518{
3a88c238 5519 if (f->async_visible)
dc6f92b8
JB
5520 {
5521 BLOCK_INPUT;
3afe33e7
RS
5522#ifdef USE_X_TOOLKIT
5523 XLowerWindow (XDISPLAY XtWindow (f->display.x->widget));
5524#else /* not USE_X_TOOLKIT */
c118dd06 5525 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
3afe33e7 5526#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5527 XFlushQueue ();
5528 UNBLOCK_INPUT;
5529 }
5530}
5531
dbc4e1c1
JB
5532static void
5533XTframe_raise_lower (f, raise)
5534 FRAME_PTR f;
5535 int raise;
5536{
5537 if (raise)
5538 x_raise_frame (f);
5539 else
5540 x_lower_frame (f);
5541}
5542
5543
fd13dbb2
RS
5544/* Change from withdrawn state to mapped state,
5545 or deiconify. */
dc6f92b8 5546
f676886a
JB
5547x_make_frame_visible (f)
5548 struct frame *f;
dc6f92b8
JB
5549{
5550 int mask;
5551
dc6f92b8 5552 BLOCK_INPUT;
dc6f92b8 5553
f676886a 5554 if (! FRAME_VISIBLE_P (f))
90e65f07
JB
5555 {
5556#ifdef HAVE_X11
af31d76f 5557#ifndef USE_X_TOOLKIT
fd13dbb2
RS
5558 if (! FRAME_ICONIFIED_P (f))
5559 x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0);
af31d76f 5560#endif
dc05a16b 5561
90e65f07 5562 if (! EQ (Vx_no_window_manager, Qt))
f676886a 5563 x_wm_set_window_state (f, NormalState);
3afe33e7 5564#ifdef USE_X_TOOLKIT
d7a38a2e
RS
5565 /* This was XtPopup, but that did nothing for an iconified frame. */
5566 XtMapWidget (f->display.x->widget);
3afe33e7 5567#else /* not USE_X_TOOLKIT */
c118dd06 5568 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
3afe33e7 5569#endif /* not USE_X_TOOLKIT */
0134a210
RS
5570#if 0 /* This seems to bring back scroll bars in the wrong places
5571 if the window configuration has changed. They seem
5572 to come back ok without this. */
ab648270 5573 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
c118dd06 5574 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
0134a210 5575#endif
c118dd06
JB
5576#else /* ! defined (HAVE_X11) */
5577 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
f676886a
JB
5578 if (f->display.x->icon_desc != 0)
5579 XUnmapWindow (f->display.x->icon_desc);
dc6f92b8 5580
90e65f07 5581 /* Handled by the MapNotify event for X11 */
3a88c238
JB
5582 f->async_visible = 1;
5583 f->async_iconified = 0;
dc6f92b8 5584
f676886a 5585 /* NOTE: this may cause problems for the first frame. */
90e65f07 5586 XTcursor_to (0, 0);
c118dd06 5587#endif /* ! defined (HAVE_X11) */
90e65f07 5588 }
dc6f92b8 5589
dc6f92b8 5590 XFlushQueue ();
90e65f07 5591
dc6f92b8 5592 UNBLOCK_INPUT;
0dacf791
RS
5593
5594 /* Synchronize to ensure Emacs knows the frame is visible
5595 before we do anything else. We do this loop with input not blocked
5596 so that incoming events are handled. */
5597 {
5598 Lisp_Object frame;
2a6cf806 5599 int one_in_four = 0;
0dacf791
RS
5600 XSET (frame, Lisp_Frame, f);
5601 while (! f->async_visible)
2a6cf806
RS
5602 {
5603 x_sync (frame);
5604 /* On HPUX on the HP800, the sleep is needed sometimes. */
5605 if ((one_in_four & 3) == 0)
5606 {
5607#ifdef EMACS_HAS_USECS
5608 Fsleep_for (make_number (1), make_number (0));
5609#else
5610 Fsleep_for (make_number (0), make_number (250));
5611#endif
5612 }
5613 one_in_four++;
5614 }
0dacf791
RS
5615 FRAME_SAMPLE_VISIBILITY (f);
5616 }
dc6f92b8
JB
5617}
5618
5619/* Change from mapped state to withdrawn state. */
5620
f676886a
JB
5621x_make_frame_invisible (f)
5622 struct frame *f;
dc6f92b8
JB
5623{
5624 int mask;
546e6d5b
RS
5625 Window window;
5626
5627#ifdef USE_X_TOOLKIT
5628 /* Use the frame's outermost window, not the one we normally draw on. */
5629 window = XtWindow (f->display.x->widget);
5630#else /* not USE_X_TOOLKIT */
5631 window = FRAME_X_WINDOW (f);
5632#endif /* not USE_X_TOOLKIT */
dc6f92b8 5633
9319ae23
RS
5634 /* Don't keep the highlight on an invisible frame. */
5635 if (x_highlight_frame == f)
5636 x_highlight_frame = 0;
5637
5627c40e 5638#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 5639 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 5640 return;
5627c40e 5641#endif
dc6f92b8
JB
5642
5643 BLOCK_INPUT;
c118dd06 5644
af31d76f
RS
5645 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5646 that the current position of the window is user-specified, rather than
5647 program-specified, so that when the window is mapped again, it will be
5648 placed at the same location, without forcing the user to position it
5649 by hand again (they have already done that once for this window.) */
5650 x_wm_set_size_hint (f, 0, 1);
5651
c118dd06
JB
5652#ifdef HAVE_X11R4
5653
546e6d5b 5654 if (! XWithdrawWindow (x_current_display, window,
c118dd06
JB
5655 DefaultScreen (x_current_display)))
5656 {
5657 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 5658 error ("Can't notify window manager of window withdrawal");
c118dd06 5659 }
c118dd06 5660#else /* ! defined (HAVE_X11R4) */
dc6f92b8 5661#ifdef HAVE_X11
16bd92ea 5662
c118dd06 5663 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
5664 if (! EQ (Vx_no_window_manager, Qt))
5665 {
16bd92ea 5666 XEvent unmap;
dc6f92b8 5667
16bd92ea 5668 unmap.xunmap.type = UnmapNotify;
546e6d5b 5669 unmap.xunmap.window = window;
16bd92ea
JB
5670 unmap.xunmap.event = DefaultRootWindow (x_current_display);
5671 unmap.xunmap.from_configure = False;
5672 if (! XSendEvent (x_current_display,
5673 DefaultRootWindow (x_current_display),
5674 False,
5675 SubstructureRedirectMask|SubstructureNotifyMask,
5676 &unmap))
5677 {
5678 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 5679 error ("Can't notify window manager of withdrawal");
16bd92ea 5680 }
dc6f92b8
JB
5681 }
5682
16bd92ea 5683 /* Unmap the window ourselves. Cheeky! */
546e6d5b 5684 XUnmapWindow (x_current_display, window);
c118dd06 5685#else /* ! defined (HAVE_X11) */
dc6f92b8 5686
c118dd06 5687 XUnmapWindow (FRAME_X_WINDOW (f));
f676886a 5688 if (f->display.x->icon_desc != 0)
c118dd06
JB
5689 XUnmapWindow (f->display.x->icon_desc);
5690
5691#endif /* ! defined (HAVE_X11) */
5692#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 5693
5627c40e
RS
5694 /* We can't distinguish this from iconification
5695 just by the event that we get from the server.
5696 So we can't win using the usual strategy of letting
5697 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5698 and synchronize with the server to make sure we agree. */
5699 f->visible = 0;
5700 FRAME_ICONIFIED_P (f) = 0;
5701 f->async_visible = 0;
5702 f->async_iconified = 0;
5703
5704 x_sync ();
5705
dc6f92b8
JB
5706 UNBLOCK_INPUT;
5707}
5708
dc6f92b8
JB
5709/* Change window state from mapped to iconified. */
5710
f676886a
JB
5711x_iconify_frame (f)
5712 struct frame *f;
dc6f92b8
JB
5713{
5714 int mask;
3afe33e7 5715 int result;
dc6f92b8 5716
9319ae23
RS
5717 /* Don't keep the highlight on an invisible frame. */
5718 if (x_highlight_frame == f)
5719 x_highlight_frame = 0;
5720
3a88c238 5721 if (f->async_iconified)
dc6f92b8
JB
5722 return;
5723
3afe33e7
RS
5724#ifdef USE_X_TOOLKIT
5725 BLOCK_INPUT;
546e6d5b
RS
5726
5727 if (! FRAME_VISIBLE_P (f))
5728 {
5729 if (! EQ (Vx_no_window_manager, Qt))
5730 x_wm_set_window_state (f, IconicState);
5731 /* This was XtPopup, but that did nothing for an iconified frame. */
5732 XtMapWidget (f->display.x->widget);
5733 UNBLOCK_INPUT;
5734 return;
5735 }
5736
3afe33e7 5737 result = XIconifyWindow (x_current_display,
bc20ebbf 5738 XtWindow (f->display.x->widget),
3afe33e7
RS
5739 DefaultScreen (x_current_display));
5740 UNBLOCK_INPUT;
5741
5742 if (!result)
546e6d5b 5743 error ("Can't notify window manager of iconification");
3afe33e7
RS
5744
5745 f->async_iconified = 1;
8c002a25
KH
5746
5747 BLOCK_INPUT;
5748 XFlushQueue ();
5749 UNBLOCK_INPUT;
3afe33e7
RS
5750#else /* not USE_X_TOOLKIT */
5751
dc6f92b8
JB
5752 BLOCK_INPUT;
5753
5754#ifdef HAVE_X11
fd13dbb2
RS
5755 /* Make sure the X server knows where the window should be positioned,
5756 in case the user deiconifies with the window manager. */
5757 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
5758 x_set_offset (f, f->display.x->left_pos, f->display.x->top_pos, 0);
5759
16bd92ea
JB
5760 /* Since we don't know which revision of X we're running, we'll use both
5761 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5762
5763 /* X11R4: send a ClientMessage to the window manager using the
5764 WM_CHANGE_STATE type. */
5765 {
5766 XEvent message;
5767
c118dd06 5768 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea
JB
5769 message.xclient.type = ClientMessage;
5770 message.xclient.message_type = Xatom_wm_change_state;
5771 message.xclient.format = 32;
5772 message.xclient.data.l[0] = IconicState;
5773
5774 if (! XSendEvent (x_current_display,
5775 DefaultRootWindow (x_current_display),
5776 False,
5777 SubstructureRedirectMask | SubstructureNotifyMask,
5778 &message))
dc6f92b8
JB
5779 {
5780 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 5781 error ("Can't notify window manager of iconification");
dc6f92b8 5782 }
16bd92ea 5783 }
dc6f92b8 5784
16bd92ea
JB
5785 /* X11R3: set the initial_state field of the window manager hints to
5786 IconicState. */
5787 x_wm_set_window_state (f, IconicState);
dc6f92b8 5788
a9c00105
RS
5789 if (!FRAME_VISIBLE_P (f))
5790 {
5791 /* If the frame was withdrawn, before, we must map it. */
5792 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
0134a210 5793#if 0 /* We don't have subwindows in the icon. */
a9c00105
RS
5794 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5795 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
0134a210 5796#endif
a9c00105
RS
5797 }
5798
3a88c238 5799 f->async_iconified = 1;
c118dd06
JB
5800#else /* ! defined (HAVE_X11) */
5801 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
dc6f92b8 5802
3a88c238 5803 f->async_visible = 0; /* Handled in the UnMap event for X11. */
f676886a 5804 if (f->display.x->icon_desc != 0)
dc6f92b8 5805 {
f676886a
JB
5806 XMapWindow (XDISPLAY f->display.x->icon_desc);
5807 refreshicon (f);
dc6f92b8 5808 }
c118dd06 5809#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
5810
5811 XFlushQueue ();
5812 UNBLOCK_INPUT;
8c002a25 5813#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5814}
5815
c0ff3fab 5816/* Destroy the X window of frame F. */
dc6f92b8 5817
c0ff3fab 5818x_destroy_window (f)
f676886a 5819 struct frame *f;
dc6f92b8 5820{
dc6f92b8 5821 BLOCK_INPUT;
c0ff3fab
JB
5822
5823 if (f->display.x->icon_desc != 0)
5824 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
5825 XDestroyWindow (XDISPLAY f->display.x->window_desc);
3afe33e7
RS
5826#ifdef USE_X_TOOLKIT
5827 XtDestroyWidget (f->display.x->widget);
9d7e2e3e 5828 free_frame_menubar (f);
3afe33e7
RS
5829#endif /* USE_X_TOOLKIT */
5830
07e34cb0 5831 free_frame_faces (f);
dc6f92b8 5832 XFlushQueue ();
dc6f92b8 5833
9ac0d9e0 5834 xfree (f->display.x);
c0ff3fab 5835 f->display.x = 0;
f676886a
JB
5836 if (f == x_focus_frame)
5837 x_focus_frame = 0;
5838 if (f == x_highlight_frame)
5839 x_highlight_frame = 0;
c0ff3fab 5840
0134a210 5841 if (f == mouse_face_mouse_frame)
dc05a16b 5842 {
3b506386
KH
5843 mouse_face_beg_row = mouse_face_beg_col = -1;
5844 mouse_face_end_row = mouse_face_end_col = -1;
dc05a16b
RS
5845 mouse_face_window = Qnil;
5846 }
0134a210 5847
c0ff3fab 5848 UNBLOCK_INPUT;
dc6f92b8
JB
5849}
5850\f
f451eb13
JB
5851/* Manage event queues for X10. */
5852
dc6f92b8
JB
5853#ifndef HAVE_X11
5854
5855/* Manage event queues.
5856
5857 This code is only used by the X10 support.
5858
5859 We cannot leave events in the X queue and get them when we are ready
5860 because X does not provide a subroutine to get only a certain kind
5861 of event but not block if there are no queued events of that kind.
5862
5863 Therefore, we must examine events as they come in and copy events
5864 of certain kinds into our private queues.
5865
5866 All ExposeRegion events are put in x_expose_queue.
69388238 5867 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
dc6f92b8
JB
5868
5869
5870/* Write the event *P_XREP into the event queue *QUEUE.
5871 If the queue is full, do nothing, but return nonzero. */
5872
5873int
5874enqueue_event (p_xrep, queue)
5875 register XEvent *p_xrep;
5876 register struct event_queue *queue;
5877{
5878 int newindex = queue->windex + 1;
5879 if (newindex == EVENT_BUFFER_SIZE)
5880 newindex = 0;
5881 if (newindex == queue->rindex)
5882 return -1;
5883 queue->xrep[queue->windex] = *p_xrep;
5884 queue->windex = newindex;
5885 return 0;
5886}
5887
5888/* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5889 If *QUEUE is empty, do nothing and return 0. */
5890
5891int
5892dequeue_event (p_xrep, queue)
5893 register XEvent *p_xrep;
5894 register struct event_queue *queue;
5895{
5896 if (queue->windex == queue->rindex)
5897 return 0;
5898 *p_xrep = queue->xrep[queue->rindex++];
5899 if (queue->rindex == EVENT_BUFFER_SIZE)
5900 queue->rindex = 0;
5901 return 1;
5902}
5903
5904/* Return the number of events buffered in *QUEUE. */
5905
5906int
5907queue_event_count (queue)
5908 register struct event_queue *queue;
5909{
5910 int tem = queue->windex - queue->rindex;
5911 if (tem >= 0)
5912 return tem;
5913 return EVENT_BUFFER_SIZE + tem;
5914}
5915
5916/* Return nonzero if mouse input is pending. */
5917
5918int
5919mouse_event_pending_p ()
5920{
5921 return queue_event_count (&x_mouse_queue);
5922}
c118dd06 5923#endif /* HAVE_X11 */
dc6f92b8 5924\f
f451eb13
JB
5925/* Setting window manager hints. */
5926
dc6f92b8
JB
5927#ifdef HAVE_X11
5928
af31d76f
RS
5929/* Set the normal size hints for the window manager, for frame F.
5930 FLAGS is the flags word to use--or 0 meaning preserve the flags
5931 that the window now has.
5932 If USER_POSITION is nonzero, we set the USPosition
5933 flag (this is useful when FLAGS is 0). */
6dba1858 5934
af31d76f 5935x_wm_set_size_hint (f, flags, user_position)
f676886a 5936 struct frame *f;
af31d76f
RS
5937 long flags;
5938 int user_position;
dc6f92b8
JB
5939{
5940 XSizeHints size_hints;
3afe33e7
RS
5941
5942#ifdef USE_X_TOOLKIT
7e4f2521
FP
5943 Arg al[2];
5944 int ac = 0;
5945 Dimension widget_width, widget_height;
bc20ebbf 5946 Window window = XtWindow (f->display.x->widget);
3afe33e7 5947#else /* not USE_X_TOOLKIT */
c118dd06 5948 Window window = FRAME_X_WINDOW (f);
3afe33e7 5949#endif /* not USE_X_TOOLKIT */
dc6f92b8 5950
b72a58fd
RS
5951 /* Setting PMaxSize caused various problems. */
5952 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 5953
f676886a
JB
5954 flexlines = f->height;
5955
5956 size_hints.x = f->display.x->left_pos;
5957 size_hints.y = f->display.x->top_pos;
7553a6b7 5958
7e4f2521
FP
5959#ifdef USE_X_TOOLKIT
5960 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5961 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5962 XtGetValues (f->display.x->column_widget, al, ac);
5963 size_hints.height = widget_height;
5964 size_hints.width = widget_width;
5965#else /* not USE_X_TOOLKIT */
f676886a
JB
5966 size_hints.height = PIXEL_HEIGHT (f);
5967 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 5968#endif /* not USE_X_TOOLKIT */
7553a6b7 5969
f676886a 5970 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
a27f9f86 5971 size_hints.height_inc = f->display.x->line_height;
7553a6b7
RS
5972 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
5973 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 5974
b1c884c3 5975 {
b0342f17 5976 int base_width, base_height;
0134a210 5977 int min_rows = 0, min_cols = 0;
b0342f17 5978
f451eb13
JB
5979 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5980 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 5981
0134a210 5982 check_frame_size (f, &min_rows, &min_cols);
b0342f17 5983
0134a210
RS
5984 /* The window manager uses the base width hints to calculate the
5985 current number of rows and columns in the frame while
5986 resizing; min_width and min_height aren't useful for this
5987 purpose, since they might not give the dimensions for a
5988 zero-row, zero-column frame.
5989
5990 We use the base_width and base_height members if we have
5991 them; otherwise, we set the min_width and min_height members
5992 to the size for a zero x zero frame. */
b0342f17
JB
5993
5994#ifdef HAVE_X11R4
0134a210
RS
5995 size_hints.flags |= PBaseSize;
5996 size_hints.base_width = base_width;
5997 size_hints.base_height = base_height;
5998 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5999 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 6000#else
0134a210
RS
6001 size_hints.min_width = base_width;
6002 size_hints.min_height = base_height;
b0342f17 6003#endif
b1c884c3 6004 }
dc6f92b8 6005
af31d76f
RS
6006 if (flags)
6007 size_hints.flags |= flags;
dc6f92b8
JB
6008 else
6009 {
6010 XSizeHints hints; /* Sometimes I hate X Windows... */
af31d76f
RS
6011 long supplied_return;
6012 int value;
6013
6014#ifdef HAVE_X11R4
6015 value = XGetWMNormalHints (x_current_display, window, &hints,
6016 &supplied_return);
6017#else
6018 value = XGetNormalHints (x_current_display, window, &hints);
6019#endif
dc6f92b8 6020
af31d76f 6021 if (value == 0)
82ee0df4 6022 hints.flags = 0;
dc6f92b8
JB
6023 if (hints.flags & PSize)
6024 size_hints.flags |= PSize;
6025 if (hints.flags & PPosition)
6026 size_hints.flags |= PPosition;
6027 if (hints.flags & USPosition)
6028 size_hints.flags |= USPosition;
6029 if (hints.flags & USSize)
6030 size_hints.flags |= USSize;
6031 }
0134a210 6032
af31d76f 6033#ifdef PWinGravity
dc05a16b 6034 size_hints.win_gravity = f->display.x->win_gravity;
af31d76f 6035 size_hints.flags |= PWinGravity;
dc05a16b 6036
af31d76f 6037 if (user_position)
6dba1858 6038 {
af31d76f
RS
6039 size_hints.flags &= ~ PPosition;
6040 size_hints.flags |= USPosition;
6dba1858 6041 }
2554751d 6042#endif /* PWinGravity */
6dba1858 6043
b0342f17
JB
6044#ifdef HAVE_X11R4
6045 XSetWMNormalHints (x_current_display, window, &size_hints);
6046#else
dc6f92b8 6047 XSetNormalHints (x_current_display, window, &size_hints);
b0342f17 6048#endif
dc6f92b8
JB
6049}
6050
6051/* Used for IconicState or NormalState */
f676886a
JB
6052x_wm_set_window_state (f, state)
6053 struct frame *f;
dc6f92b8
JB
6054 int state;
6055{
3afe33e7 6056#ifdef USE_X_TOOLKIT
546e6d5b
RS
6057 Arg al[1];
6058
6059 XtSetArg (al[0], XtNinitialState, state);
6060 XtSetValues (f->display.x->widget, al, 1);
3afe33e7 6061#else /* not USE_X_TOOLKIT */
c118dd06 6062 Window window = FRAME_X_WINDOW (f);
dc6f92b8 6063
16bd92ea
JB
6064 f->display.x->wm_hints.flags |= StateHint;
6065 f->display.x->wm_hints.initial_state = state;
b1c884c3 6066
16bd92ea 6067 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
546e6d5b 6068#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
6069}
6070
f676886a
JB
6071x_wm_set_icon_pixmap (f, icon_pixmap)
6072 struct frame *f;
dc6f92b8
JB
6073 Pixmap icon_pixmap;
6074{
75231bad
RS
6075#ifdef USE_X_TOOLKIT
6076 Window window = XtWindow (f->display.x->widget);
6077#else
c118dd06 6078 Window window = FRAME_X_WINDOW (f);
75231bad 6079#endif
dc6f92b8 6080
dbc4e1c1
JB
6081 if (icon_pixmap)
6082 {
6083 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
6084 f->display.x->wm_hints.flags |= IconPixmapHint;
6085 }
6086 else
6087 f->display.x->wm_hints.flags &= ~IconPixmapHint;
b1c884c3 6088
16bd92ea 6089 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
6090}
6091
f676886a
JB
6092x_wm_set_icon_position (f, icon_x, icon_y)
6093 struct frame *f;
dc6f92b8
JB
6094 int icon_x, icon_y;
6095{
75231bad
RS
6096#ifdef USE_X_TOOLKIT
6097 Window window = XtWindow (f->display.x->widget);
6098#else
c118dd06 6099 Window window = FRAME_X_WINDOW (f);
75231bad 6100#endif
dc6f92b8 6101
16bd92ea
JB
6102 f->display.x->wm_hints.flags |= IconPositionHint;
6103 f->display.x->wm_hints.icon_x = icon_x;
6104 f->display.x->wm_hints.icon_y = icon_y;
b1c884c3 6105
16bd92ea 6106 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
6107}
6108
6109\f
f451eb13
JB
6110/* Initialization. */
6111
3afe33e7
RS
6112#ifdef USE_X_TOOLKIT
6113static XrmOptionDescRec emacs_options[] = {
6114 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
6115 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
6116
6117 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6118 XrmoptionSepArg, NULL},
6119 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
6120
6121 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
6122 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
6123 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
6124 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
6125 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
6126 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
6127 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
6128};
6129#endif /* USE_X_TOOLKIT */
6130
dc6f92b8 6131void
1f8255f2 6132x_term_init (display_name, xrm_option, resource_name)
dc6f92b8 6133 char *display_name;
1f8255f2
RS
6134 char *xrm_option;
6135 char *resource_name;
dc6f92b8 6136{
f676886a 6137 Lisp_Object frame;
dc6f92b8 6138 char *defaultvalue;
3afe33e7
RS
6139 int argc = 0;
6140 char** argv = 0;
041b69ac 6141#ifndef F_SETOWN_BUG
dc6f92b8
JB
6142#ifdef F_SETOWN
6143 extern int old_fcntl_owner;
c118dd06 6144#endif /* ! defined (F_SETOWN) */
041b69ac 6145#endif /* F_SETOWN_BUG */
6d4238f3 6146
ef2a22d0
RS
6147#ifdef X_IO_BUG
6148 x_noop_count = 0;
6149#endif
6150
f676886a 6151 x_focus_frame = x_highlight_frame = 0;
dc6f92b8 6152
3afe33e7 6153#ifdef USE_X_TOOLKIT
1f8255f2
RS
6154 argv = (char **) XtMalloc (7 * sizeof (char *));
6155 argv[0] = "";
6156 argv[1] = "-display";
6157 argv[2] = display_name;
6158 argv[3] = "-name";
6159 /* Usually `emacs', but not always. */
6160 argv[4] = resource_name;
c2df547c 6161 argc = 5;
1f8255f2
RS
6162 if (xrm_option)
6163 {
6164 argv[argc++] = "-xrm";
6165 argv[argc++] = xrm_option;
6166 }
3afe33e7 6167 Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs",
bc20ebbf 6168 emacs_options, XtNumber (emacs_options),
3afe33e7
RS
6169 &argc, argv,
6170 NULL, NULL, 0);
983f76b8 6171 XtFree ((char *)argv);
3afe33e7
RS
6172 x_current_display = XtDisplay (Xt_app_shell);
6173
6174#else /* not USE_X_TOOLKIT */
dc6f92b8 6175 x_current_display = XOpenDisplay (display_name);
3afe33e7 6176#endif /* not USE_X_TOOLKIT */
dc6f92b8 6177 if (x_current_display == 0)
041b69ac
JB
6178 fatal ("X server %s not responding.\n\
6179Check the DISPLAY environment variable or use \"-d\"\n",
dc6f92b8
JB
6180 display_name);
6181
6182#ifdef HAVE_X11
6183 {
dc6f92b8
JB
6184#if 0
6185 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 6186#endif /* ! 0 */
59653951 6187 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
becadff8 6188 + XSTRING (Vsystem_name)->size
60fb3ee1 6189 + 2);
becadff8
KH
6190 sprintf (x_id_name, "%s@%s",
6191 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
dc6f92b8 6192 }
28430d3c
JB
6193
6194 /* Figure out which modifier bits mean what. */
6195 x_find_modifier_meanings ();
f451eb13 6196
ab648270 6197 /* Get the scroll bar cursor. */
d56a553a
RS
6198 x_vertical_scroll_bar_cursor
6199 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
f451eb13 6200
d56a553a 6201#if 0
28430d3c
JB
6202 /* Watch for PropertyNotify events on the root window; we use them
6203 to figure out when to invalidate our cache of the cut buffers. */
6204 x_watch_cut_buffer_cache ();
d56a553a 6205#endif
28430d3c 6206
a4fc7360 6207 if (ConnectionNumber (x_current_display) != 0)
61c3ce62
RS
6208 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display));
6209 change_input_fd (ConnectionNumber (x_current_display));
6d4238f3 6210
c118dd06 6211#endif /* ! defined (HAVE_X11) */
dc6f92b8 6212
041b69ac 6213#ifndef F_SETOWN_BUG
dc6f92b8 6214#ifdef F_SETOWN
61c3ce62 6215 old_fcntl_owner = fcntl (ConnectionNumber (x_current_display), F_GETOWN, 0);
dc6f92b8 6216#ifdef F_SETOWN_SOCK_NEG
61c3ce62
RS
6217 /* stdin is a socket here */
6218 fcntl (ConnectionNumber (x_current_display), F_SETOWN, -getpid ());
c118dd06 6219#else /* ! defined (F_SETOWN_SOCK_NEG) */
61c3ce62 6220 fcntl (ConnectionNumber (x_current_display), F_SETOWN, getpid ());
c118dd06
JB
6221#endif /* ! defined (F_SETOWN_SOCK_NEG) */
6222#endif /* ! defined (F_SETOWN) */
041b69ac 6223#endif /* F_SETOWN_BUG */
dc6f92b8
JB
6224
6225#ifdef SIGIO
6226 init_sigio ();
c118dd06 6227#endif /* ! defined (SIGIO) */
dc6f92b8 6228
dc6f92b8
JB
6229 expose_all_windows = 0;
6230
f676886a 6231 clear_frame_hook = XTclear_frame;
dc6f92b8
JB
6232 clear_end_of_line_hook = XTclear_end_of_line;
6233 ins_del_lines_hook = XTins_del_lines;
6234 change_line_highlight_hook = XTchange_line_highlight;
6235 insert_glyphs_hook = XTinsert_glyphs;
6236 write_glyphs_hook = XTwrite_glyphs;
6237 delete_glyphs_hook = XTdelete_glyphs;
6238 ring_bell_hook = XTring_bell;
6239 reset_terminal_modes_hook = XTreset_terminal_modes;
6240 set_terminal_modes_hook = XTset_terminal_modes;
6241 update_begin_hook = XTupdate_begin;
6242 update_end_hook = XTupdate_end;
6243 set_terminal_window_hook = XTset_terminal_window;
6244 read_socket_hook = XTread_socket;
b8009dd1 6245 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8
JB
6246 cursor_to_hook = XTcursor_to;
6247 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 6248 mouse_position_hook = XTmouse_position;
f451eb13 6249 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 6250 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
6251 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
6252 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
6253 redeem_scroll_bar_hook = XTredeem_scroll_bar;
6254 judge_scroll_bars_hook = XTjudge_scroll_bars;
dc6f92b8 6255
f676886a 6256 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
6257 char_ins_del_ok = 0; /* just as fast to write the line */
6258 line_ins_del_ok = 1; /* we'll just blt 'em */
6259 fast_clear_end_of_line = 1; /* X does this well */
f676886a 6260 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
6261 off the bottom */
6262 baud_rate = 19200;
6263
b30b24cb
RS
6264 /* Try to use interrupt input; if we can't, then start polling. */
6265 Fset_input_mode (Qt, Qnil, Qt, Qnil);
6266
c118dd06
JB
6267 /* Note that there is no real way portable across R3/R4 to get the
6268 original error handler. */
6269 XHandleError (x_error_quitter);
8922af5f 6270 XHandleIOError (x_io_error_quitter);
dc6f92b8
JB
6271
6272 /* Disable Window Change signals; they are handled by X events. */
6273#ifdef SIGWINCH
6274 signal (SIGWINCH, SIG_DFL);
c118dd06 6275#endif /* ! defined (SIGWINCH) */
dc6f92b8 6276
c118dd06 6277 signal (SIGPIPE, x_connection_closed);
dc6f92b8 6278}
55123275
JB
6279
6280void
6281syms_of_xterm ()
6282{
ab648270 6283 staticpro (&last_mouse_scroll_bar);
e53cb100 6284 last_mouse_scroll_bar = Qnil;
b8009dd1
RS
6285 staticpro (&mouse_face_window);
6286 mouse_face_window = Qnil;
55123275 6287}
c118dd06
JB
6288#endif /* ! defined (HAVE_X11) */
6289#endif /* ! defined (HAVE_X_WINDOWS) */