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