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