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