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